专栏名称: ImportNew
伯乐在线旗下账号,专注Java技术分享,包括Java基础技术、进阶技能、架构设计和Java技术领域动态等。
目录
相关文章推荐
芋道源码  ·  分库分表 带来了哪些问题? ·  昨天  
Java编程精选  ·  字节员工疑问:为什么大厂客户端宁愿用28k招 ... ·  2 天前  
芋道源码  ·  DeepSeek浪潮,Spring也赶上了?! ·  3 天前  
芋道源码  ·  SpringBoot ... ·  3 天前  
51好读  ›  专栏  ›  ImportNew

Java 内部类的一些实现细节

ImportNew  · 公众号  · Java  · 2017-05-12 13:43

正文

(点击 上方蓝字 ,快速关注我们)


编译:ImportNew - 陈秋林

如有好文章投稿,请点击 → 这里了解详情


Java中可以定义成员内部类(在另一个类里面定义的类),局部内部类(在语句块中定义的类)和匿名内部类(没有名字的类):


class Outer {

Object anonymous = new Object() {}; // 这是一个匿名类

// 匿名初始化

{

// 这是一个Local类

class Local {}

Local l = new Local();

}

Outer() {

// 这是构造函数中的Local类

class Local {}

Local l = new Local();

}

void method() {

// 这是方法中的Local类

class Local {}

Local l = new Local();

}

// 这是一个成员类

class Inner {}

Inner i = new Inner();

}


Java语言规范将成员类,本地类和匿名类统称为内部类。


实现“细节”


Java语言规范和虚拟机规范并没有告诉我们内部类的实现细节。这里的一些文章阐明了一些细节,比如Java编译器如何生成合成方法,可以使这些成员类访问(外部类的)私有成员,这在JVM中本来是是不允许的。


很容易知道内部类的另一个实现细节:内部类的构造函数需要额外的合成参数。内部类构造函数第一个合成参数就是普遍知道的内部类的外围实例(的引用),它存储在this$0 的合成域中。 这是适用于三种内部类:成员,本地和匿名。


但鲜为人知的是,局部内部类需要通过额外的合成构造参数来获取非常量变量,(获取常量将被内联,并不会产生额外的合成构造函数参数):


class Outer {

void method() {

final String constant = "foo";

final String nonConstant = "foo".toUpperCase();

class Local {

/*

* synthetic fields and constructor:

*

* Outer this$0; String nonConstant;

*

* Local(Outer this$0, String nonConstant){ this.this$0 = this$0;

* this.nonConstant = nonConstant; }

*/

}

Local l = new Local();

}

}


好吧,但是我为什么要关心它?


在大多数情况下,你并不关心内部类的实现机制,除非好奇心使然。但是如果你在内部类中使用了反射,这里有些东西你需要清楚,而且我并没有听过或者在网上看过这类资料,所以我想很有必要列出清单帮助其他人弄清楚,因为通过Java反射的API,不同的编译器会产生不同的结果。


现在的问题是,当你使用Java反射来获取对内部类构造一个java.lang.reflect.Constructor中的实例会发生什么情况,尤其是使用那些允许你访问参数类型(pre-generics:getParameterTypes()),泛型参数类型(post-generics: getGenericParameterTypes())和注释(getParameterAnnotations())?答案是:这取决于不同的编译器。


假设有一个类:


class Outer {

class Inner {

Inner() {}

Inner(String param) {}







请到「今天看啥」查看全文