这段代码将一个字符串分离为令牌,并将它们存储在一个字符串数组中,然后将一个变量与第一个home…为什么它不工作?
public static void main(String...aArguments) throws IOException {
String usuario = "Jorman";
String password = "14988611";
String strDatos = "Jorman 14988611";
StringTokenizer tokens = new StringTokenizer(strDatos, " ");
int nDatos = tokens.countTokens();
String[] datos = new String[nDatos];
int i = 0;
while (tokens.hasMoreTokens()) {
String str = tokens.nextToken();
datos[i] = str;
i++;
}
//System.out.println (usuario);
if ((datos[0] == usuario)) {
System.out.println("WORKING");
}
}
满足Jorman
Jorman是一个成功的商人,他有两套房子。
但其他人并不知道。
还是那个乔曼吗?
当你问麦迪逊街或伯克街的邻居时,他们唯一能说的就是:
仅从住所来看,很难确定是同一个人。因为他们是两个不同的地址,所以很自然地假设他们是两个不同的人。
这就是运算符==的行为。它会说datos[0]==usuario是假的,因为它只比较地址。
一个救援的调查员
如果我们派个调查员去呢?我们知道是同一个乔曼,但我们需要证明。我们的警探会仔细检查身体的各个方面。通过彻底的调查,代理人将能够得出结论,是否是同一个人。让我们看看它在Java术语中的情况。
下面是String的equals()方法的源代码:
它逐个字符地比较字符串,以便得出它们确实相等的结论。
这就是String =方法的行为。因此datos[0].equals(通常)将返回true,因为它执行逻辑比较。
It's good to notice that in some cases use of "==" operator can lead to the expected result, because the way how java handles strings - string literals are interned (see String.intern()) during compilation - so when you write for example "hello world" in two classes and compare those strings with "==" you could get result: true, which is expected according to specification; when you compare same strings (if they have same value) when the first one is string literal (ie. defined through "i am string literal") and second is constructed during runtime ie. with "new" keyword like new String("i am string literal"), the == (equality) operator returns false, because both of them are different instances of the String class.
唯一正确的方法是使用.equals() -> datos[0].equals(通常)。==表示仅当两个对象是object的相同实例(即。内存地址相同)
更新:01.04.2013我更新了这篇文章,因为下面的评论是正确的。最初我声明实习(String.intern)是JVM优化的副作用。虽然它确实节省了内存资源(这就是我所说的“优化”),但它是语言的主要特征
我知道这是一个老问题,但我是这样看的(我觉得很有用):
技术的解释
在Java中,所有变量都是基本类型或引用。
(如果你需要知道什么是引用:“对象变量”只是指向对象的指针。Object something =…,某些东西实际上是内存中的一个地址(一个数字)。
==比较准确的值。因此,它比较原始值是否相同,或者引用(地址)是否相同。这就是为什么==经常在string上不起作用;字符串是对象,对两个字符串变量执行==只是比较内存中地址是否相同,正如其他人指出的那样。equals()调用对象的比较方法,该方法将比较引用所指向的实际对象。在字符串的情况下,它比较每个字符,看它们是否相等。
有趣的是:
那么为什么==有时会为字符串返回true呢?注意字符串是不可变的。在你的代码中
String foo = "hi";
String bar = "hi";
由于字符串是不可变的(当你调用.trim()或其他东西时,它会生成一个新的字符串,而不是修改内存中指向的原始对象),所以你实际上不需要两个不同的string ("hi")对象。如果编译器是智能的,字节码将只读取生成一个String("hi")对象。所以如果你这样做
if (foo == bar) ...
之后,它们指向同一个对象,返回true。但你很少会这么想。相反,你要求用户输入,这是在内存的不同部分创建新的字符串,等等。
注意:如果你执行类似baz = new String(bar)这样的操作,编译器可能仍然会认为它们是相同的东西。但重点是,当编译器看到字面值字符串时,它可以很容易地优化相同的字符串。
我不知道它在运行时是如何工作的,但我假设JVM没有保存一个“活动字符串”列表,并检查是否存在相同的字符串。(例如,如果你读取一行输入两次,用户输入相同的输入两次,它不会检查第二个输入字符串是否与第一个输入字符串相同,并将它们指向相同的内存)。这将节省一些堆内存,但它是如此微不足道,开销是不值得的。同样,重点是编译器很容易优化文字字符串。
你知道了……对== vs. equals()以及为什么它看起来是随机的给出了一个强有力的解释。