感谢您抽出宝贵时间阅读本文。对不起,如果我的问题是愚蠢的,我尝试搜索,但无法弄清楚为什么我有这个问题。我试图为另一个应用程序测试一些代码,但我遇到了问题。也许我只是不理解数组。
我在一个名为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;
}
}
我在main方法中有以下代码:
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"));
工作正常。解决方案可能很容易,但在寻求帮助时我无法找到一个好的方法。 再次感谢您的阅读,我们非常感谢您的回答!
答案 0 :(得分:18)
为您已经获得的答案添加更多信息:
Java有两种类型的存储。一个是堆栈,包括变量名称及其值。一个是堆,这只是一个庞大的自由浮动对象集合。
现在,如果你正在处理原始类型(例如int
,boolean
或char
),请指定一个变量,如
int myInt = 1;
将该变量推送到堆栈上 - 名称为myInt
,值为1
。
但是,如果你有一个对象(比如字符串),那么分配一个变量就会多一点
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
指向另一个。因此,虽然两个对象的内容可能相同,但堆栈上a
和b
的内容却不同。
因此,要比较任何对象,如果要比较内容而不是实例相等,请始终使用.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,就无法修改它。永远。不相信吗?看看吧!
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。
答案 1 :(得分:2)
比较字符串时应使用.equals()
方法,而不是==
。 ==
运算符比较引用以查看它们是否指向同一个底层对象。 .equals()
方法将底层对象相互比较,看它们是否在语义上等效。
答案 2 :(得分: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;
}
}
答案 3 :(得分:0)
故障就在这一行:
if (note == "c") n = "c#";
这会按地址而非按值比较字符串。请尝试使用"c".equals(note)
。
答案 4 :(得分:-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]));
}
}
工作代码