Java == for String对象停止工作?
public class Comparison { public static void main(String[] args) { String s = "prova"; String s2 = "prova"; System.out.println(s == s2); System.out.println(s.equals(s2)); } }
输出:
true true
在我的机器上。 为什么? 不应该==比较对象引用相等?
因为 String
实例是不可变的 ,所以Java语言能够进行一些优化,从而实现String
文字(或更一般地,其值为编译时常量的String
)实际上并且实际引用相同的(即==
)对象。
JLS 3.10.5字符串文字
每个字符串文字都是对
class String
实例的引用。String
对象具有常量值。 字符串文字 – 或者更一般地说,作为常量表达式的值的字符串 – 是“interned”,以便使用String.intern
方法共享唯一的实例。
这就是您获得以下内容的原因:
System.out.println("yes" == "yes"); // true System.out.println(99 + "bottles" == "99bottles"); // true System.out.println("7" + "11" == "" + '7' + '1' + (char) (50-1)); // true System.out.println("trueLove" == (true + "Love")); // true System.out.println("MGD64" == "MGD" + Long.SIZE);
也就是说,需要说你不应该依赖于==
进行String
比较,并且应该使用equals
作为非null
instanceof String
。 特别是,不要试图使用intern()
所有的String
,这样你就可以使用==
而不知道字符串实习是如何工作的。
相关问题
- Java String.equals与==
- 字符串对象和字符串文字之间的区别
- 与字符串文字相比,字符串对象的优点是什么
- 使用java.lang.String.intern()是一种好习惯吗?
关于new String(...)
如果由于某些特殊原因你需要创建两个 String
对象 (因此根据定义不是==
),并且是equals
,那么除了其他方面,你可以使用这个构造函数:
public String(String original)
:初始化一个新创建的String
对象,使其表示与参数相同的字符序列; 换句话说,新创建的字符串是参数字符串的副本。 除非需要显式的原始副本,否则不必使用此构造函数,因为Strings
是不可变的 。
因此,您可以:
System.out.println("x" == new String("x")); // false
new
运算符总是创建一个新对象,因此上面保证打印为false
。 也就是说,这通常不是你真正需要做的事情。 只要有可能,您应该只使用字符串文字而不是为它显式创建new String
。
相关问题
- Java字符串:“String s = new String(”傻“);”
- Java中表达式“new String(…)”的目的是什么?
JLS,3.10.5 =>保证在同一个虚拟机中运行的任何其他代码将重复使用文字字符串对象,该代码恰好包含相同的字符串文字
如果显式创建新对象, ==
返回false:
String s1 = new String("prova"); String s2 = new String("prova"); System.out.println(s1 == s2); // returns false.
否则JVM可以使用相同的对象,因此s1 == s2将返回true。
确实如此。 但是字符串文字被合并,因此"prova"
返回相同的实例。
String s = "prova"; String s2 = "prova";
s
和s2
是文字字符串,它们指向JVM字符串池中的同一对象,因此比较返回true。
是的,“prova”存储在java内部字符串池中,因此它的引用相同。
源代码文字是常量池的一部分,因此如果同一个文字出现多次,它将在运行时成为同一个对象。
JVM可以优化String的使用,以便在内存中只有一个“相等”的String实例。 在这种情况下,==运算符也将返回true。 但不要指望它。
您必须了解“==”比较引用,“等于”比较值。 s
和s1
都指向相同的字符串文字,因此它们的引用是相同的。
在java代码中放入文字字符串时,编译器会自动对该字符串进行实例化,即创建一个静态全局实例。 或者更具体地说,它被放入一个实习字符串表中。 内容方面完全相同的任何其他引用字符串将引用相同的实习字符串。
所以在你的代码中,s和s2 是相同的字符串
理想情况下,它不应该永远发生。 因为java规范保证了这一点。 所以我认为它可能是JVM中的错误,你应该向sun microsystems报告。