一直以来都有个疑问:明明在方法里写匿名内部类时都是new 一个外部类的,那为何叫匿名内部类呢?
public class Test{
public void testSomeThing() {
// 如此处,假设LoginUser类与Test类不在同一包下
LoginUser loginUser1 = new LoginUser() {
@Override
public void setId(String id) {
super.setId(id);
}
};
}
}
查阅了相关资料,发现此时是创建了一个基于此类的子类
public class Test{
// 一个子类继承了LoginUser
class LoginUserTest extends LoginUser{
}
public void testSomeThing() {
// 如此处,假设LoginUser类与Test类不在同一包下
LoginUser loginUser1 = new LoginUser() {
@Override
public void setId(String id) {
super.setId(id);
}
};
// 实际上loginUser1 等价于loginUserTest ,此时会自动创建一个类似LoginUserTest 的匿名类
LoginUserTest loginUserTest = new LoginUserTest();
}
}
这个类由于是匿名的,所以通常在idea下是看不到的,但是如果使用javac编译可以看到,
假如编译了Test文件,会发现一个叫
$Test
的.class文件,这个文件就是匿名内部类,一个等价于LoginUserTest 的类(不是LoginUserTest ,这个会直接编译成LoginUserTest的)
(此图中的CourseResultServiceImpl看成是Test类,CourseResultB看成是LoginUserTest ,匿名内部类idea中不会显示所以此处没有显示,但实际上会有一个$CourseResultServiceImpl
的匿名内部类)
部署项目的时候,如果是单个class文件(Test.class)而不是那种.jar(my-test.jar)的形式的话,对应的java类里尽量不要写匿名内部类(包括双大括号写法{{}},lambda表达式)的写法,否则可能会报找不到$XXX类的错误。这个就是因为没有吧对应内部类的class文件也给部署上去的缘故
如果是接口形式的话,内部类会变成接口的实现类
public class Test{
// 一个子类继承了LoginUser
class LoginUserTest extends LoginUser{
}
// 一个接口的实现类,UserService是一个接口
class MyServiceImpl implements UserService{
@Override
public void test(){
}
}
public void testSomeThing() {
// 如此处,假设LoginUser类与Test类不在同一包下
LoginUser loginUser1 = new LoginUser() {
@Override
public void setId(String id) {
super.setId(id);
}
};
// 实际上loginUser1 等价于LoginUserTest ,但不是LoginUserTest ,此时会自动创建一个类似LoginUserTest 的匿名类
LoginUserTest loginUserTest = new LoginUserTest();
// 此时等价于MyServiceImpl,但不是MyServiceImpl,此时会自动创建一个类似MyServiceImpl的匿名类
UserService service = new UserService(){
@Override
public void test(){
}
}
}
}
- 2024-01-12日更新:描述里将java文件修改成了class文件