开发者社区> 问答> 正文

创建新的String作为文字/新对象时的内存分配

注意:在将其标记为重复之前,请阅读问题。这不是关于常量池存储在何处,实习生如何工作,创建了多少个对象或使用不同的创建技术/使用实习生如何影响==结果的问题。

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 [] arr是相同的。这让我想到,JVM会以某种方式执行此检查以检查是否存在这样的现有byte []并将所有引用都指向相同的arr。这是否意味着无论我们使用文字还是new关键字,底层数组都将缓存在池中?

因此,s =“ something”在池上创建一个新的String类型对象以及一个包含数据的基础数组-该数组也在该池上创建。

s = new String(“ something”)->在堆上创建String类型的对象,但是仍存储在池中的基础数组/如果已经存在,则仅创建引用。

我的理解正确吗?

任何有任何指向好文章的指针的人也将是很好的,因为这困扰了我很长时间:(

问题来源:Stack Overflow

展开
收起
montos 2020-03-23 11:10:21 961 0
1 条回答
写回答
取消 提交回答
  • 您使用什么Java版本?我在11 jdk上检查它,String.value的类型为char []。接下来的所有单词均基于11 JDK版本。

    此行为的原因是String构造函数。

    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
    

    如您所见,该value字段是从originalString对象复制的。由于您使用的"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);
    

    回答来源:Stack Overflow

    2020-03-23 11:11:06
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
内存取证与IaaS云平台恶意行 为的安全监控 立即下载
云服务器ECS内存增强型实例re6全新发布 立即下载
低代码开发师(初级)实战教程 立即下载