java面向对象三——内部类

内部类的定义和分类

使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。接口只是解决了部分问题,而内部类使得多重继承的解决方案变得更加完整。

  • 对于成员内部类,在外部创建内部类对象的标准格式为:
    Outer.Inner oi = new Outer().new Inner();

成员内部类可以理解为一种特殊成员,一般是不会直接暴露给外部使用的,需要用private保证封装性,然后在外部类中设置访问接口。

public void method() {
    if(condition) {
        Inner in = new Inner();
        in.function();
    }
}
  • 在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。
  • 内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。
  • 内部类提供了更好的封装,除了该外围类,其他类都不能直接访问(即便是静态内部类,访问时也至少加上类名前缀)

非静态内部类实例创建时候必须依赖外部类的实例,其寄生在外部类实例中,所以非静态内部类会隐式地保存一个外部类的引用

一、非静态内部类
  • 非静态内部类不能包含静态成员,因为此类内部类相当于一个类的特殊成员,不会随着类加载而存在,需要随着对象的创建才能使用;而根据static的语义,其标识的内容是跟随类加载而存在,不需要对象的创建就能被访问。如果非静态内部类中存在静态成员,static声明和内部类依赖对象的属性就会产生冲突。
  • 可以无缝访问外部类成员,外部类如果想访问内部类需要创建对象(局部内部类无法在方法外被访问)

1.成员内部类

  • 成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类。
  • 外部类访问内部类成员需要通过内部类实例实现
  • 内部类访问成员变量,当内外部类变量同名时候,需要用外部类.this和this作为限定来区分,内部类中访问同名成员时系统优先访问内部类中的成员

2、匿名内部类

  • 适合创建那种只需要一次使用的类,好处就是使用完后就可以当做垃圾回收,而且没有栈内变量指向它。
  • 不能定义构造器,因为没有类名。
  • 匿名内部类中如果有访问方法中的局部变量,就必须设置为final,因为局部变量在方法结束后就销毁,但局部内部类对象还在堆中等待垃圾回收(不够及时),仍然在引用那个变量,这样就会产生不可预料后果。所以我们需要将变量设置为final,使其在内部类对象中被存储为一个常量拷贝。这样即使变量被回收了,在内部类中也能使用。Java8 后取消了这个限制,但依然会隐式添加final。
  • 匿名内部类的语法同样可以运用到普通类中

3、局部内部类

  • 仅仅作用在方法中,其他程序单元不能访问局部内部类。
  • 不能加任何修饰符
  • 使用局部方法中的局部变量时候需要将该变量设置成final,原因同上。
二、静态内部类

它的创建是不需要依赖于外围类的。
它不能使用任何外围类的非static成员变量和方法,只能通过创建外部类对象可以访问。
接口内部类只能是静态内部类,默认使用了public static修饰符
标准访问格式为:
Outer.Inner inner = new Outer.Inner();
不能通过外部类对象进行访问或创建,我的理解是这样就表明外部类对象会被内部类对象引用。

总结区别

非静态内部类

  • 创建条件 需要基于外部类实例创建,会隐式包含外部类的引用(内存泄漏)
  • 内容特征 不能包含静态成员
  • 访问条件 可以访问外部类包括私有在内的所有成员,外部访问内部类需要创建对象调用
    静态内部类
  • 创建条件 不需要外部类实例创建,没有对外部类的引用
  • 内容特征 自身可以包含静态和非静态成员
  • 访问条件 不能使用外部类的非静态成员,外部类可以通过类名直接访问其中静态成员,也可以直接创建静态内部类对象进行访问。

使用内部类

1.在外部类中使用内部类
基本和使用普通类无差别,唯一注意的是不要在外部类的静态成员中直接调用非静态内部类,因为非静态内部类的调用首先要保证在外部类对象中创建实例

2.在外部类之外使用非静态内部类
必须在使用前创建外部类的实例,

OuterInstance.new InnerInstance()
或者
Out.In in = new Out().new In();

有个方法可以保证在创建非静态内部类时必定创建了外部类的实例

public class SubClass extends Out.In {
       public SubClass(Out out) {
              out.super();//通过传入out对象显示地调用in的构造器
}
}

3.在外部类以外使用静态内部类
Outer.StaticInner staticIn = new Outer.StaticInner();

你可能感兴趣的:(java面向对象三——内部类)