- Java内部类是编译器现象,最终会将内部类编译成一个外部类$内部类.class字节码文件
源代码
public class OuterClass {
private String name;
class InnerClass{
//为了让内部类的静态字段是唯一的,所以必须强制要求是final
static final String a = "a";
private String name ;
public void hello(){
System.out.println("iiClass hello");
}
public InnerClass(String name){
this.name = name;
}
}
}
//使用 javac 来解析出class文件,使用javap 来查看class 文件
解析出的文件
- 内部类和外部类文件内容
- 外部类,只包含了构造方法
- 内部类,注入了一个外部类实例,同时在构造方法中也引入了外部类的形参,通过外部类的实例来访问外部类的实例。
- 外部类,只包含了构造方法
- 内部类中静态变量,由于Java设计中,静态实例只有一个实例,所以静态实例需要使用final来强制要求只有一个对象。如果不使用final修饰,可以会被修改。
内部类对外部类私有成员的访问特权
在上面代码的基础上进行了修改
public class OuterClass {
private String title;
class InnerClass{
//为了让内部类的静态字段是唯一的,所以必须强制要求是final
static final String a = "a";
private String name ;
public void hello(){
//内部类访问外部的实例
System.out.println("InnerClass hello"+title);
}
public InnerClass(String name){
this.name = name;
}
}
}
- 外部类
- 生成了一个静态方法,返回的外部类的title的值,内部类调用该方法,将内部类中外部类的实例传递进来,然后获取到内部类中的字段的值,从而实现访问外部类中的私有成员。上面的内部类的方法,将会变成如下
System.out.println("InnerClass hello"+title);
--》
System.out.println("InnerClass hello"+access$000(this$0));
局部内部类
- 作用域范围:限定在声明这个局部类的块中,所以不能是public或者private进行声明
- 优势:可以访问外部类中的变量,例如name,也可以访问局部变量,即task
- 示例
- 代码
public class Student { private String name; //内部类使用了,需要声明为final public void doWork(final String task){ //只要内部类使用就需要声明为final final String title = "Math"; class Work{ public void work(){ System.out.println("do "+title+","+task); } } System.out.println(title); }
}
```
* 解析出之后的class文件
* 局部类的反编译结果,内部类中存在方法的行参副本,为了保证局部类中的 副本值和使用的值是相等的,必须保证在方法中不能对使用的形参以及局部变量的值进行修改,所以都需要定义为final。
匿名内部类
- 优点:简化书写,在局部内部类的基础上进行简化
- 编译器根据匿名内部类实现的方式,可以分为
- 通过接口的方式,生成匿名内部类,实质是实现接口的一个类的实例
- 通过类的方式,生成匿名内部类,实质是具体类的子类的一个实例,所以不能通过getClass来进行比较。
- 代码
public class EnglishTask {
public void doTask(){
System.out.println("do English Task");
}
}
public interface Work {
void doWork();
}
public class Student {
private static String name = "小花";
public static void doWork(){
Work work = new Work() {
@Override
public void doWork() {
System.out.println("Student["+name+"] do Work");
}
};
System.out.println(work.getClass());
System.out.println(work.getClass().getSuperclass());
Class<?>[] interfaces = work.getClass().getInterfaces();
for (Class clazz :
interfaces) {
System.out.println(clazz.getName());
}
}
public static void doWork2(){
EnglishTask work = new EnglishTask() {
@Override
public void doTask() {
System.out.println("Student["+name+"] do Work");
}
};
EnglishTask task = new EnglishTask();
System.out.println(work.getClass());
System.out.println(work.getClass().getSuperclass());
System.out.println( work instanceof Object);
System.out.println(work.getClass() == task.getClass());
}
public static void main(String[] args) {
doWork();
System.out.println("------------------");
doWork2();
}
}
静态内部类
- 使用场景:只是为了将一个类隐藏在另外一个类的内部,并不需要内部类引用外部类对象。其他与其他内部类完全一样。
- 代码
public class Work {
private String titleName;
private Task firstTask;
static class Task{
private String taskName;
public void doTask(){
System.out.println("do task");
}
}
}
- 反编译结果
- 外层类
- 内部静态类,不存在外部类的副本,
- 外层类