有什么办法,使用反射来确定静态final字段是否具有'='值(以便该值在访问时将被内联)或者其值是否由静态初始化程序分配? 如果该字段确实有值,是否有任何方法来检索该值而不使用Field.get方法(并因此导致静态初始化程序被执行)?使用反射,我可以确定Java静态最终字段是否内置?
3
A
回答
1
该字段只有在编译时间常数时才会“内联” - 请参阅JLS中冗长的定义。
所以它是不够的,它是在宣布时分配。 这不是一个编译时间常数,虽然有效声明:
static final int INT_CONST = compute();
static int compute() {
return 5;
}
只需通过反射,你无法确定该领域的初始化。
要访问类字段的任何值,该类需要首先加载,因此无法阻止静态初始化程序运行。
1
您不能反映这样做,但你可以做到这一点使用字节码工程库像ASM:
public class AsmTest {
static final int a = 2; // constant
static final String b = "string"; // constant
static final String c = "foo "+"bar"; // constant: concatenation is allowed
static final String d = " foobar ".trim(); // not constant: method called
public static Object getFieldConstantValue(Class<?> clazz, final String field) {
try(InputStream is = clazz.getResourceAsStream(clazz.getSimpleName()+".class")) {
final Object[] value = {null};
new ClassReader(is).accept(new ClassVisitor(Opcodes.ASM5) {
@Override
public FieldVisitor visitField(int access, String name, String desc,
String sig, Object val) {
if(name.equals(field))
value[0] = val;
return null;
}
}, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
return value[0];
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
for(String name : new String[] {"a", "b", "c", "d"}) {
System.out.println(name+"="+getFieldConstantValue(AsmTest.class, name));
}
}
}
输出:
a=2
b=string
c=foo bar
d=null
相关问题
- 1. 无法使用java反射更改静态最终字段?
- 2. 使用“最终静态”还是“静态最终”是否正确?
- 3. 使用Java反射的Android更改私有静态最终字段?
- 4. 是否可以使用最终的静态类方法?
- 5. ==还是比较最终静态字段
- 6. 从静态类内使用反射获取所有字段
- 7. 我可以在ejb 3.1单例中定义一个非最终静态字段:
- 8. 强制Java编译器不要内联最终静态字段
- 9. 是否可以使用反射来设置静态类的静态私有成员?
- 10. Kotlin中Java静态最终字段的等价物是什么?
- 11. 最终静态字段的值可以在android中更改吗?
- 12. 是否可以调试Java反射?
- 13. 机器人:改变私有静态最终使用场Java反射
- 14. 确定反射类型是否可以投射到另一种反射类型
- 15. 使用Java反射,我可以访问私有静态嵌套类的私有字段吗?
- 16. 设置静态事件使用反射
- 17. 我是否正确使用静态?
- 18. 确定是否可以为给定值分配反射属性
- 19. 确定一个字段是I型创建,使用反射
- 20. Java SE的静态最终
- 21. 最终静态可以更改吗?
- 22. 使用反射获取类型的静态字段值
- 23. 使用反射,我可以列出#region中的字段?
- 24. 为什么我们可以有静态最终成员,但不能在内部类中使用静态方法?
- 25. 我可以使用Java反射获取方法字段名称吗?
- 26. 初始化Java中的静态最终字段
- 27. 通过反射获取一个类的公共静态最终字段/属性的值在Java中
- 28. 是否可以在Java中扩展非静态内部类?
- 29. 我是否以正确的方式使用静态?
- 30. 我可以使用VS2010 PrivateObject访问静态类中的静态字段吗?
感谢这个,ASM听起来像一个不错的选择。我假设ASM代码不会导致执行静态初始化程序? –
@RobertSales,不,它只是读取它作为'byte []'数组。这样它可以读取任何类,即使它没有加载到应用程序中。 –