Java字符串引用与new不同,同样没有new

时间:2013-03-12 21:14:19

标签: java string

之前从未使用过Java,我在教自己泛型语法。我用一些字符串测试了简单的泛型函数,并注意到一些有点奇怪的东西:

public class Main {

    public static <T> boolean areSameReference(T lhs, T rhs) {
        return lhs == rhs;
    }

    public static void main(String[] args) {
        String s = new String("test1");
        String t = s;
        String u = new String("test1");

        System.out.println(areSameReference(s, t)); //true
        System.out.println(areSameReference(s, u)); //false

        String v = "test2";
        String w = "test2";
        System.out.println(areSameReference(v, w)); //true
    }
}

为什么[s]和[u]是不同的参考文献,但[v]和[w]是相同的参考文献?我想如果有或没有“new”,字符串文字会导致它们在两种情况下都一致或不同。

我错过了其他的事情吗?

5 个答案:

答案 0 :(得分:4)

  

为什么[s]和[u]是不同的参考,

因为您告诉编译器您想要字符串,不是吗?

答案 1 :(得分:3)

根据JLS 3.10.5

  

字符串文字始终引用类String的相同实例。   这是因为字符串文字 - 或者更常见的是字符串   常量表达式的值(§15.28) - 被“实施”以便   使用String.intern。

方法共享唯一实例
     String v = "test2";
     String w = "test2";

将被视为字符串文字。

当您使用 new 运算符构造String对象时,它会分配新的String对象。

答案 2 :(得分:1)

使用new,您可以调用内存管理系统并获取新对象。

如果没有new,编译器会将字符串内容优化为“.class”常量表中的一个条目,从而导致对“.class”常量表中相同条目的两次访问。

Java中的=比较运算符是一个参考比较运算,因此您将看到这两种技术之间的差异。您可以通过充分使用String.intern(otherString)来隐藏这些差异。

这里带回家的教训是,除非在极端情况下,始终使用.equals(...)与对象进行比较

答案 3 :(得分:1)

JVM保留一个字符串池,这样就不会浪费具有重复字符串的内存。因此,vw应该相同。我猜你所遇到的行为是由new String(String original)构造函数中隐含的契约引起的,这表明它创建了一个新对象(参见http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#String(java.lang.String))。

答案 4 :(得分:1)

String对象是不可变的,其中字符串引用是可变的。定义“s”和“u”时,会创建每个新对象。这里的值无关紧要,因为您调用构造函数,但是当您为不同的String对象分配相同的值时,它们将成为对内存中相同“test2”对象的引用。

我建议在Java中阅读更多有关不可变对象的内容,这里有一篇好文章: http://javarevisited.blogspot.com/2010/10/why-string-is-immutable-in-java.html