常用类-内部类

在千锋教育的学习笔记

内部类

概念

在一个类的内部在定义一个完整的类

特点

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

    public class Outer01 {
        private String name = "肖枫";
        private int age = 18;
        class Inner{
            private String sex = "男";
            public void Play(){
                System.out.println(name + " plays CF well!");
                System.out.println(sex);
            }
        }
    }
    
  • 编译之后生成独立的字节码文件

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

分类

成员内部类
  • 概念

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

    • 外部类的一个实例部分,创建内部类对象时必须依赖外部类对象,否则会报错:“is not an enclosing class”

      package com.ciao.innerDemo;
      import com.ciao.innerDemo.Outer01.Inner;//先导入内部类(为什么?)
      public class Test01 {
          public static void main(String[] args) {
              //创建外部类对象
              Outer01 outer = new Outer01();
              //创建内部类对象
              Inner inner = outer.new Inner();
              //Inner inner = new Outer01().new Inner();//一步完成
              inner.Play();//调用内部类中的共有方法
          }
      }
      
    • 当内部类、外部类存在同名属性时,会优先访问内部类的属性

      public class Outer01 {
          private String name = "肖枫";
          private int age = 18;
          class Inner{
              private String sex = "男";
              private String name = "麒麟";
              public void Play(){
                  System.out.println(name + " plays CF well!");//访问内部类
                  System.out.println(this.name + " plays CF well!");//当前类
                  System.out.println(Outer01.this.name + " plays CF well!");//外部类
                  System.out.println(sex);
              }
          }
      }
      
  • 成员内部类中不能定义静态成员,但可以定义静态常量

    private static String name = "麒麟";//会报错(Inner classes cannot have static declarations)
    private static final String name = "麒麟";//定义静态常量
    
静态内部类
  • 概念

    • 在类的内部定义 ,与外部类同级别的类(相当于一个外部类)
  • 特点

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

      package com.ciao.innerDemo02;
      public class Outer {
          private String name = "肖枫";
          private int age = 18;
          static class Inner{//静态内部类,在内部类前添加一个static修饰
              private String sex = "男";
              private String name = "麒麟";
              private static int count = 10;//静态成员
              public void Play(){
                  //相当于一个外部类调用Outer类中的属性
                  // 需要先创建实例,再通过实例调用属性
                  Outer outer = new Outer();//创建外部实例
                  System.out.println(this.name + " plays CF well!");//调用实例属性
                  System.out.println(name + " plays CF well!");
                  System.out.println(outer.name + " plays CF well!");
                  System.out.println(count);
              }
          }
      }
      
  • 注意

    • 只有内部类才能用static修饰,普通类不可以。
局部内部类
  • 概念

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

      • 定义类

        package com.ciao.innerDemo03;
        public class Outer {
            //外部类属性
            private String name = "肖枫";
            private int age = 19;
            public void show(){
                //定义局部变量(问:只能用final修饰?)(答:jdk1.7要求变量必须是常量final,jdk1.8自动添加final)
                String sex = "男";
                //定义局部内部类,不能加任何访问修饰词
                class Inner {
                    //定义局部内部类的属性
                    private String phone = "15333333333";
                    public void InnerShow() {
                        System.out.println(Outer.this.name);//直接访问外部类属性
                        System.out.println(sex);//直接访问方法中的局部变量,jdk1.7要求变量必须是常量final,jdk1.8自动添加final
                        System.out.println(this.phone);
                    }
                }
                //在方法中创建局部内部类对象
                Inner inner = new Inner();
                inner.InnerShow();//调用方法
            }
        }
        
        

        思考:上述sex变量为什么要加final修饰符?(https://www.bilibili.com/video/BV1vt4y197nY?p=6 11:05 内部类中访问的sex已经变成确定的值"男"了)

      • 测试

        package com.ciao.innerDemo03;
        public class Test {
            public static void main(String[] args) {
                Outer outer01 = new Outer();//通过外部类实例调用局部内部类
                outer01.show();
            }
        }
        
  • 特点

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

      public class Outer {
          //外部类属性
          private String name = "肖枫";
          private int age = 19;
          public void show(){
              //定义局部变量(问:只能用final修饰?)(答:jdk1.7要求变量必须是常量final,jdk1.8自动添加final)
              String sex = "男";
              //定义局部内部类,不能加任何访问修饰词
              class Inner {
                  //定义局部内部类的属性
                  private String phone = "15333333333";
                  public void InnerShow() {
                      System.out.println(Outer.this.name);//直接访问外部类属性
                      System.out.println(sex);//直接访问方法中的局部变量,jdk1.7要求变量必须是常量final,jdk1.8自动添加final
                      System.out.println(this.phone);
                  }
              }
              //在方法中创建局部内部类对象
              Inner inner = new Inner();
              inner.InnerShow();//调用方法
          }
      }
      
      
    • 局部内部类中不能包含静态成员,但可用final修饰静态成员变成静态常量

      private static int count = 1;//Inner classes cannot have static declarations
      private final static int count = 1;
      
    • 限制类的使用范围,只能在方法中使用

匿名内部类
  • 概念

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

    • 必须继承一个父类或者实现一个接口
    • 定义类、实现类、创建对象的语法合并,只能创建一个该类的对象
  • 优缺点

    • 优点:减少代码量
    • 缺点:可读性较差
  • 案例

    • 接口

      package com.ciao.innerDemo04;
      //接口
      public interface Usb {
          //服务
          void Service();
      }
      
    • 鼠标类

      package com.ciao.innerDemo04;
      //鼠标实现usb接口
      public class Mouse implements Usb{
          //实现方法
          @Override
          public void Service() {
              System.out.println("连接成功,鼠标开始工作...");
          }
      }
      
    • 测试类

      package com.ciao.innerDemo04;
      public class TestUsb {
          public static void main(String[] args) {
      //        Usb usbMouse = new Mouse();//创建接口类型的变量
      //        usbMouse.Service();
              /*
              //局部内部类
              class Windy implements Usb{
                  //风扇
                  @Override
                  public void Service() {
                      System.out.println("连接成功,风扇开始工作...");
                  }
              }
              //使用局部内部类创建对象
              Usb usbWindy = new Windy();
              usbWindy.Service();
              */
              //使用匿名内部类优化(相当于创建了一个局部内部类)
              Usb usbKey = new Usb() {//可以是接口,也可以是抽象类或者父类,在里面重写方法就行
                  @Override
                  public void Service() {
                      System.out.println("连接成功,键盘开始工作...");
                  }
              };
              usbKey.Service();
          }
      }
      
    • 匿名函数其实也有名字,系统命名的,查看输出文件

posted on 2020-09-08 20:26  C1ao  阅读(42)  评论(0)    收藏  举报