快捷搜索:  汽车  科技

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

java匿名内部类怎么创建对象(为什么起这么一个名字)(1)

前言

这是速读系列的第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文件:

java匿名内部类怎么创建对象(为什么起这么一个名字)(2)

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,这个话题就此打住,已经超出了本次文章的范围。不过既然你开了口,下一次我们来好好聊一聊内部匿名类持有外部引用,造成内存泄漏的问题~

剧终

猜您喜欢: