09.内部类

什么是内部类?

  • 概念:在一个类的内部再定义一个完整的类。

  • 特点:

    • 编译之后可以生成独立的字节码文件。

    • 内部类可以直接访问外部类的私有成员,而不破坏封装。

    • 可为外部类提供必要的内部功能组件。

      • package Inner;
        
        // 身 体
        public class Test01 {
            private String name ;//私有成员变量
            public static void main(String[] args) {
            }
                // 头 部
                class Header{ // 内部类
                    public void show(){
                        System.out.println(name);
                    }
                }
        }
        

成员内部类

  • 在类的内部定义,与实例变量、实例方法同级别的类。

  • 外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象

    • Outer out = new Outer();

    • Inner in = out.new Inner();

    • package Inner;
      
      import Inner.Outer.Inner;
      
      public class TestOuter {
          public static void main(String[] args) {
      //        // 1.创建外部类对象
      //        Outer outer = new Outer();
      //        // 2.创建内部类对象
      //        Inner inner = outer.new Inner();
              // 一步到位
              Inner inner = new Outer().new Inner();
              inner.show();
          }
      }
      
      package Inner;
      
      public class Outer {
          // 实例变量
          private String name = "张三";
          private int age = 20;
          // 内部类
          class Inner{
              private String address = "北京";
              private String phone = "110";
      
              // 方法
              public void show(){
                  // 打印外部类的属性
                  System.out.println(name);
                  System.out.println(age);
      //            打印内部类的属性
                  System.out.println(address);
                  System.out.println(phone);
              }
          }
      }
      
  • 当外部类、内部类存在重名属性是,会优先访问内部类属性。

    • package Inner;
      
      public class Outer {
          // 实例变量
          private String name = "张三";
          private int age = 20;
          // 内部类
          class Inner{
              // 属性和外部类属性相同,优先访问内部类属性
              private  String name = "李四";
              private String address = "北京";
              private String phone = "110";
      
              // 方法
              public void show(){
                  // 打印外部类的属性
                  System.out.println(name);//输出:李四
                  // 打印外部类属性:Outer.this.。。。
                  System.out.println(Outer.this.name);//输出:张三
                  System.out.println(age);
      //            打印内部类的属性
                  System.out.println(address);
                  System.out.println(phone);
              }
          }
      }
      
  • 成员内部类不能调用静态成员

    • package Inner;
      
      public class Outer {
      
      //    // 内部类
          class Inner{
      
      //        private static String name = "中国";//内部类不能包含静态成员
              private final static String country = "中国"; // 特殊情况
      
      
          }
      }
      

静态内部类

  • 不依赖外部类对象,可以直接创建或通过类名访问,可声明静态成员。

  • 只能直接访问外部类的静态成员(实例成员需实例化外部类对象)

    • Outer.Inner = new Outer.Inner();
      Outer.Inner.show();
      
    • package staticInner;
      
      public class TestOuter {
          public static void main(String[] args) {
              // 直接创建内部类对象
              Outer.Inner inner = new Outer.Inner();
              //调用方法
              inner.show();
          }
      }
      
      package staticInner;
      
      // 外部类
      public class Outer {
          private String name = "xxx";
          private int age = 18;
      
          // 静态内部类,和外部类相同
          static class Inner{
              private String address = "上海";
              private String phone = "111";
              // 静态成员
              private static int count = 1000 ;
      
              public void show(){
                  //调用外部类的属性:
                    // 1.先创建外部类对象
                  Outer outer = new Outer();
                    // 2.调用外部类对象的属性
                  System.out.println(outer.age);
                  System.out.println(outer.name);
                  // 调用静态内部类属性
                  System.out.println(address);
                  System.out.println(phone);
                  // 调用静态内部类的静态属性
                  System.out.println(Inner.count);
              }
          }
      }
      

