This source outputs G'Day Mate.
How this is happening ?
public static void main(String args[]) {
System.out.println("Hello World");
}
static {
try {
Field value = String.class.getDeclaredField("value");
value.setAccessible(true);
value.set("Hello World", value.get("G'Day Mate."));
} catch (Exception e) {
throw new AssertionError(e);
}
}
And if we change main functions "Hello World"
to new String("Hello World")
:
System.out.println(new String("Hello World"));
It outputs Hello world
.
What is happening actually?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With