【发布时间】:2016-06-05 02:42:27
【问题描述】:
现在我正在实现一个方法,它有一个 Class 类型的参数,如果给定的类对象需要它的封闭类的实例来实例化,则此方法返回一个布尔值。
此方法目前的工作方式如下:
if (clazz.getEnclosingClass() == null) {
return false;
}
if (clazz.isAnonymousClass() || clazz.isMemberClass()) {
return !Modifier.isStatic(clazz.getModifiers());
}
if (clazz.getEnclosingConstructor() != null) {
return true;
}
final Method enclosingMethod = clazz.getEnclosingMethod();
if (enclosingMethod != null) {
return !Modifier.isStatic(enclosingMethod.getModifiers());
}
解释为什么这样设计:
- 它首先检查它是否是顶级类,如果是,算法可以安全地返回 false
- 如果类是匿名类或成员类,则如果它不是静态的,则需要关闭实例(如果在静态构造函数/方法/初始化程序块中声明任何类,则它自动为静态)
- 现在可以假定该类是本地类(不考虑数组和原语),因此它在构造函数、方法或初始化程序中定义。但是,与匿名类不同的是,本地类从不被视为静态类,但如果本地类定义在非静态块中,则仍需要封闭实例。
- 构造函数永远不是静态的,所以在这种情况下返回 true
- 如果在方法中定义,如果方法不是静态的,则返回 true
我需要第 6 步来确定本地类是驻留在静态初始化程序块还是实例初始化程序块中,所以我完成了这个函数的实现。
所以这就是反射 API 有点不足的地方。反射包中没有Class.getEnclosingInitializer()之类的方法,也没有代表初始化器的类。
初始化块不是类的成员吗?在 java 1.8 规范中,Member 接口只有实现类 Field、Executable(带有子类 Constructor 和 Method),然后是 MemberName,它超出了大多数反射用户的范围。
我不确定规范背后的人是否忘记了这种情况,如果在静态方法/初始化程序(如匿名类)中声明,本地类实际上应该是静态的。但在我看来,从这个角度来看,它缺乏最后一点一致性。
那么有没有人知道如何确定本地类是在哪种类型的初始化程序块中声明的?
我并不热衷于挖掘字段以寻找与其封闭类相等的类型的合成类型,或者循环遍历它的构造函数以获得类似的东西(旁注:来自Constructor.getParameters() 的参数对象总是在 @ 上返回 false 987654324@ 和 isSynthetic() 无论我尝试什么......这似乎是错误的)。所以,如果我能避免这样的解决方案,那就太好了。
【问题讨论】:
-
看起来更像是讨论而不是问题。
-
嗯,我需要一种方法来确定 X,而使用方法 Y 是我希望避免的,所以我的问题是“什么是方法 Z 来确定我不知道的 X?”。
标签: java class reflection static