Tag: Cannot perform reflection ring PAC his private SSE constructor
We all know that using Java reflection can dynamically change the behavior of an object at run time, even private final member variables, but not all cases, you can modify the member variable. Give a few small examples today.
- Basic data types
- String type
- Integer type
- Summarize
First look at the basic types of modifications:
/**@author*/Publicclass reflectionusage { Private Final int age=18; Public int Getage () { return age ; } }
Test code:
ImportJava.lang.reflect.Field;/** * @authorcool-coding 2018/5/15*/ Public classReflectiontest { Public Static voidMain (string[] args) {Try{Class Reflectionusage= Class.forName ("Practise.practise.ReflectionUsage"); Reflectionusage o=(Reflectionusage) reflectionusage.newinstance (); Field Age= Reflectionusage.getdeclaredfield ("Age"); Age.setaccessible (true); Age.set (O,68); Age.setaccessible (false); System.out.println (O.getage ()); } Catch(ClassNotFoundException e) {e.printstacktrace (); } Catch(nosuchfieldexception e) {e.printstacktrace (); }Catch(Illegalaccessexception |instantiationexception e) { } }}
Run Result: 18
Member variable age cannot be modified at this time.
What happens if you put the initialization age into the constructor:
/** * @ Author cool-coding 2018/5/15 */ Span style= "COLOR: #0000ff" >public class reflectionusage { private final Span style= "COLOR: #0000ff" >int age; public Reflectionusage () { this . Age=18; public int Getage () { return age; }}
What happens when we execute refectiontest? will find that the result becomes 68.
Why is this happening? Take a look at the different class files generated in these two cases:
Direct initialization:
Public class reflectionusage { privatefinalint age =; Public Reflectionusage () { } publicint getage () { return }}
Constructor in the initialization:
Public class reflectionusage { privatefinalint age =; Public Reflectionusage () { } publicint getage () { return this. age; }}
It can be seen that if you initialize directly, the compiled Getage method returns the constant value directly, and when initialized in the constructor, the value of the This.age variable is returned.
Then look at the modification of the string type:
/**@author*/Publicclass reflectionusage { Privatefinal String reflectionstring= "reflectionstring"; Public String getreflectionstring () { return reflectionstring; }}
Test code:
ImportJava.lang.reflect.Field;/** * @authorcool-coding 2018/5/15*/ Public classReflectiontest { Public Static voidMain (string[] args) {Try{Class Reflectionusage= Class.forName ("Practise.practise.ReflectionUsage"); Reflectionusage o=(Reflectionusage) reflectionusage.newinstance (); Field reflectionstring= Reflectionusage.getdeclaredfield ("reflectionstring"); Reflectionstring.setaccessible (true); Reflectionstring.set (O,"Newreflectionstring"); Reflectionstring.setaccessible (false); System.out.println (O.getreflectionstring ()); } Catch(ClassNotFoundException e) {e.printstacktrace (); } Catch(nosuchfieldexception e) {e.printstacktrace (); }Catch(Illegalaccessexception |instantiationexception e) { } }}
Running result:reflectionstring
What if you put the initialization reflectionstring in the constructor?
/** * @ Author cool-coding 2018/5/15 */ Span style= "COLOR: #0000ff" >public class reflectionusage { private final Span style= "COLOR: #000000" > String reflectionstring; public Reflectionusage () { this . reflectionstring= "reflectionstring" ; public String getreflectionstring () { /span>return reflectionstring; }}
Running result:newreflectionstring
Why the results are different, look at the class file:
Direct initialization:
Public class reflectionusage { privatefinal String reflectionstring = "reflectionstring"; public reflectionusage () { } public String getreflectionstring ( { return "reflectionstring"; }}
Constructor in the initialization:
Public class reflectionusage { privatefinal String reflectionstring = "reflectionstring"; public reflectionusage () { } public String getreflectionstring () { return This . reflectionstring; }}
It can be seen that, like a primitive type, when initialized directly, the compiler replaces the place where reflectionstring appears, replacing it with a constant value, while the constructor does not replace it with initialization.
Then look at the changes to the integer:
/**@author*/Publicclass reflectionusage { Privatefinal Integer age=18; Public Integer getage () { return age ; }}
Test code:
ImportJava.lang.reflect.Field;/** * @authorcool-coding 2018/5/15*/ Public classReflectiontest { Public Static voidMain (string[] args) {Try{Class Reflectionusage= Class.forName ("Practise.practise.ReflectionUsage"); Reflectionusage o=(Reflectionusage) reflectionusage.newinstance (); Field reflectionstring= Reflectionusage.getdeclaredfield ("Age"); Reflectionstring.setaccessible (true); Reflectionstring.set (O,68); Reflectionstring.setaccessible (false); System.out.println (O.getage ()); } Catch(ClassNotFoundException e) {e.printstacktrace (); } Catch(nosuchfieldexception e) {e.printstacktrace (); }Catch(Illegalaccessexception |instantiationexception e) { } }}
Operation Result:
You can see that after initializing the private final Integer age variable directly, unlike the base type and the string type, it is not possible to modify, for what reason, look at the class file.
Public class reflectionusage { privatefinal Integer age = integer.valueof; Public Reflectionusage () { } public Integer getage () { return This . Age; }}
You can see that the compiler has not replaced the variable in getage with a constant.
When you see an integer assignment, the compiler automatically boxed it, and if you initialize the string variable, you can modify it by using the String.value () method, and look at it.
/** * @ Author cool-coding 2018/5/15 */ Span style= "COLOR: #0000ff" >public class reflectionusage { private final String reflectionstring = string.valueof ("reflectionstring" public Reflectionusage () {} public String getreflectionstring () { return this
Running result:newreflectionstring
As you can see, the value of reflectionstring has been modified to look at the class file:
Package practise.practise; Public class reflectionusage { privatefinal String reflectionstring = string.valueof (" Reflectionstring "); Public Reflectionusage () { } public String getreflectionstring () { Returnthis. reflectionstring;} }
The visible compiler does not replace the variable in the Getreflectionstring method.
What if the integer type variable is initialized in the constructor?
Public class reflectionusage { privatefinal Integer age; Public Reflectionusage () { this. age=18; } Public Integer getage () { returnthis. age; }}
Operation Result:
The age value has also been changed to look at the class file:
Public class reflectionusage { privatefinal Integer age = integer.valueof; Public Reflectionusage () { } public Integer getage () { return This . Age; }}
The generated class file is the same as the direct initialization.
Summarize:
Final can modify the class, variable, method, non-inheritable, non-modifiable, non-overwriting (override), which discusses the use of reflection to modify the private final decoration of the member variable case, when private final modifies the underlying type of direct initialization or string ( Note When you cannot use string.valueof () initialization, you cannot modify the value of a variable by using reflection, and you can modify it in other cases. This also tells us that at the time of development, if you want to define constants, add the private final decoration to the primitive type int or string type, so that the compiler will replace these variables wherever they appear at compile time to avoid being maliciously modified.
Java Reflection-Modify the private final member variable value, how much do you know?