【问题标题】:When do I need to initialize a String?我什么时候需要初始化一个字符串?
【发布时间】:2014-08-05 22:07:26
【问题描述】:

浏览来自各种来源的一些switch 命令教程。我正在尝试基于这个 SwitchDemo 教程创建一个小程序(我已经删除了一些重复的代码以节省空间):

public class SwitchDemo {
public static void main(String[] args) {

    int month = 8;
    String monthString;
    switch (month) {
        case 1:  monthString = "January";
                 break;
        case 2:  monthString = "February";
                 break;
        case 3:  monthString = "March";
                 break;
        default: monthString = "Invalid month";
                 break;
    }
    System.out.println(monthString);
}
}

在此代码中monthString 不需要在String monthString; 行中初始化。但是我想使用Scanner 将用户输入添加到代码中,如下所示:

 import java.util.Scanner;
 public class App2 {

 public static void main(String[] args) {

    Scanner scan = new Scanner(System.in);

    int month = scan.nextInt();

    String monthString;

    switch (month) {
    case 1:
        monthString = "January";
        break;      
    case 2:
        monthString = "February";
        break;
    case 3: 
        monthString = "March";
        break;
    default: 
        System.out.println("Invalid month");
        break;
    }
    System.out.println(monthString);
}

}

在这种情况下,代码不起作用,Eclipse 告诉我需要初始化monthString; eclipse 通过将= null 添加到String monthString 来纠正它。

这是什么原因?

P.s 我对 Java 完全陌生,所以你能像向不懂任何编程的人一样解释吗?

谢谢

【问题讨论】:

  • 在示例一中,默认给字符串一个值。在示例 2 中,您没有这样做。

标签: java string initialization switch-statement


【解决方案1】:

这是因为monthString 是一个本地 变量,并且您可以在未初始化且仍在尝试使用它的地方采用路径。

这在 Java 中是不允许的。我认为原因是 Java 可以很容易地防止你犯错。它迫使您承认您尚未将monthString 设置为任何内容,但您仍在尝试使用它。 10 次中有 9 次,这是开发人员的错误,所以 Java 不会让你这样做。

修复它的一种方法是将monthString 设置为default: 中的某个值。正如@Eran 所说,您也可以将其初始化为null。

【讨论】:

    【解决方案2】:

    您可以在声明时将其初始化为 null:

    String monthString = null;

    或者在开关的default 子句中给它一些默认值。

    default: 
        System.out.println("Invalid month");
        monthString = null; // or some other default value
        break;
    }
    

    如果你不做这两者之一,你可能会在字符串初始化之前到达System.out.println(monthString);,这是一个错误。

    【讨论】:

      【解决方案3】:

      基本上,只要您可以访问一条语句,该语句中使用的任何变量都必须已初始化。

      在您的第二个示例中,default 案例脱离了 switch 语句,但代码随后执行切换后的下一条语句:System.out.println(monthString)。因此,该变量必须已在通向该处的所有代码路径中初始化,但在 default 的情况下却没有。

      【讨论】:

      • 谢谢,这很有意义,因此我对路径有了更多的了解。我改变了 system.out.println();默认为monthString =“默认文本”的行,就像我在案例中所做的那样,它可以工作!
      【解决方案4】:

      这样做的原因是它是 Java 语言规范的一部分。如果变量尚未“明确分配”,则不允许访问局部变量(或空白最终字段)的值。编译器执行分析以确保在访问之前发生赋值,无论访问采用什么代码路径。

      在您的第二个示例中,通过默认 switch 案例的路径永远不会为 monthString 赋值,然后在 println 语句中访问变量的值。

      完整的明确分配规则非常复杂。您可以在规范 here 的第 16 章中阅读它们。

      【讨论】:

        【解决方案5】:

        或者你可以尝试这样的事情:

        String monthString;
        switch (month) {
        case 1:
            monthString = "January";
            break;      
        case 2:
            monthString = "February";
            break;
        case 3: 
            monthString = "March";
            break;
        default: 
            monthString = "Invalid month";
            break;
        }
        System.out.println(monthString);
        

        为了在 java 中使用局部变量,必须将其初始化为某个值,即使该值将其设置为等于 null。 eclipse 所做的是遵循创建monthString 和在System.out.println(monthString) 中使用它的位置之间的所有不同路径,并确定没有初始化monthString 的位置。

        如果您要在封闭的SwitchDemo 类中声明monthString,那么您的代码也是有效的,因为eclipse 无法确定另一个方法是否设置了monthString。 (如果您要这样做,您当然必须将 monthString 声明为静态,因为您只能从静态方法中访问静态变量)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-12-26
          • 1970-01-01
          • 1970-01-01
          • 2011-09-20
          相关资源
          最近更新 更多