How can synthetic fields be created in Java?
Can synthetic fields in java only be created at runtime? If not: Is there a standard-compliant way to this at compile time (without changing some bytes in the class file)
问题:
回答1:
They're created by the compiler when "oddities" of the language require them. A simple example of this is using an inner class:
public class Test
{
class Inner
{
}
}
The Test.Inner
class will have a synthetic field to represent the appropriate instance of the Test
class.
We can extend this code slightly to show that field:
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
{
}
}
With my compiler, that prints:
this$0: true
回答2:
Yes, it's doable, and it's called load-time weaving. Essentially, you will need to define your own ClassLoader that will decide on a class-by-class case whether to do modify a classfile that is bout to be loaded; that means you will need to inspect the binary class that is being loaded, possibly modify it, then pass it on to the JVM for definition/resolving. It's a bit cumbersome, complicated, and prone to ClassCastExceptions (the same class defined in 2 different classloaders will give 2 different classes that are not assignment-compatible).
Note that weaving allows you to do much more: you can add new methods, interfaces, fields, modify the code of existing classes, and more.
There are already tools that can help you - see for example AspectJ as a full-on language modification, or something like BCEL or javassist that allows you to write such weaving tools.