Java Reflection-Modify the private final member variable value, how much do you know?

Source: Internet
Author: User

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?

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.