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

时间:2014-02-08 10:17:01

标签: java if-statement

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

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

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

3 个答案:

答案 0 :(得分:11)

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

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

它应该有效。有关详细说明,请参阅this answer

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

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

如果您使用的是Java 7,您还可以使用字符串执行switch语句(但如果成绩为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

答案 1 :(得分:3)

问题是,当您使用==时,您正在使用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)循环break(退出循环)和continue(跳回循环开始)是更惯用的Java。我上面的版本的主要好处是没有重复行numClasses++

您甚至可以使循环更简洁,并且可以更简单地使用地图更改成绩点,地图将返回成绩的分数值或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++;
}

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

答案 2 :(得分:0)

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

使用equals进行字符检查,如下所示:

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