java 内部类 构造函数_Java 内部类的一些实现细节

276cf30628f06eebd7030d6f1d77340f.png

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

46f3f26f1e5c0b1b5beb2a29be7086d9.png

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

实现“细节”

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

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

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

be6f2cfeffca8795c74d943a23f1d961.png

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

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

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

假设有一个类:

41a6bb555f0c0b4d3e2e0363893cdba6.png

下面是这三个通过反射调用构造函数得到的数组的长度,它们会因为java编译器的不同而不同。

74cfc873dacd0b907b12ec988ff5d83a.png

可以看到,getParameterTypes()中始终包含“合成”参数,但是在getGenericParameterTypes()中,只有用Eclipse编译时才包含“合成”参数;而对于getParameterAnnotations(),除非你的构造函数的参数使用了注释,否则也一直包含了“合成”参数。

通过这些信息,你可以了解到这三个方法产生的不同结果,但是到目前为止我还是没有办法确定一个参数是否是“合成”的,因为虽然你可以对每个内部类都需要的this$X合成参数做一个很好的猜测,你没办法知道最终成为局部内部类的“合成”参数的数目。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值