这段代码将一个字符串分离为令牌,并将它们存储在一个字符串数组中,然后将一个变量与第一个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,因为它执行逻辑比较。
我知道这是一个老问题,但我是这样看的(我觉得很有用):
技术的解释
在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()以及为什么它看起来是随机的给出了一个强有力的解释。