Java-使用new关键字创建String对象

时间:2015-02-10 08:54:57

标签: java string

我知道String literal和新String对象之间的区别,也知道它是如何在内部工作的。但我的问题是稍微提前一点。当我们使用new关键字创建String对象时

String str = new String("test");

在这种情况下,我们传递一个String类型的参数。 我的问题是这个字符串生成的地方 - 堆或字符串常量池还是其他地方?

据我所知,这个参数是一个字符串文字所以它应该在String常量池中。如果它是那么使用intern方法 - 只是链接变量str到恒定池?因为"test"已经可用。

如果我误解了这个概念,请澄清一下。

3 个答案:

答案 0 :(得分:9)

语句String str = new String("test");创建一个字符串对象,它像任何其他对象一样存储在堆上。作为参数传递的字符串文字"test"存储在字符串常量池中。

String#intern()检查字符串池中是否已有字符串常量。如果有一个已经返回它,否则它会创建一个新的并将其存储在池中。请参阅Javadocs

  

返回字符串对象的规范表示。

     

字符串池(最初为空)由类String私有维护。

     

当调用intern方法时,如果池已经包含与equals(Object)方法确定的此String对象相等的字符串,则返回池中的字符串。否则,将此String对象添加到池中,并返回对此String对象的引用。

     

对于任何两个字符串sts.intern() == t.intern()当且仅当s.equals(t)为真时才为真。

从JDK7开始,实习字符串存储在堆上。这来自release notes of JDK7

  

在JDK 7中,实例化的字符串不再分配在Java堆的永久生成中,而是分配在Java堆的主要部分(称为年轻和旧的代),以及创建的其他对象通过申请。此更改将导致更多数据驻留在主Java堆中,并且永久生成中的数据更少,因此可能需要调整堆大小。由于此更改,大多数应用程序只会看到堆使用中的相对较小的差异,但是加载许多类或大量使用String.intern()方法的较大应用程序将看到更显着的差异。

答案 1 :(得分:7)

使用intern()

public static void main(String[] args) throws IOException {
    String s = new String(new char[] { 'a', 'b', 'c' }); // "abc" will not be added to String constants pool.
    System.out.println(System.identityHashCode(s));
    s = s.intern();// add s to String constants pool
    System.out.println(System.identityHashCode(s));

    String str1 = new String("hello");
    String str2 = "hello";
    String str3 = str1.intern();
    System.out.println(System.identityHashCode(str1));
    System.out.println(System.identityHashCode(str2));
    System.out.println(System.identityHashCode(str3));
}

O / P:

1414159026
1569228633 --> OOPs String moved to String constants pool

778966024
1021653256 
1021653256 --> "hello" already added to string pool. So intern does not add it again.

答案 2 :(得分:3)

当您使用String str = new String("test");时,它将创建两个对象和一个引用变量。在这种情况下,JVM将在普通(非池)堆内存中创建一个新的字符串对象,文字"test"将放在字符串常量池中。变量str将引用堆中的对象(非池)。