局部内部类

  • 定义在外部类方法中,作用范围和创建对象范围仅限于当前方法。

  • 局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final。

  • 限制类的适用范围(只能在当前方法中使用)

    • package part;
      
      public class TestOuter {
          public static void main(String[] args) {
              Outer outer = new Outer();
              outer.show();
          }
      }
      
      package part;
      
      // 外部类
      public class Outer {
          private String name = "刘德华";
          private int age = 35 ;
          public void show(){
              // 定义局部变量
              String address = "深圳";
      
              // 局部内部类:注意不能加任何访问修饰符
              class Inner{
                  private String phone = "123456";
                  private String email = "123456@qq.com";
      
                  public void show2(){
                      // 访问外部类的属性
                      System.out.println(name);// 也可以写Outer.this.name
                      System.out.println(age); // 也可以写Outer.this.age
                      // 访问内部类属性
                      System.out.println(phone); // 也可以写this.phone
                      System.out.println(email);// 也可以写this.email
                      // 访问局部变量,从JDK1.7开始,要求变量必须是常量final,而JDK1.8之后自动添加final。
                      System.out.println(address);
                  }
      
              }
              // 创建局部内部类对象
              Inner inner = new Inner();
              inner.show2();
          }
      }
      

匿名内部类

  • 没有类名的局部内部类(一切特征都与局部内部类相同)。

  • 必须继承一个父类或者实现一个接口。

    • package anonymous;
      
      public class TestUsb {
          public static void main(String[] args) {
              // 创建接口类型的变量
              /*
              Usb usb = new Mouse();
              usb.service();
               */
              class Fan implements Usb{
      
                  @Override
                  public void service() {
                      System.out.println("连接电脑成功,风扇开始工作了。。");
                  }
              }
              // 使用局部内部类创建对象
              Usb usb = new Fan();
              usb.service();
      
              // 使用匿名内部类优化(相当于创建了一个局部内部类)
              Usb usb1 = new Usb() {
                  @Override
                  public void service() {
                      System.out.println("连接电脑成功,风扇开始工作了。。");
                  }
              };
              usb1.service();
          }
      }
      
      package anonymous;
      
      // 接口
      public interface Usb {
          void service();
      }
      
      package anonymous;
      
      public class Mouse implements Usb {
          @Override
          public void service() {
              System.out.println("连接成功,鼠标开始工作了");
          }
      }
      
  • 定义类、实现类、创建对象的语法合并,只能创建一个该类的对象。

  • 优点:减少代码量。

  • 缺点:可读性较差。

