Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does this static code work? [duplicate]

Tags:

java

Code:

public static void main ( String[] args){
      String a = new String("Hello");
      String b = " pardner.";
      System.out.println(a+b);
      System.out.println("a.equals(\"Hello\") --> " + (a.equals("Hello")));
      System.out.println("a --> " + a);
}

static {
      try {
          Field value = String.class.getDeclaredField("value");
          value.setAccessible(true);
          value.set("Hello", value.get("Howdy"));
      } catch (Exception e) { }
}

Result:

Howdy pardner.
a.equals("Hello") --> true
a --> Howdy

How does this code change "Hello" to "Howdy" when printing?

like image 676
plue Avatar asked Nov 02 '14 05:11

plue


People also ask

What is meant by code duplication?

Simply put, it's when a snippet of code appears multiple times throughout a codebase. It happens for many reasons: Somebody wanted to reuse a function in a different class, and copy-paste was the quickest solution.

What does duplicated code fragment mean?

Code Inspection: Duplicated code fragmentReports duplicated blocks of code from the selected scope: the same file or the entire project. The inspection features quick-fixes that help you to set the size of detected duplicates, navigate to repetitive code fragments, and compare them in a tool window.

What is duplicate code in SonarQube?

SonarQube detects duplications in files and projects and also across projects. SonarQube reports duplication by line, block, and file. If you've lived through this type of situation, you already know that duplicate code is one of the highest risk factors for bug propagation.


2 Answers

First, String literals composed of the same characters resolve to the same instance. So in

String one = "hello";
String two = "hello";

both variables are referring to the same object.

Second, static initializer blocks are executed when a class is first loaded (and initialized). This occurs before any class methods are invoked, ie. before main.

Third, your Java version's implementation of String, presumably, uses a char\[\] field to store the string of characters. This field is named value.

You're using reflection to retrieve this char[] for the String object referenced by the String literal "Howdy".

Field value = String.class.getDeclaredField("value");
...
value.get("Howdy")

and assigning it to the char[] field of the String object referenced by the String literal "Hello"

value.set("Hello", value.get("Howdy"));

Now, when your main method executes

String a = new String("Hello");

the String literal "Hello" is referencing the same object for which you set the char[] field previously. This char[] contains the characters 'H', 'o', 'w', 'd', and 'y' since it was taken from the String object referenced by the literal "Howdy".

These characters are copied into a new String object created here

String a = new String("Hello"); 
like image 52
Sotirios Delimanolis Avatar answered Oct 29 '22 01:10

Sotirios Delimanolis


The first thing that happens is your static block executes. By reflection, it changes the value of String a to "Howdy" (actually it changes the String "Hello" to "Howdy" but that has the same effect). However, you get

a.equals("Hello") --> true

because the compiler has already replaced the value with true. I ran javap -v and got

31: ldc           #75                 // String a.equals(\"Hello\") --> true

So that is exactly what has happened. As I noted in the comments, if you change String a to

final String a = "Hello";

The last line changes to

a --> Hello

for the same reason.

like image 41
Elliott Frisch Avatar answered Oct 29 '22 01:10

Elliott Frisch