Java之深入理解内部类
第一次学习内部类的时候理解内部类就只是定义在类里的累,其他并无区别。然而在之后的学习和应用中,也没有过多使用过内部类。于是打算借助期末复习的机会详细学习并理解一下内部类。
内部类分类
成员内部类
成员内部类是最普通的内部类,定义在类内部,好似类的一个成员
成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问
当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象
,需要使用
外部类.this.成员变量 外部类.this.成员方法
访问
成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。
权限:
内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。比如上面的例子,如果成员内部类Inner用private修饰,则只能在外部类的内部访问,如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。
局部内部类
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
匿名内部类
用的比较多,比如实现接口的时候,lambda表达式也类似(但不是内部类)。
或者:
public void test(final int b) {
final int a = 10;
new Thread(){
public void run() {
System.out.println(a);
System.out.println(b);
};
}.start();
}
静态内部类
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。
- 静态内部类是不需要依赖于外部类的
- 不能使用外部类的非static成员变量或者方法(相当于静态成员)
深入理解
为什么需要内部类?
1.丰富继承体系,内部类可以继承或实现接口 不影响外部类
2.语法糖,可以简化代码
3.方便lambda,事件驱动型代码的书写
成员内部类是如何访问外部类成员的?
答案:通过指针(或引用?)!在成员内部类被创建的时候,编译器会为其构造函数添加参数:传入一个外部类的指针。
创建成员内部类实例为什么要先创建外部累实例?
答案:同上。因为内部类的构造函数会默认有一个参数为外部累的引用(指针?)
为什么局部内部类和匿名内部类只能访问局部final变量?
lambda表达式也是同理。
答案:局部代码块中的局部变量,在函数执行结束后,便被销毁了。而局部内部类(通常伴随着线程),所以该变量又不能销毁,于是JVM想了一个办法:将该变量拷贝一份在创建局部内部类的时候当作参数传进去,所以必须在编译期就要确定,所以必须是final的,否则不能通过。
局部内部类和匿名内部类会生成字节码的,所以要求编译期就要确定变量外部变量的值。
lambda虽然不回产生匿名累的class但是,采用字节码追加的技术追加到class中,也要求编译期可以确定。