2

I came accross with a snippet that one friend send me. It had a really strange behaviour. I tried google the code to see if I found something in internet but without luck. I can't contact my friend, so I was courious about what it is doing.

    public class Test {

        public static void main(String[] args) throws MalformedURLException {
            System.out.println(Boolean.TRUE); //This prints false
        }

        static {
            try {
                Field value = Boolean.class.getDeclaredField("value");
                value.setAccessible(true);
                value.set(Boolean.TRUE, value.get(Boolean.FALSE));
            } catch (Exception e) {
                throw new AssertionError(e);
            }
        }

    }

I think, like that piece of code it's declared as static, it will run first that the main method, and inside that static code is changing the value of all Boolean instances (?). I don't know, I need an expert opinion to confirm this.

nicael
  • 18,550
  • 13
  • 57
  • 90
4gus71n
  • 3,717
  • 3
  • 39
  • 66
  • The `static` section is a static initialization block, which is executed when the class is first loaded. This block is using a (nasty) piece of reflection to change the value of the static field `TRUE` to equal `false`. Take a look at [initializing fields](http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html) for some more details – MadProgrammer Oct 15 '13 at 01:33

3 Answers3

4
Field value = Boolean.class.getDeclaredField("value");
value.setAccessible(true);
value.set(Boolean.TRUE, value.get(Boolean.FALSE));

Trough reflection the constant value of Boolean.TRUE is set to Boolean.FALSE. That's.. Exactly as you can read in the code.

static initializer blocks are executed before the main method, don't let the order fool you into thinking it happens at a later time.

Quote from this post:

Assuming no SecurityManager is preventing you from doing this, you can use setAccessible to get around private and resetting the modifier to get rid of final, and actually modify a private static final field.

Community
  • 1
  • 1
Jeroen Vannevel
  • 43,651
  • 22
  • 107
  • 170
  • Okey, but isn't the `Boolean.TRUE` and `Boolean.FALSE` constants declared as `final`. So reflection can cheat the `final` keyword? – 4gus71n Oct 15 '13 at 01:38
  • Reflection is the cheatcode of programming: you can get things done that shouldn't be be possible in the first place. – Jeroen Vannevel Oct 15 '13 at 01:39
  • Yeah, I realized a lot of weird thing. First this happens because, both, `Boolean.FALSE` and `Boolean.TRUE` are instances of Boolean, not primitives. If you try this same example with primitives, all will run normal. Also, the `value` field of the `Boolean` object is `final` and isn't initialized, so, somewhere with reflection, the same Boolean class must change his own value field value with. Boy you are weird java [Boolean.java](http://www.docjar.com/html/api/java/lang/Boolean.java.html) – 4gus71n Oct 15 '13 at 01:58
  • @astinx `Boolean.value` is assigned in the constructor `Boolean(boolean)`. Constructors (and initializers) are allowed to assign final fields (once), nothing weird about that. – Dev Oct 15 '13 at 02:09
2

This is because of the order of execution guarentees that static intialisation blocks will be executed before other initialisation for the instance of class. Static initialisation is done when the class is loaded; usually at the first reference of the class.

As the static block changes the value of Boolean.TRUE before the main method is called, it prints the changed value.

Consider the following example (source):

/*
 * Here we will learn to see how the different part (Ananymous Block, Constructor and Static Block ) of class will behave
 * and what would be the order of execution. 
 */
class JBTCLass {

    /*
     * Here Creating the Ananymous Block
     */
    {
        System.out.println("Inside Ananymous Block");
    }

    /*
     * Now Creating the Static Block in Class
     */
    static {
        System.out.println("Inside Static Block");
    }

    /*
     * Here Creating the Constructor of Class
     */
    JBTCLass() {
        System.out.println("Inside Constructor of Class");
    }

    public static void main(String[] args) {

        // Creating the Object of the Class
        JBTCLass obj = new JBTCLass();

        System.out.println("*******************");

        // Again Creating Object of Class
        JBTCLass obj1 = new JBTCLass();

    }

}

Result:

Inside Static Block
Inside Ananymous Block
Inside COnstructor of Class
*******************
Inside Ananymous Block
Inside COnstructor of Class
Craig
  • 1,390
  • 7
  • 12
1
public static final Boolean TRUE = new Boolean(true);

Constant TRUE is a reference point to an object, final means you can't change it to point to another object. Because of you have changed the value constant to false, so now the object value is false.

Leo Xu
  • 11
  • 2