java构造函数内部调用_具有内部类构造函数参数的Java Reflection奇数

java构造函数内部调用

关于Java内部类

Java允许成员类(在其他类内定义的类),局部类(在语句块内定义的类)和匿名类(无名称的类):



class Outer {
    Object anonymous = new Object(){}; // this is an anonymous class
 
    // anonymous initialisation block
    {
        // this is a local class
        class Local{}
        Local l = new Local();
    }
 
    Outer() {
        // this is a local named class in a constructor
        class Local{}
        Local l = new Local();
    }
 
    void method() {
        // this is a local named class in a method
        class Local{}
        Local l = new Local();
    }
 
    // this is a member class
    class Inner{}
    Inner i = new Inner();
}

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

实施“细节”

Java语言或虚拟机规范没有告诉您的是它们是如何实现的。 其他文章已经对此进行了解释,例如Java编译器如何生成综合方法以允许这些成员类访问私有字段,而JVM不允许这样做。

内部类的另一个易于实现的实现细节是内部类的构造函数采用了额外的综合参数。 相对众所周知 ,内部类构造函数的第一个综合参数将是其封闭实例,并将其存储在this$X综合字段中。 这对所有三种内部类均有效:成员,本地和匿名。

但是通常不知道捕获非恒定最终变量的局部类是否要求将所有这些变量作为额外的综合构造函数参数传递(捕获的常数最终变量将被内联并且不会生成额外的综合构造函数参数):

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反射,那么您应该了解一些事情,并且由于我没有在网上找到或列出它们,因此我认为重要的是要列出帮助他人了解的事情因为不同的编译器将在Java Reflection API中产生不同的结果。

问题是,当您使用Java反射为内部类构造函数获取java.lang.reflect.Constructor实例时会发生什么? 特别是,允许​​您访问参数类型(前泛型: getParameterTypes() ),泛型参数类型(后泛型: getGenericParameterTypes() )和注释( getParameterAnnotations() )以及答案的方法会发生什么?是: 这取决于

假设以下Java类:

class Outer {
    class Inner {
        Inner(){}
        Inner(String param){}
        Inner(@Deprecated Integer param){}
    }
}

这是我们的每个构造函数上这三种反射方法返回的数组的大小,以及它们根据所使用的Java编译器的不同而有所不同:

外层内部类
.getDeclaredConstructor()
外层内部类
.getDeclaredConstructor(
String.class)
外层内部类
.getDeclaredConstructor(
Integer.class)
getParameterTypes()
。长度
1个 2 2
getGenericParameterTypes()
.length用Eclipse编译
1个 2 2
getGenericParameterTypes()
.length用Javac编译
0 1个 1个
getParameterAnnotations()
。长度
1个 2 1个

如您所见,合成参数始终包含在getParameterTypes() ,但仅在使用Eclipse进行编译时才包含在getGenericParameterTypes()

另一方面, getParameterAnnotations()将始终包含合成参数,除非注释了至少一个构造函数参数。

通过此信息,您现在了解了这些方法的结果之间的差异,但是到目前为止,我仍然没有找到确定哪个参数是合成参数的方法,因为尽管您可以对this$X合成做出很好的猜测参数,这是每个内部类都需要的,因此您无法知道将捕获为局部类构造函数的综合参数的非常量捕获变量的数量。

参考: Ceylon Team博客博客中的JCG合作伙伴 Stef Epardaud提供的带有内部类构造函数参数的Java Reflection奇数。

翻译自: https://www.javacodegeeks.com/2013/05/java-reflection-oddities-with-inner-class-constructor-parameters.html

java构造函数内部调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值