2014-11-02 52 views
14

代碼:這個靜態代碼是如何工作的?

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) { } 
} 

結果:

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

請問這個代碼改變 「你好」 到 「你好」 打印時?

+0

一個String對象時,它使用反射來替換每個字符串是「你好」和「你好」。 – 2014-11-02 05:39:41

+0

這真的很有趣!注意,如果你使'String a' * final *會發生什麼。它必須是某種形式的編譯器優化。 – 2014-11-02 05:52:28

+2

相關:[1](http://stackoverflow.com/q/8086065/1391249),[2](http://stackoverflow.com/q/20036436/1391249) – Tiny 2014-11-02 13:33:11

回答

6

看看這裏:

http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Field.html

公共無效集(obj對象,對象的值)

設置由指定的 對象參數此Field對象表示的字段到指定的新值。如果基礎字段具有基元類型,則自動解包新值 。

公共的get(對象OBJ)

返回該字段表示的字段的值,則 指定的對象上。

你的靜態塊首先被執行。

在執行main()之前,所有出現的包含「Hello」的字符串被字符串「Howdy」替換。

「你好」和「你好」是指同一個對象。這就是爲什麼s.equals("Hello")輸出爲真 System.out.println(a.equals("Howdy"));也會輸出true

看一看的確切執行過程: enter image description here

8

出現這種情況是你static塊執行的第一件事。通過反思,它將String a的值更改爲"Howdy"(實際上它將String"Hello"更改爲"Howdy",但具有相同的效果)。但是,您得到

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

因爲編譯器已經用true取代了該值。我跑javap -v並得到了

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

所以這正是發生了什麼事。正如我在評論中指出,如果你改變String a

final String a = "Hello"; 

最後一行更改爲

a --> Hello 

出於同樣的原因。

+0

我沒有看到'final'行爲,你在Java 7中描述它。 – Makoto 2014-11-02 06:14:52

+0

@Makoto我用Java 8測試過。注意,我必須使用'final String a =「Hello」;'not'final String a = new String(「Hello」);'' – 2014-11-02 06:18:52

+1

我認爲一個'String'文字會表現出不同的行爲來使用構造函數。 – 2014-11-02 13:23:26

9

首先,String literals composed of the same characters resolve to the same instance.所以在

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

兩個變量都指的是同一個對象。第二,static initializer blocks are executed when a class is first loaded (and initialized)。這發生在任何類方法被調用之前,即。在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.

using reflection to retrievechar[]String文字"Howdy"引用的String對象。

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

並將其分配給由String字面"Hello"

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

引用現在String對象,當你main方法執行

String a = new String("Hello"); 

String字面"Hello"是的char[]場引用相同的對象爲你你以前設置了char[]字段。此char[]包含字符'H','o','w','d''y',因爲它取自文字爲"Howdy"String對象。

這些字符複製到這裏創建

String a = new String("Hello");