[英]Memory allocation when creating new String as literal/new Object
代码:
String s1 = "Hello";
String s2 = new String("Hello");
Field declaredField = String.class.getDeclaredField("value");
declaredField.setAccessible(true);
byte[] arr1 = (byte[])declaredField.get(s1);
byte[] arr2 = (byte[])declaredField.get(s2);
现在,s1 == s2 = False,arr1== arr2 = True。
我的问题是对象如何存储在内存中。
第一行确实在池上创建了一个新的 String 类型对象。 第二行确实在堆上将其创建为常规对象
但是底层的 byte[] 数组是一样的。 这让我想到,JVM 会以某种方式检查这样一个现有的 byte[] 是否已经存在,并将所有引用指向同一个数组。 这是否意味着无论我们使用literal 还是new 关键字,底层数组都缓存在池中?
所以 s = "something" 在池上创建一个新的 String 类型对象以及一个保存数据的底层数组 - 它也在池上创建。
s = new String("something")
-> 在堆上创建 String 类型的对象,但底层数组仍然存储在池中/如果已经存在,则只是创建一个引用。
我的理解正确吗?
注意:这不是关于常量池存储在哪里、实习生如何工作、创建了多少对象或使用不同的创建技术/使用实习生如何影响 == 结果的问题。
你用的是什么java版本? 我在 11 jdk 上检查它,String.value 的类型是 char[]。 所有接下来的话基于 11 JDK 版本。
这种行为的原因是 String 构造函数。
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
如您所见, value
字段是从original
String 对象复制的。 由于您使用"Hello"
作为new String(...)
参数, "Hello"
是从 String 池中获取并传递给构造函数,其中value
字段复制到一个新的 String 对象。
您可以稍微更改代码以达到预期的行为:
String s1 = "Hello";
String s2 = new String("Hell") + "o";
Field declaredField = String.class.getDeclaredField("value");
declaredField.setAccessible(true);
char[] arr1 = (char[])declaredField.get(s1);
char[] arr2 = (char[])declaredField.get(s2);
assert arr1 != arr2;
assert s1.equals(s2);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.