Object类

  • 超类、基类,所有类的直接或间接父类,位于继承树的最顶层。

  • 任何类,如没有书写extends显示继承某个类,都默认直接继承Object类,否则为间接继承。

  • Object类中所定义的方法,是所有对象都具备的方法。

  • Object类型可以存储任何对象。

    • 作为参数,可接受任何对象。
    • 作为返回值,可返回任何对象。
  • getClass()方法

    • public final Class<?> getClass(){}

    • 返回引用中存储的实际对象类型。

    • 应用:通常用于判断两个引用中实际存储对象类型是否一致。

      • package Object;
        
        public class TestStudent {
            public static void main(String[] args) {
                Student s1 = new Student("aaa",20);
                Student s2 = new Student("bbb",22);
                //  判 断 s1 和 s2 是 不 是 同 一 个 类 型
               Class class1 = s1.getClass();
               Class class2 = s2.getClass();
               if (class1 == class2) {
                   System.out.println("s1和s2属于同一各类型");
               }else {
                   System.out.println("s1和s2不属于同一各类型");
               }
            }
        }
        
        package Object;
        
        public class Student {
            private String name;
            private int age;
        
            public Student(String name, int age) {
                this.name = name;
                this.age = age;
            }
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        
            public int getAge() {
                return age;
            }
        
            public void setAge(int age) {
                this.age = age;
            }
        }
        
  • hashCode()方法

    • public int hashCode() {}

    • 返回该对象的哈希码值。

    • 哈希值根据对象的地址或字符串或数字使用hash算法计算出来的int类型的数值。

    • 一般情况下相同对象返回相同哈希码。

      • package Object;
        
        public class TestStudent {
            public static void main(String[] args) {
                // getClass()方法
                Student s1 = new Student("aaa",20);
                Student s2 = new Student("bbb",22);
                       System.out.println(s1.hashCode());
        
                System.out.println(s2.hashCode());
        
                Student s3 = s1;
                System.out.println(s3.hashCode());
            }
        }
        
  • toString()方法

    • public String toString() {}

    • 返回该对象的字符串表示(表现形式)。

    • 可以根据程序需求覆盖该方法,如:展示对象各个属性值。

      • package Object;
        
        public class TestStudent {
            public static void main(String[] args) {
                // getClass()方法
                Student s1 = new Student("aaa",20);
                Student s2 = new Student("bbb",22);
                        System.out.println(s1.toString());
                System.out.println(s2.toString());
            }
        }
        
        package Object;
        
        public class Student {
            private String name;
            private int age;
        
            public Student(String name, int age) {
                this.name = name;
                this.age = age;
            }
                public String toString(){
                return name+":"+age;
            }
        }
        
  • equals()方法

    • public boolean equals(Object obj){}
      
    • 默认实现为(this == obj),比较两个对象地址是否相同。

    • 可进行覆盖,比较两个对象的内容是否相同。

      • equals()方法覆盖步骤

        • 比较两个引用是否指向同一个对象
        • 判断obj是否为null。
        • 判断两个引用指向的实际对象类型是否一致。
        • 强制类型转换
        • 依次比较各个属性值是否相同。
      • package Object;
        
        public class TestStudent {
            public static void main(String[] args) {
                // getClass()方法
                Student s1 = new Student("aaa",20);
                Student s2 = new Student("bbb",22);
                //  判 断 s1 和 s2 是 不 是 同 一 个 类 型
        //       Class class1 = s1.getClass();
        //       Class class2 = s2.getClass();
        //       if (class1 == class2) {
        //           System.out.println("s1和s2属于同一各类型");
        //       }else {
        //           System.out.println("s1和s2不属于同一各类型");
        //       }
               // hashCode方法
        //        System.out.println(s1.hashCode());
        //
        //        System.out.println(s2.hashCode());
        //
        //        Student s3 = s1;
        //        System.out.println(s3.hashCode());
                //toString方法
                System.out.println(s1.toString());
                System.out.println(s2.toString());
                // equals方法,判断两个对象是否相等
                System.out.println(s1.equals(s2));//false(s1,s2对象地址不同)
        
                Student s4 = new Student("小明", 17);
                Student s5 = new Student("小明", 17);
                System.out.println(s4.equals(s5));//false(s4,s5对象地址不同)
                
            }
        }
        
        package Object;
        
        public class Student {
            private String name;
            private int age;
        
            public Student(String name, int age) {
                this.name = name;
                this.age = age;
            }
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        //
            public int getAge() {
                return age;
            }
        
            public void setAge(int age) {
                this.age = age;
            }
            public String toString(){
                return name+":"+age;
            }
        
            @Override
            public boolean equals(Object obj) {
                // 1.判断两个对象是否是同一个引用
                if (this == obj){
                    return true;
                }
                // 2.判断obj是否为null
                if (obj == null) {
                    return false;
                }
                // 3.判断是否是同一个类型
                if (this.getClass()==obj.getClass()){
        
                }
                // instanceof 判断对象是否是某种类型
                if (obj instanceof Student){
                    // 4.强制类型转换
                    Student s = (Student)obj;
                    // 5. 比较属性
                    if (this.name.equals(s.getName())&&this.age==s.getAge()) {
                        return true;
                    }
        
                }
                return false;
            }
        }
        
posted @ 2022-07-17 19:08  小白到大牛  阅读(36)  评论(0)    收藏  举报