Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying final fields in Java

Let's start with a simple test case:

import java.lang.reflect.Field;  public class Test {   private final int primitiveInt = 42;   private final Integer wrappedInt = 42;   private final String stringValue = "42";    public int getPrimitiveInt()   { return this.primitiveInt; }   public int getWrappedInt()     { return this.wrappedInt; }   public String getStringValue() { return this.stringValue; }    public void changeField(String name, Object value) throws IllegalAccessException, NoSuchFieldException {     Field field = Test.class.getDeclaredField(name);     field.setAccessible(true);     field.set(this, value);     System.out.println("reflection: " + name + " = " + field.get(this));   }    public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {     Test test = new Test();      test.changeField("primitiveInt", 84);     System.out.println("direct: primitiveInt = " + test.getPrimitiveInt());      test.changeField("wrappedInt", 84);     System.out.println("direct: wrappedInt = " + test.getWrappedInt());      test.changeField("stringValue", "84");     System.out.println("direct: stringValue = " + test.getStringValue());   } } 

Anybody care to guess what will be printed as output (shown at the bottom as to not spoil the surprise immediately).

The questions are:

  1. Why do primitive and wrapped integer behave differently?
  2. Why does reflective vs direct access return different results?
  3. The one that plagues me most - why does String behave like primitive int and not like Integer?

Results (java 1.5):

reflection: primitiveInt = 84 direct: primitiveInt = 42 reflection: wrappedInt = 84 direct: wrappedInt = 84 reflection: stringValue = 84 direct: stringValue = 42 
like image 629
ChssPly76 Avatar asked Oct 23 '09 18:10

ChssPly76


People also ask

Can we modify final variable in Java?

Final variable in Java cannot be changed. Once if we have assigned the final variable it can not be changed it is fixed. but if you have declare a blank final variable then you can assign value to it only in constructor.

How do I change the value of the final static variable in Java?

In Java, non-static final variables can be assigned a value either in constructor or with the declaration. But, static final variables cannot be assigned value in constructor; they must be assigned a value with their declaration.

How can a final field be set to a value?

When a field is defined as final , it has to be initialised when the object is constructed, i.e. you're allowed to assign value to it inside a constructor. A static field belongs to the class itself, i.e. one per class. A static final field is therefore not assignable in the constructor which is one per object.


1 Answers

Compile-time constants are inlined (at javac compile-time). See the JLS, in particular 15.28 defines a constant expression and 13.4.9 discusses binary compatibility or final fields and constants.

If you make the field non-final or assign a non-compile time constant, the value is not inlined. For instance:

private final String stringValue = null!=null?"": "42";

like image 63
Tom Hawtin - tackline Avatar answered Sep 22 '22 01:09

Tom Hawtin - tackline