一、先对匿名内部类的本质进行说明
1、匿名内部类本质是一个类,能当正常类使用,
2、匿名内部类没有名字,但 jdk 会对匿名内部类分配名字
3、匿名内部类有自己的构造器
4、匿名内部类也是一个对象
二、匿名内部类的语法
new 接口/类(参数列表){ }
三、基于接口的匿名内部类
package com.hspedu.csdn;
public class Explain {
public static void main(String[] args) {
/*
1、在new一个匿名内部类之前,jdk底层会分配一个类,这个类会实现接口,
分配的类长下面这个样子:
class Explain$1 implements A{
Explain$1(){
}
@Override
public void ok() {
System.out.println("ok---");
}
}
Explain$1就是jdk底层给这匿名内部类的名字,只是你看不到
2、这个名字的命名格式是“外部类名+美元符号+数字”,这里的外部类
就是Explain,数字指这个匿名内部类第几个运行就是几
3、这个匿名内部类Explain$1和正常类区别在于,不能自己手动添加一个构造器,
Explain$1的构造器是系统提供的无参构造器
4、Explain$1匿名内部类和正常类一样,可以在匿名内部类中添加属性,
方法,代码块等
5、系统分配的Explain$1类只能创建一次,创建一次之后,Explain$1类就会销毁,即:
只能new一次,new完之后,不能在其他地方new Explain$1();
6、对象引用a,它的编译类型是接口A,运行类型是Explain$1类
7、为什么我会知道这些?原因:对Explain.java文件进行编译,会生成三个字节码文件
分别是:A.class Explain.class Explain$1.class
其中用javap指令对Explain$1.class进行反编译,可以得到这个字节码文件的源代码
*/
A a = new A(){
@Override
public void ok() {
System.out.println("ok---");
}
};
}
}
interface A{
int a = 10;
void ok();
}
四、基于类的匿名内部类
package com.hspedu.csdn;
public class Explain {
public static void main(String[] args) {
/*
1、在new一个匿名内部类之前,jdk 底层会分配一个类,这个类会继承B类,
分配的类长下面这个样子:
class Explain$1 extends B{
Explain$1(int ){}
@Override
public void hi() {
System.out.println("匿名内部类 hi");
}
}
Explain$1就是jdk底层给这匿名内部类的名字,只是你看不到
2、这个名字的命名格式是“外部类名+美元符号+数字”,这里的外部类
就是Explain,数字指这个匿名内部类第几个运行就是几
3、这个匿名内部类Explain$1和正常类区别在于,不能自己手动添加一个构造器,
Explain$1的构造器是系统提供的有一个参数的构造器,这个参数是你在new的时候
传进来的
4、Explain$1匿名内部类和正常类一样,可以在匿名内部类中添加属性,
方法,代码块等
5、系统分配的Explain$1类只能创建一次,创建一次之后,Explain$1类就会销毁,即:
只能new一次,new完之后,不能在其他地方new Explain$1();
6、对象引用a,它的编译类型B类,运行类型是Explain$1类
7、为什么我会知道这些?原因:对Explain.java文件进行编译,会生成三个字节码文件
分别是:B.class Explain.class Explain$1.class
其中用javap指令对Explain$1.class进行反编译,可以得到这个字节码文件的源代码
*/
B b = new B(888) {
@Override
public void hi() {
System.out.println("匿名内部类 hi");
}
};
}
}
class B{
private int n2 = 20;
public B(int n2) {
}
public void hi(){
System.out.println("B hi");
}
}