2

感谢您抽出时间来阅读。抱歉,如果我的问题很愚蠢,我尝试搜索但无法完全弄清楚我为什么会遇到这个问题。我试图为另一个应用程序测试一些代码,但我遇到了问题。也许我只是不正确地理解数组。

我在名为 Transpose 的类中有一个名为 halfStepUp 的方法,出于测试目的,如果给定“c”,则应返回“c#”,如果给定“d”,则应返回“d#”。这是代码:

public class Transpose{
    public static String halfStepUp(String note){
        String n = null;
        if (note == "c") n = "c#";
        if (note == "d") n = "d"#;
        return n;
    }   
}

我的主要方法中有以下代码:

String [] scale = new String[2];
scale[0] = "c";
scale[1] = "d";

System.out.println(Transpose.halfStepUp(scale[0]));

这将打印“null”。我究竟做错了什么?我知道该方法有效,因为如果我使用

System.out.println(Transpose.halfStepUp("c"));

它工作正常。解决方案可能非常简单,但在寻求帮助时我找不到一个好的方法来表达它。再次感谢您的阅读,任何答案都非常感谢!

4

5 回答 5

21

要为您已经得到的答案添加更多信息:

Java 有两种类型的存储。一个是堆栈,其中包括变量名称及其值。一个是堆,它只是一个巨大的自由浮动对象的集合。

现在,如果您正在使用原始类型(如 或) int,则分配一个变量,如 将变量推送到堆栈上 - 名称是,值是。booleanchar
int myInt = 1;
myInt1

但是,如果您有一个对象(如字符串),则分配一个变量会做更多的事情。现在在堆的某处
String myString = "Hey!";
创建一个对象(的实例)。String它在那里没有名字,只有内存中可以找到它的某个地址。
除此之外,它将一个变量压入堆栈。名称是myString- 值是堆上对象的地址。

那么为什么这与比较变量有关呢?因为==比较变量的值。在堆栈上,就是这样。所以如果你比较原始类型,一切都会按预期工作。但是如果你在比较对象,==仍然只比较变量的值——在这种情况下,就是对象的地址。如果地址相同,则返回 true。这确实意味着,两个变量都指向同一个对象。如果地址不同,则==返回 false。,无需查看对象真正所在的堆。

一个例子:

String a = new String("Hey!");
String b = a;
if (a == b) System.out.println("true");
else System.out.println("false");

将回显“true” - 因为两个变量都包含相同的对象。

String a = new String("Hey!");
String b = new String("Hey!");
if (a == b) System.out.println("true");
else System.out.println("false");

将回显“false” - 因为您现在在堆上有两个对象,并且a指向一个,而b指向另一个。因此,虽然两个对象的内容可能相同,但堆栈的内容ab堆栈上的内容是不同的。

因此,要比较任何对象,.equals()如果要比较内容,请始终使用,而不是实例相等。

[附录]:使用字符串,这更加复杂。正如你已经发现的那样,

String a = "Hey!"; // mention the difference to the example above:
String b = "Hey!"; // I did NOT use the `String()` cosntructor here!
if (a == b) System.out.println("true");
else System.out.println("false");

实际上会给你“真实”。为什么会这样?有人可能会认为我们仍然创建了两个对象。但实际上,我们不是。

String不可变的。这意味着,一旦创建了字符串,就无法修改它。曾经。不相信?看一看!

String myString = "test"; // we create one instance of String here
myString += " and more"; // we create another instance of String (" and more")
                         // and append that. Did we modify the instance stored in
                         // myString now? NO! We created a third instance that
                         // contains "test and more".

因此,无需创建String具有相同内容的其他实例 - 这会提高性能,因为字符串被广泛使用,大量使用,因此我们希望尽可能少地使用它们。为了归档它,JVM 维护了一个我们已经创建的字符串对象列表。每次我们写下一个字符串字面量(类似于"Hey!")时,它都会查看该列表并检查我们是否已经创建了一个具有该值的实例。如果是这样,它会返回一个指向该完全相同实例的指针,而不是创建一个新实例。

这就是,为什么"Hey!" == "Hey!"会返回true。

于 2013-11-13T22:52:11.147 回答
2

.equals()比较字符串时应该使用该方法,而不是==. ==运算符比较引用以查看它们是否指向相同的底层对象。该.equals()方法将底层对象相互比较,以查看它们在语义上是否等效。

于 2013-11-13T22:40:09.803 回答
0

试试这个:(根据评论编辑)

public class Transpose{
    public static String halfStepUp(String note){
        String n = null;
        if ("c".equals(note)) n = "c#"; //using .equals as a string comparison
        if ("d".equals(note)) n = "d#"; //not "d"#
        return n;
    }   
}
于 2013-11-13T22:39:49.740 回答
0

故障在这一行:

 if (note == "c") n = "c#";

这将按地址而不是按值比较字符串。尝试"c".equals(note)改用。

于 2013-11-13T22:40:04.757 回答
-3
class Transpose{
    public static String halfStepUp(String note){
        String n = null;
        if (note == "c") n = "c#";
        if (note == "d") n = "d#";
        return n;
    }
}
public class TransposeTest {
    public static void main(String... args) {
        String [] scale = new String[2];
        scale[0] = "c";
        scale[1] = "d";
        System.out.println(Transpose.halfStepUp(scale[0]));
    }
}

工作代码

于 2013-11-13T22:41:13.010 回答