【发布时间】:2010-07-21 10:09:34
【问题描述】:
如何在 Java 中创建合成字段?
java 中的合成字段只能在运行时创建吗? 如果没有:在编译时是否有符合标准的方法(不更改类文件中的某些字节)
【问题讨论】:
-
为什么要手动创建合成字段?这有点违反它的规范,因为它说“这是编译器为启用某些特定行为所做的事情”。您想要手动执行的任何操作都应该对外部可见。
标签: java reflection
如何在 Java 中创建合成字段?
java 中的合成字段只能在运行时创建吗? 如果没有:在编译时是否有符合标准的方法(不更改类文件中的某些字节)
【问题讨论】:
标签: java reflection
当语言的“奇怪”需要它们时,它们由编译器创建。一个简单的例子是使用内部类:
public class Test
{
class Inner
{
}
}
Test.Inner 类将有一个合成字段来表示 Test 类的适当实例。
我们可以稍微扩展这段代码以显示该字段:
import java.lang.reflect.*;
public class Test
{
public static void main(String[] args)
{
for (Field field : Inner.class.getDeclaredFields())
{
System.out.println(field.getName() + ": " + field.isSynthetic());
}
}
class Inner
{
}
}
使用我的编译器,会打印:
this$0: true
【讨论】:
是的,它是可行的,它被称为加载时编织。本质上,您将需要定义自己的 ClassLoader,它将逐个决定是否修改即将加载的类文件;这意味着您将需要检查正在加载的二进制类,可能对其进行修改,然后将其传递给 JVM 以进行定义/解析。这有点麻烦、复杂,并且容易出现 ClassCastExceptions(在 2 个不同的类加载器中定义的同一个类会给出 2 个不兼容赋值的不同类)。
请注意,编织允许您做更多事情:您可以添加新方法、接口、字段、修改现有类的代码等等。
已经有一些工具可以为您提供帮助 - 例如,将 AspectJ 视为一种全面的语言修改,或者像 BCEL 或 javassist 之类的允许您编写此类编织工具的工具。
【讨论】:
如何在 Java 中创建合成字段?
synthetic 字段由 Java 编译器自动创建,在某些特定情况下。
例子:
帮助处理 Java assert 关键字 - java.awt.AWTKeyStroke.$assertionsDisabled
帮助处理java this关键字 - java.util.AbstractList$Itr.this$0
匿名内部类中的字段 - java.util.AbstractList$SubList$1.val$index
帮助处理枚举字段 - java.nio.file.attribute.AclEntryFlag.$VALUES
java中的合成字段只能在运行时创建吗?如果没有:在编译时是否有符合标准的方法(不更改类文件中的某些字节)
synthetic 是由 Java 编译器在编译时生成的。 .class 文件已包含 ACC_SYNTHETIC 标志。虽然我们总是可以在运行时生成 Java 字段。
【讨论】: