java匿名内部类怎么创建对象(为什么起这么一个名字)
java匿名内部类怎么创建对象(为什么起这么一个名字)小A:不能!…不…能…能吧?这不new出来了…MDove:它就是普通的new?!!!你怎么学的Java!!接口能被new么!大声告诉我,接口能被new么?!public class Main { public static void main(String[] args) { final String name = "Haha"; new FunLisenter() { @Override public void fun() { System.out.println(name); } }.fun(); } } // 外部接口 public interface FunLisenter { void fun(); } MDove:先解答你第一个问题,啥是内部匿名类。上述demo中的:new FunLisenter() { @Override public void f
前言这是速读系列的第4篇文章,内容是一起聊一聊内部匿名类,以及内部匿名类使用外部变量为啥要加final。
引子小A:MDove,我最近在学习匿名内部类的时候有点懵逼了?咋还起了个这么洋气的名字?啥是内部匿名类啊?为啥它引用外部变量还得加final?还不能重新赋值?
MDove:哎呦,叭叭的,问题还挺多。话说回来,内部匿名类的确是一个很别扭的存在。那咱们今天就好好聊一聊内部匿名类,好好从源头解一解你的疑问。
啥是内部匿名类MDove:咱们先写一个普通的内部匿名类的简单demo:
public class Main { public static void main(String[] args) { final String name = "Haha"; new FunLisenter() { @Override public void fun() { System.out.println(name); } }.fun(); } } // 外部接口 public interface FunLisenter { void fun(); }
MDove:先解答你第一个问题,啥是内部匿名类。上述demo中的:
new FunLisenter() { @Override public void fun() { System.out.println(name); } }
这就是内部匿名类。
小A:啊?它不就是普通的new么?咋还成内部匿名类了?
MDove:它就是普通的new?!!!你怎么学的Java!!接口能被new么!大声告诉我,接口能被new么?!
小A:不能!…不…能…能吧?这不new出来了…
MDove:接口不能new!为什么这里被new出来了?因为它是匿名内部类,它是特殊的存在!
小A:(小声哔哔…)特殊在哪?
MDove:Java语言规定,接口不能被new!既然这是“甲鱼的臀部”,那么new FunLisenter()…就一定不是我们表面上看到的new!接口!!不给你扯犊子,直接上编译后的.class文件:
MDove:瞪大你的眼,仔细看!有什么不同?
小A:咦?怎么2个java文件编译后出来了3个class文件?
MDove:这就是特殊的存在,我们反编译这个特别的Main$1.class文件:
final class Main$1 implements FunLisenter { Main$1() { } public void fun() { System.out.println("Haha"); } }
MDove:这很清晰吧?看明白了么?
小A:嗯??一个奇怪的类实现了我们的FunLisenter接口??难道我new的FunLisenter就是new的这个奇怪的Main$1类么?
MDove:呦,这么快反应过来了?再深入思考一下。为啥叫做匿名,是不是有点感觉了?对于我们java层面来说,这个类压根就看不到。
小A:那它为啥要叫内部类呀?
MDove:啊?Main$1,不叫内部类叫啥类?你有没有编译过含有内部类的类?内部类的class文件就是这样啊!
小A:哦哦,好像还真是这样!那也就是说之所以被称之为内部匿名类,是因为:在编译阶段,编译器帮我们以内部类的形式,帮我们implement我们的接口,因此我们才可以以new的方式使用。
MDove:没错,你理解的很到位。
小A:对了,我还听说过一个名词,好像叫做:内部匿名类会持有外部对象的引用…这是啥意识?
内部匿名类会持有外部对象的引用
MDove:呦,都了解的这么多了?关于这个话题,暂时先不开展。后续我会专门好好整理一遍内部,好好帮你理解一下这句话,以及这句话背后所带来的问题。这里先简单写段代码,你可以先看看,解解闷。
public class Main { public static void main(String[] args) { Main main = new Main(); main.fun(); } public void fun() { new FunLisenter() { @Override public void fun() { } }.fun(); } }
MDove:直接看 反编译后的匿名内部类:
class Main$1 implements FunLisenter { Main$1(Main var1) { this.this$0 = var1; } public void fun() {} }
MDove:OK,这个话题就此打住,已经超出了本次文章的范围。不过既然你开了口,下一次我们来好好聊一聊内部匿名类持有外部引用,造成内存泄漏的问题~
剧终