为什么此代码不能按预期工作?

我正在编写一个简单的方法,将成绩作为用户的输入并计算成绩点平均值。 这是我的代码:

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; } 

当我测试这个方法时,我只能输入一个等级并且没有任何变量递增,有人可以告诉我代码有什么问题吗?

问题在于使用==而不是equals进行字符串比较。 ==比较不太可能相等的引用。 改成

  if(grade.equals("A")){ totalGradePoints += 4; numClasses++; }else if(grade.equals("B")){ ... 

它应该工作。 有关详细说明,请参阅此答案 。

作为一种好的做法,建议始终使用静态字符串作为调用equals的对象以防止NPE:

  if("A".equals(grade)){ totalGradePoints += 4; numClasses++; }else if("B".equals(grade)){ ... 

如果您使用的是Java 7,您还可以使用字符串执行switch语句(但如果grade为null,则会抛出一个NPE):

 switch(grade) { case "A": totalGradePoints += 2; numClasses++; break; case "B": ... } 

最后,由于您只将一个字母转换为整数,最佳解决方案是将它们转换为char,并将AD之间的值转换为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 

问题是你应该使用==来比较字符串,当你应该使用s.equals("...")==运算符检查标识,并且不保证字符串具有相同的标识(可能有多个对象表示完全相同的字符串)。 equals()方法比较字符串的内容是否相等而不是对象的标识。

我会写得更像这样:

 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); 

while(true)循环with break (退出循环)和continue (跳回循环开始)是更惯用的Java。 我上面的版本的主要好处是没有重复的numClasses++行。

您甚至可以使循环更简洁,并且通过使用Map更改等级点更简单,Map将返回等级的分数值或无效等级的null

 Map gradePoints = new HashMap() {{ 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++; } 

同样值得指出的是,在你的代码和本页的所有答案中,如果你没有输入任何等级,你将得到一个除零(产生NaN),所以你可能想要考虑处理优雅。

您的失败是使用==运算符检查字符串是否相等。 字符串是对象,因此在这种情况下将检查对象标识(默认为引用检查)。

使用equals通过字符检查来制作一个字符,如下所示:

 if(grade.equals("A")){