这个静态代码如何工作?

时间:2014-11-02 05:34:32

标签: java

代码:

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

此代码如何变更" Hello"和#34;你好"打印时?

3 个答案:

答案 0 :(得分: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.

对于char[]文字String引用的String对象,您using reflection to retrieve "Howdy"。{/ p>

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

并将其分配到char[]文字String

引用的String对象的"Hello"字段
value.set("Hello", value.get("Howdy"));

现在,当您的main方法执行时

String a = new String("Hello");

String文字"Hello"引用之前为其设置char[]字段的同一对象。此char[]包含字符'H''o''w''d''y',因为它来自String文字"Howdy"引用的对象。

这些字符将复制到此处创建的 String对象

String a = new String("Hello"); 

答案 1 :(得分: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

出于同样的原因。

答案 2 :(得分:6)

看看这里:

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

public void set(Object obj,Object value)

  

在指定的对象上设置此Field对象表示的字段   对象参数指定的新值。新的价值是   如果基础字段具有基本类型,则自动解包。

public get(Object obj)

  

返回此字段所代表的字段的值   指定的对象。

首先执行静态块。

在执行main()之前,所有出现的包含“Hello”的String都被字符串“Howdy”替换为反射。

“Hello”和“Howdy”指的是同一个对象。这就是s.equals("Hello")输出为真的原因 System.out.println(a.equals("Howdy"));也会输出true

查看确切的执行过程: enter image description here