Explanation of the principle of synthetic keywords in Java
When I looked at the reflection of JAVA, I saw a synthetic. I was curious about the method isSynthetic (). I just learned about it:
1. Definition
Any constructs introduced by a Java compiler that do not have a corresponding construct in the source code must be marked as synthetic, doesn t for default constructors, the class initialization method, and the values and valueOf methods of the Enum class.
Meaning: methods generated by the java compiler (except for the default constructor class), or classes
2. Instance
Since we know that the synthetic method and the synthetic class are generated by the compiler, how can the compiler generate these things and under what circumstances?
First look at a piece of code:
import static java.lang.System.out;public final class DemonstrateSyntheticMethods{ public static void main(final String[] arguments) { DemonstrateSyntheticMethods.NestedClass nested = new DemonstrateSyntheticMethods.NestedClass(); out.println("String: " + nested.highlyConfidential); } private static final class NestedClass { private String highlyConfidential = "Don't tell anyone about me"; private int highlyConfidentialInt = 42; private Calendar highlyConfidentialCalendar = Calendar.getInstance(); private boolean highlyConfidentialBoolean = true; }}
After compilation, You can see three files:
Among them, the bottom of this class file is a good explanation, that is, our main class, the middle file, is our internal class, the above file, I will talk about it later, let's take a look at the internal class in the middle.
2.1 internal class decompilation results
Decompile DemonstrateSyntheticMethods $ NestedClass. class with javap. The following results are obtained:
javap DemonstrateSyntheticMethods\$NestedClass.classCompiled from "DemonstrateSyntheticMethods.java"final class DemonstrateSyntheticMethods$NestedClass { DemonstrateSyntheticMethods$NestedClass(DemonstrateSyntheticMethods$1);
static java.lang.String access$100(DemonstrateSyntheticMethods$NestedClass);}
Let's put the constructor aside first. Let's look at the method access $100 which is blacklisted. What is the problem? We cannot find this access method in the source file?
2.2 synthetic Method
This method is the synthetic method generated by the compiler. If you do not believe it, you can use method. isSynthetic () to verify it.
Why is this method generated?
As you can see, in our NestedClass class, highConfidential is a private attribute, and we directly reference this attribute in the external class DemonstrateSyntheticMethods. As an internal class, the attributes of NestedClass are referenced by external classes and there is no semantic problem, but this causes the compiler to suffer.
To enable a private variable to be referenced, the compiler generates a package scope access method, which is a get method. When the attribute highConfidential is used in an external class, this access method is actually used.
You can see the direct evidence in javap:
The position of the red box in the figure shows that the main method actually calls the access $100 method.
Therefore, it is clear that the compiler generates a get method to make it easier for private members of internal classes to be referenced by external classes. This can be understood as a trick, the restriction on private member variables is bypassed.
2.3 synthetic class
As mentioned above, the compiler not only generates methods, but also synthetic classes.
Let's look back at the last class called DemonstrateSyntheticMethods $1. class mentioned in 2.1.
This class is a completely empty class. After decompiling, it looks like this:
// $FF: synthetic classclass DemonstrateSyntheticMethods$1 {}
This class only appears once. It serves as the constructor of the package scope of the internal class NestedClass ,:
So what is the role of this class? I checked a lot of information and did not explicitly explain the purpose of this class. I can only speculate based on the Code as follows:
NestedClass is a private class, and its default constructor is private. As a matter of fact, as the DemonstrateSyntheticMethods class of the external class, there is no way to new the internal class object, which is contrary to the semantics we need.
To implement the semantics, the compiler uses a trick and quietly generates a constructor NestedClass (DemonstrateSyntheticMethods $1 obj), which is visible to the package.
Then, the external class can get the internal class object through the new NestedClass (null) method. If you check the main method, you can see the call of this method as shown in.
This is the role of the synthetic class. If we add a public-level default constructor to our NestedClass, we can see that the compiler will not generate this synthetic class.
3. Conclusion
By generating some synthetic methods and classes that do not exist in the source code, the compiler implements access to private-level fields and classes, thus bypassing language restrictions, this is a trick.
In actual production and application, there is basically no need for programmers to consider synthetic.
PS: hereA common example of synthetic exists.
If both Enum and switch are used, for example, an enum enumeration is defined first, and then the switch is used to traverse the enumeration, the java compiler will generate a synthetic array, and the array content is an enum instance.
In this case, I found a document for your reference:
Dynamic Modification of Enum instances using Java
.