这个静态代码如何工作?

plu*_*lue 14 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) { }
}
Run Code Online (Sandbox Code Playgroud)

结果:

Howdy pardner.
a.equals("Hello") --> true
a --> Howdy
Run Code Online (Sandbox Code Playgroud)

打印时,此代码如何将"Hello"更改为"Howdy"?

Sot*_*lis 9

首先,String由相同字符组成的文字解析为同一个实例.所以

String one = "hello";
String two = "hello";
Run Code Online (Sandbox Code Playgroud)

两个变量都指的是同一个对象.

其次,static初始化块在首次加载(并初始化)类时执行.这在调用任何类方法之前发生,即.之前main.

第三,您的Java版本的实现String可能使用char\[\]字段来存储字符串.此字段已命名value.

您正在使用反射来检索char[]String被引用的对象String字面"Howdy".

Field value = String.class.getDeclaredField("value");
...
value.get("Howdy")
Run Code Online (Sandbox Code Playgroud)

并将其分配给文字引用char[]String对象的字段String"Hello"

value.set("Hello", value.get("Howdy"));
Run Code Online (Sandbox Code Playgroud)

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

String a = new String("Hello");
Run Code Online (Sandbox Code Playgroud)

String文字"Hello"中引用了你设置了相同的对象char[]先前场.这char[]包含字符'H','o','w','d',和'y'因为它是取自String通过字面引用的对象"Howdy".

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

String a = new String("Hello"); 
Run Code Online (Sandbox Code Playgroud)


Ell*_*sch 8

首先发生的是你的static块执行.通过反射,它改变了String ato 的值"Howdy"(实际上它改变了String "Hello"to "Howdy"但具有相同的效果).但是,你明白了

a.equals("Hello") --> true
Run Code Online (Sandbox Code Playgroud)

因为编译器已经用该值替换了true.我跑了javap -v,得到了

31: ldc           #75                 // String a.equals(\"Hello\") --> true
Run Code Online (Sandbox Code Playgroud)

所以这就是发生的事情.正如我在评论中指出的那样,如果你String a改为

final String a = "Hello";
Run Code Online (Sandbox Code Playgroud)

最后一行更改为

a --> Hello
Run Code Online (Sandbox Code Playgroud)

出于同样的原因.


Pie*_*ard 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)

返回指定对象上此Field表示的字段的值.

首先执行静态块.

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

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

看一下确切的执行过程: 在此输入图像描述