Java Puzzle with reflection and String

喜欢而已 提交于 2019-11-30 06:52:08
MD. Sahib Bin Mahboob

This source code opens up some interesting techniques of java. Let's examine one by one.

At first we need to understand the flow of the code. Which part of the code will execute first?

The Static Initialization Block. Why? Let's consult with Java Language Specification (12.4) :

Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class.

And when does it occur? Again from JLS (12.4.1):

T is a class and a static method declared by T is invoked.

So we can come to the conclusion that static initiazlier will execute first before the main method.

Now, these two lines are using reflection:

Field value = String.class.getDeclaredField("value");
value.setAccessible(true);

We can break the fist line into two lines for simplicity:

Class<String> c = String.class;
Field value = c.getDeclaredField("value");

The first line is retrieving the Reflected Class Object and the second line is retrieving a Field which represents the value field of the String class.

value.setAccessible(true) indicates that the reflected class object should suppress Java language access checking when it is used.(Reference).

Next line under question is

value.set("Hello World", value.get("G'Day Mate."));

If we dive into .set() documenation we can see that we are calling the set(Object aObject,Object value) version of set. value.get("G'Day Mate.") is returning "G'Day Mate."'s value field's value which is actually a char[]. And with the call of set it replaces the value of "Hello World" object's value field with "G'Day Mate." object's value field.

The static block's code is explained.

Lets dive into main funciton. It's pretty simple. It should output Hello, world. But it is outputting G'Day Mate. Why? Because the Hello, world String object we created in the static initializer is the same as Hello, world object we are using in main function. Consulting with JLS again will shed light on it

Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.

This answer can help you to understand the fact more concisely.

So it is showing different value as we have already changed Hello,world object's value to G'Day, Mate.

But if you use new String("Hello world") in main function it will directly create a fresh instance of String rather than checking into its pool. So Hello world of main function would be differnt than Hello world of static initializer of which we have changed the value.

As new String("Hello World") creates new Object in Heap rather than using previously created "Hello World" Object in String Constant Pool.

So, If you write

System.out.print(new String("Hello World").intern());

it will show output as G'Day, Mate. because intern() method return reference id of a string instance from String Constant Pool.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!