【问题标题】:How to switch off "java: variable might not have been initialized"如何关闭“java:变量可能尚未初始化”
【发布时间】:2015-07-24 02:22:31
【问题描述】:

我有以下代码:

public static void main( String[  ] args ){
    int begin, end;
    try{
        begin = Integer.valueOf( args[ 1 ] );
        end = Integer.valueOf( args[ 2 ] );
    }catch( NumberFormatException conversion_error ){
        System.out.println( "Not A Number." );
        System.exit( 1 );
    }
    if( begin >= end ){
        System.out.println( "Wrong arguments. (" + begin + " >= " + end + ")" );
        System.exit(1);
    }
    System.out.print( "OK." );
    System.exit(0);
}

当我尝试编译它时,我得到了这个错误。

错误:(13, 13) java: 变量 begin 可能没有被初始化 错误:(13, 22) java: 变量 end 可能没有被初始化

我理解为什么编译器会警告我,但我的代码的真正目的是处理这种情况:当变量未初始化时,我关闭了我的程序。在这种情况下,我从不使用它们。

我认为答案相当简单:在“try”块之外初始化“begin”和“end”,例如立即为它们分配零。

int begin = 0, end = 0;

但是我可以强制编译器忽略这个问题吗?有什么办法可以关闭对我的代码的这种好奇检查吗?除了我的变量值可能错误之外,我的程序没有任何技术问题。

【问题讨论】:

  • 作为一般经验法则,编译器试图帮助您避免代码可能产生的问题。您可以将值初始化为默认的已知值...
  • 查看“默认值”部分herebeginend 不会被分配默认值。这会导致问题,因为您在 if 语句中使用它们。你别无选择,只能初始化它们。
  • 你在这里问错了问题。您不想将其关闭:您想修复代码以使其能够编译。

标签: java


【解决方案1】:

来自System.exit的javadoc:

终止当前运行的 Java 虚拟机。

您的编译器不会提前确定 jvm 将关闭,因此程序将退出。

如果您将System.exit(1); 更改为return;,编译器将认识到此时您会将控制流返回给调用方法。 由于您在程序的Main 类的main 方法中,因此它也会终止程序。直到现在,您的编译器才知道它。

您可以使用以下代码,但请注意,在这种情况下,您不会将status code 1 发送到您的操作系统:

public static void main( String[  ] args ) {

try{
    final int begin = Integer.valueOf( args[ 1 ] );
    final int end = Integer.valueOf( args[ 2 ] );

    if( begin >= end ) {
        System.out.println( "Wrong arguments. (" + begin + " >= " + end + ")" );
        System.exit(1);
    }

} catch( NumberFormatException conversion_error ) {
    System.out.println( "Not A Number." );
    return;
}

System.out.print( "OK." );
System.exit(0);
}

【讨论】:

  • 修复它的正确方法是将所有使用beginend 的代码放在try 块中,它应该放在首位。
【解决方案2】:

没有。你不能关掉它。编译器坚持不要使用未初始化的变量。这是一个rule of Java

您需要修复您的代码。具体来说,依赖于先前try 块中代码成功的代码应该在该try 块内。

【讨论】:

    【解决方案3】:

    就像其他人说的那样,您没有禁用错误,而是修复了代码中的错误。我建议这种解决方法

    public static void main( String[  ] args ){
        int begin, end;
        try{
            begin = Integer.valueOf( args[ 1 ] );
            end = Integer.valueOf( args[ 2 ] );
    
            if( begin >= end ){
                System.out.println( "Wrong arguments. (" + begin + " >= " + end + ")" );
                System.exit(1);
            }
            System.out.print( "OK." );
            System.exit(0);
        }catch( NumberFormatException conversion_error ){
            System.out.println( "Not A Number." );
            System.exit( 1 );
        }
    }
    

    【讨论】:

      【解决方案4】:

      您可能希望忽略/抑制变量可能未初始化警告可能有合理的理由......例如,当您在测试中的 @Before 方法中初始化变量时。在这种情况下,您可以使用:@SuppressWarnings("InstanceVariableMayNotBeInitialized")

      注意:我会添加一个结尾注释来解释原因

      @SuppressWarnings("InstanceVariableMayNotBeInitialized") // Initialized in @Before

      【讨论】:

      • 问题是关于一个错误,而不是一个警告,它是由局部变量而不是实例变量引起的。
      【解决方案5】:

      也许这发生在你身上:

      • 您想在静态方法中使用变量。
      • 您有类似循环或开关构造的东西,因此由于块作用域和花括号,您无法确定在哪里初始化。
      • 答案是:
        • 1 将变量声明为静态
        • 2 改为使用在类级别定义的属性创建类的实例。
          • 然后调用该类实例的方法。
          • 所以你最终会得到这样的结果:
      public class Solution {
          private int i;
          private double d;
          private String s;
          private Solution() {
              i = 0;
              d = 0.0;
              s = null;
          }
          private void processInput() {
             /* using i in here now, instead of i in main
              * since that's the equivalent of this.i now instead
              * ... unless you defined int i in the method!
              */
          }
          public static void main(String[] args) {
              Solution s = new Solution();
              s.processInput();
          }
      }
      
      • 您也可以在不引入类级别属性的情况下摆脱困境,也可以通过重构,并将事物分解为返回类型的方法,并且所有类型都在同一个作用域块内。

      【讨论】:

        猜你喜欢
        • 2013-05-22
        • 1970-01-01
        • 1970-01-01
        • 2012-03-25
        • 2015-07-04
        • 1970-01-01
        相关资源
        最近更新 更多