Java 为什么这段代码不能按预期工作?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21644741/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does this code not work as intended?
提问by user3189506
I'm writing a simple method that takes grades as input from the user and calculates the Grade Point Average. Here is my code:
我正在编写一个简单的方法,它将成绩作为用户的输入并计算平均成绩点。这是我的代码:
public static double calculateGPA(){
Scanner in = new Scanner(System.in);
double totalGradePoints = 0; // total grade points
int numClasses = 0; // total classes completed
boolean doneInput = false; // returns true when use is done inputting grades
System.out.println("Enter all your grades (A,B,C,D,F) and enter 'done' if you are done entering your grades.");
while (!doneInput) {
String grade = in.next();
if (grade == "A") {
totalGradePoints += 4;
numClasses++;
} else if (grade == "B") {
totalGradePoints += 3;
numClasses++;
} else if(grade == "C") {
totalGradePoints += 2;
numClasses++;
} else if(grade == "D") {
totalGradePoints += 1;
numClasses++;
} else if(grade == "F") {
numClasses++;
} else {
doneInput = true;
} //end if - else-if - else statement
}//end while loop
double unwtGPA = (totalGradePoints/numClasses);
return unwtGPA;
}
When I tested the method, I was only able to input one grade and none of the variables incremented, can somebody tell me what's wrong with the code?
当我测试该方法时,我只能输入一个等级并且没有任何变量增加,有人能告诉我代码有什么问题吗?
回答by Janick Bernet
The issue is with the string comparison using ==
instead of equals
. ==
compares the references, which are very unlikely to be equal. Change to
问题在于字符串比较使用==
而不是equals
. ==
比较不太可能相等的引用。改成
if(grade.equals("A")){
totalGradePoints += 4;
numClasses++;
}else if(grade.equals("B")){ ...
and it should work. See this answerfor a detailed explanation.
它应该工作。有关详细说明,请参阅此答案。
As a good practice it is advisable to always use the static string as the object for calling equals on to prevent a NPE:
作为一种好的做法,建议始终使用静态字符串作为调用 equals 的对象以防止出现 NPE:
if("A".equals(grade)){
totalGradePoints += 4;
numClasses++;
}else if("B".equals(grade)){ ...
If you are using Java 7, you can also do a switch
statement with strings (though this one will throw an NPE if grade is null):
如果您使用的是 Java 7,您还可以switch
使用字符串执行语句(尽管如果 Grade 为 null,此语句会抛出 NPE):
switch(grade) {
case "A":
totalGradePoints += 2;
numClasses++;
break;
case "B":
...
}
And finally, since you are converting only one letter to an integer, to best solution is to convert them to char and for the values between A
and D
to do totalGradePoints += ('D' - grade.charAt(1)) + 1
. So something along those lines would be simplest to read IMO:
最后,因为你将只有一个字母为整数,以最好的解决办法是将它们转换为焦炭和之间的价值观A
和D
做totalGradePoints += ('D' - grade.charAt(1)) + 1
。因此,阅读 IMO 最简单的方法是:
while (true) {
final String input = in.next();
if(input == null || input.isEmpty())
break;
final char grade = input.charAt(0);
if(grade >= 'A' && grade <= 'D') {
totalGradePoints += ('D' - grade) + 1;
} else if(grade == 'F') {
// no gradepoints for 'F'
} else {
break;
} //end if - else-if - else statement
++numClasses;
} //end while loop
回答by markusthoemmes
Your failure is to use the ==
operator to check Strings on equality. Strings are objects so in this case there will be a check on object identity (which defaults to a reference check).
您的失败是使用==
运算符来检查字符串是否相等。字符串是对象,因此在这种情况下将检查对象身份(默认为引用检查)。
Use equals
to make a character by character check like so:
用于equals
逐个字符检查,如下所示:
if(grade.equals("A")){
回答by ???v?т?
The problem is that you are using ==
to compare Strings, when you should be using s.equals("...")
. The ==
operator checks identity and Strings are not guaranteed to have the same identity (there may be several objects representing exactly the same string). The equals()
method compares the contentsof the Strings for equality rather than the identity of the objects.
问题是您正在使用==
比较字符串,而您应该使用s.equals("...")
. 的==
操作者检查身份和字符串不能保证具有相同的标识(可能有正好表示相同的字符串的多个对象)。该equals()
方法比较字符串的内容是否相等,而不是对象的身份。
I would write it more like this:
我会更像这样写:
Scanner in = new Scanner(System.in);
double totalGradePoints = 0; // total grade points
int numClasses = 0; // total classes completed
System.out.println("Enter all your grades (A,B,C,D,F) and"
+ " write 'done' when you have finished");
while (true) {
String input = in.next();
if (input.equals("done")) {
break;
}
if (input.equals("A")) {
totalGradePoints += 4;
} else if (input.equals("B")) {
totalGradePoints += 3;
} else if (input.equals("C")) {
totalGradePoints += 2;
} else if (input.equals("D")) {
totalGradePoints += 1;
} else if (!input.equals("F")) {
System.err.println("Invalid input: " + input);
continue;
}
numClasses++;
}
double unweightedGPA = (totalGradePoints / numClasses);
System.out.println(unweightedGPA);
The while(true)
loop with break
(to exit the loop) and continue
(to skip back to the start of the loop) is more idiomatic Java. The main benefit with my version above is that there is no duplication of the line numClasses++
.
该while(true)
带环break
(退出循环)和continue
(跳回到循环的开始)是更地道的Java。我上面的版本的主要好处是没有重复的行numClasses++
。
You could even make the loop more succinct and make it simpler to alter the grade points by using a Map, which will return a points value for the grade or null
for an invalid grade:
您甚至可以使循环更简洁,并通过使用 Map 更简单地更改成绩点,这将返回成绩或null
无效成绩的点值:
Map<String, Integer> gradePoints = new HashMap<String, Integer>() {{
put("A", 4);
put("B", 3);
put("C", 2);
put("D", 1);
put("F", 0);
}};
String input;
while (!(input = in.next()).equals("done")) {
Integer points = gradePoints.get(input);
if (points == null) {
System.err.println("Invalid input: " + input);
continue;
}
totalGradePoints += points;
numClasses++;
}
It's also worth pointing out that in your code and in all the answers on this page, if you don't enter any grades, you will get a division-by-zero (yielding NaN), so you might want to think about handling that gracefully.
还值得指出的是,在您的代码和此页面上的所有答案中,如果您不输入任何成绩,您将得到除以零(产生 NaN),因此您可能需要考虑处理优雅地。