这只是自学阶段的理解,以后还有再写相关的文章来完善的
所谓内部类就是在类的内部的类。按照所在不同位置,修饰符不同,使用方法不同可以分为4类
总的来说内部类有一下三个共同特点:
- 编译之后会生成独立的字节码文件。Outer$Inner.class的形式
- 内部类可以直接访问外部类的私有成员,而不破坏封装性。
- 为外部类提供必要的内部功能组件
成员内部类
1.与类的普通成员同级,在在创建外部类对象之后才被加载,才能创建内部类对象。
2.创建方式:
//非常特殊的创建方式。
Outer.Inner in = out.new Inner();
访问不同级的同名变量的方式
class Outer {
int a = 1 ;
class Inner {
int a = 2;
void m(){
int a = 3;
System.out.println("a = " + a );
System.out.println("a = " + this.a );
System.out.println("a = " + Outer.this.a );
}
}
}
其实没有多大意义,一般开发中涉及到这样的问题,绝对不能定义同名变量。
静态内部类
与类成员同级,在外部类被加载时不会被加载,只有当调用静态内部类的成员时才会被加载。不需要借助外部类来加载,不过在静态内部类被加载时,外部类也会被加载。
//好理解
Outer.Inner in = new Outer.Inner();
局部内部类
所谓局部内部类就时和局部变量同级的内部类,也就是定义在方法中的内部类。
这样的内部类在方法被调用时加载,一般在方法中创建。
下面提出一个问题,为什么local要用final修饰?
class Outer {
Printable pr = null;
void m1 (){
//这里要求local是final修饰的,虽然在jdk8之后不加final修饰也不报错,但是实际上编译器自动给我加了final。
String local = "Hello";
class Inner implements Printable{
@Override
public void print() {
int a = 20 ;
System.out.println("local:"+ local);
//loacl++;
//上一行代码吃那个尝试修改local就报错了,提示local是final修饰的
}
}
pr = new Inner();
pr.print();
}
}
interface Printable {
void print();
}
因为局部类对象虽然和局部变量同级,但是让m()结束后,在栈中的局部变量local的值在内存中就被清除了,但是内部类的对象在堆中,不会随着方法的结束马上没清除,这时候如果我把给内部类的对象传给了外面的一个接口或者类的引用之后,这个内部类就依然存在。如果我想在调这个类的方法,方法中调这个局部变量local的值,就会出现问题,因为它已经被清除了。所以为了保证local的生命周期比内部类对象长,就必须把local用final声明为常量,放在常量池中。
匿名内部类
匿名内部类就是没有名字的局部内部类。
没有名字那么怎么证明这是个类呢?都没class声明了呀
用new 类名或接口名(){};这样的方式创建。必须继承或者实现一个接口。
定义、创建、实现一起完成。
其实从语法上没有什么特别的,几乎和局部内部类一样,但是使用起来非常方便,而且还有lambda表达式的支持。
内部类的使用场景非常多,而且程序设计层面上使用特别多。很多框架源码里有大量的内部类