Java字符串引用与new不同,与new相同

Java字符串引用与new不同,与new相同,java,string,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 S

我以前从未使用过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
    }
}
公共类主{
公共静态布尔值参考(T lhs,T rhs){
返回lhs==rhs;
}
公共静态void main(字符串[]args){
字符串s=新字符串(“test1”);
字符串t=s;
字符串u=新字符串(“test1”);
System.out.println(areamereference(s,t));//true
System.out.println(areamereference(s,u));//false
字符串v=“test2”;
字符串w=“test2”;
System.out.println(areamereference(v,w));//true
}
}
为什么[s]和[u]是不同的引用,而[v]和[w]是相同的引用?我会认为,无论是否使用“new”,字符串文字都会导致它们在这两种情况下保持相同或不同

我是否错过了这里发生的其他事情?

根据

字符串文本始终引用类字符串的同一实例。 这是因为字符串文字,或者更一般地说,是 常量表达式(§15.28)的值被“插入”以便 使用String.intern方法共享唯一实例

将被视为字符串文本


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

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

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

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


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

JVM保留一个字符串池,这样就不会用重复的字符串浪费内存。因此,
v
w
应该是相同的。我猜您正在经历的行为是由于
新字符串(String original)
构造函数中隐含的契约,这表明它创建了一个新对象(请参阅)

为什么[s]和[u]是不同的引用


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

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

我建议您阅读更多关于Java中不可变对象的内容,这里有一篇好文章:

看看。我就把这个留在这里::-)出于好奇,{String s=new String(“test1”);}为什么不是一个常量表达式?我看到使用了new,但我认为编译器或String类应该足够聪明,能够意识到它是同一个字符串,字符串是不可变的,并且使用同一个引用。@w00te然后会有人过来抱怨,尽管他需要新的引用,但他得到了相同的旧引用。@w00te:Alex,答案可能对您的评论有答案。当您调用新字符串(..)时,根据javadoc,它会创建新对象。公平地说,您是在向JVM请求一个
new
字符串(它似乎在倾听您的声音,因为
new
覆盖了此行为)。谢谢大家的帮助:)+1。如果用户要求新的
字符串
;用户将获得一个新的
字符串
。不要责怪编译器给了程序员明确要求的东西。
     String v = "test2";
     String w = "test2";