这段代码将一个字符串分离为令牌,并将它们存储在一个字符串数组中,然后将一个变量与第一个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");
    }
}

当前回答

我知道这是一个老问题,但我是这样看的(我觉得很有用):


技术的解释

在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()以及为什么它看起来是随机的给出了一个强有力的解释。

其他回答

让我们分析下面的Java,来理解string的恒等式:

public static void testEquality(){
    String str1 = "Hello world.";
    String str2 = "Hello world.";

    if (str1 == str2)
        System.out.print("str1 == str2\n");
    else
        System.out.print("str1 != str2\n");

    if(str1.equals(str2))
        System.out.print("str1 equals to str2\n");
    else
        System.out.print("str1 doesn't equal to str2\n");

    String str3 = new String("Hello world.");
    String str4 = new String("Hello world.");

    if (str3 == str4)
        System.out.print("str3 == str4\n");
    else
        System.out.print("str3 != str4\n");

    if(str3.equals(str4))
        System.out.print("str3 equals to str4\n");
    else
        System.out.print("str3 doesn't equal to str4\n");
}

当第一行代码String str1 = "Hello world."执行时,一个字符串\Hello world." 创建,变量str1引用它。由于优化,下一行代码执行时不会再次创建另一个字符串“Hello world.”。变量str2也引用现有的“Hello world.”。

运算符==检查两个对象的同一性(两个变量是否引用同一个对象)。由于str1和str2在内存中引用同一个字符串,所以它们彼此是相同的。equals方法检查两个对象是否相等(两个对象是否具有相同的内容)。当然,str1和str2的内容是相同的。

当代码String str3 = new String("Hello world.")执行时,将创建一个内容为"Hello world."的String的新实例,该实例由变量str3引用。然后再次创建内容为"Hello world."的string的另一个实例,并由 str4。因为str3和str4引用了两个不同的实例,所以它们并不相同,但它们是相同的 内容相同。

因此,输出包含四行:

Str1 == str2

Str1 equals str2

Str3! = str4

Str3 equals str4

我知道这是一个老问题,但我是这样看的(我觉得很有用):


技术的解释

在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()以及为什么它看起来是随机的给出了一个强有力的解释。

使用字符串。equals(对象其他)函数用于比较字符串,而不是==操作符。

该函数检查字符串的实际内容,==操作符检查对对象的引用是否相等。请注意,字符串常量通常是“内嵌”的,这样两个具有相同值的常量实际上可以用==进行比较,但最好不要依赖于此。

if (usuario.equals(datos[0])) {
    ...
}

注意:比较是在'usuario'上完成的,因为这在你的代码中是保证非空的,尽管你仍然应该检查你实际上在datos数组中有一些令牌,否则你会得到一个数组越界异常。

而不是

datos[0] == usuario

use

datos[0].equals(usuario)

==比较变量的引用,其中.equals()比较你想要的值。

equals()函数是Object类的一个方法,程序员需要重写它。String类重写它,以检查两个字符串是否相等,即在内容和不引用。

==运算符检查两个对象的引用是否相同。

考虑程序

String abc = "Awesome" ;
String xyz =  abc;

if(abc == xyz)
     System.out.println("Refers to same string");

这里的abc和xyz,都是指同一个字符串“Awesome”。因此表达式(abc == xyz)为真。

String abc = "Hello World";
String xyz = "Hello World";

if(abc == xyz)
    System.out.println("Refers to same string");
else
    System.out.println("Refers to different strings");

if(abc.equals(xyz))
     System.out.prinln("Contents of both strings are same");
else
     System.out.prinln("Contents of strings are different");

这里abc和xyz是两个具有相同内容“Hello World”的不同字符串。因此,表达式(abc == xyz)为假,而as (abc.equals(xyz))为真。

希望你理解==和<Object>.equals()之间的区别

谢谢。