Java 内部类 (Inner Classes)

2023-08-28  本文已影响0人  Tinyspot

1. 内部类

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

class OuterClass {
    ...
    class InnerClass {
        ...
    }
}

要实例化内部类InnerClass,必须先实例化外部类OuterClass

1.1 特点

1.2 作用

2. 成员内部类

  1. 成员内部类与实例变量、实例方法同级别
  2. 成员内部类是依附外部类而存在的,创建成员内部类对象时,必须依赖外部类对象
  3. 当外部类与内部类的属性重名时,优先访问内部类属性
  4. 成员内部类不能定义静态成员,但可以包含静态常量 final
public class Outer {
    private String name = "Bob";

    // 默认作用域:包内可见
    public class Inner {
        private String name = "Alice";
        // 4. 静态常量 final
        private static final String address = "...";
        
        public void show() {
            System.out.println(name); // 等价 this.name
            // 3. 属性相同时,外部类使用 Outer.this
            System.out.println(Outer.this.name);
        }
    }
}

实例化成员内部类

@Test
public void test() {
    Outer outer = new Outer();
    Outer.Inner inner = outer.new Inner();
    // or
    Outer.Inner inner = new Outer().new Inner();
}

2.1 接口中的成员内部类

@Test
public void test() {
    OuterInterface.Inner inner = new OuterInterface.Inner();
    inner.show();
}
public interface OuterInterface {

    class Inner {
        // 可以有静态属性
        private static String address = "";
        public void show() {
            
        }
    }
}

3. 局部内部类

  1. 定义在外部类方法
  1. 局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,所以该局部变量必须修饰为 final
  2. 局部内部类也不能定义静态成员,但可以包含静态常量 final
public class Outer {
    private String name = "Bob";

    public void show() {
        String address = "...";

         // 局部内部类在 方法 里声明
        class Inner {
            private Integer age;
            public void innerShow() {
                System.out.println(Outer.this.name);
                // 局部内部类里访问局部变量,JDK1.7 要求变量必须是常量final,JDK1.8 自动添加final
                System.out.println(address);
                // Variable 'address' is accessed from within inner class, needs to be final or effectively final
                // address = "111";
            }
        }
        Inner inner = new Inner();
        inner.innerShow();
    }
}

访问测试

@Test
public void test() {
    Outer outer = new Outer();
    outer.show();
}

3.1 address 为什么是 final

address 若是一个普通属性,当 show() 方法执行完之后,局部变量 address 就会消失
show() 里面的 Inner inner = new Inner(); new Inner() 在堆里,不会立即消失,innerShow() 属于类 Inner 也不会立即消失
变量 address 没有了但类还在,不合理,所以是 final 类型

4. 匿名内部类

见文章 https://www.jianshu.com/p/463a7ae13fc5

5. 扩展

5.1 内部类实现接口

public class OuterClass {

    public OutInterface newInnerClass() {
        return new InnerClass();
    }

    private class InnerClass implements OutInterface {

        @Override
        public void out() {
            System.out.println("InnerClass execute");
        }
    }
}
public interface OutInterface {
    void out();
}

访问测试

@Test
public void test() {
    OuterClass out = new OuterClass();
    OutInterface outInterface = out.newInnerClass();
    outInterface.out();
}
上一篇 下一篇

猜你喜欢

热点阅读