others - java语言 - 如何使用"variable might not have been initialized(变量可能未初始化)"避免System.exit

我想避免这种丑陋的模式:


Long foo = null;


Double bar = null;



try {


 foo = Long.parseLong(args[0]);


 bar = Long.parseLong(args[0]);


} catch (NumberFormatException e) {


 System.out.println(USAGE);


 System.exit(1);


}



doSomethingWith(foo, bar);



我知道可以把initialisations和doSomethingWith移动到try块,但是,

  • doSomethingWith实际上是几行条件逻辑,许多方法调用,语句等等,
  • 我不想不必要地嵌套块
  • 我想避免意外地捕捉到意外的NumberFormatException 从doSomethingWith抛出,

这段丑陋的代码让我怀疑有一种更好的方法来编写这些代码。


long foo;


double bar;



try {


 foo = Long.parseLong(args[0]);


 bar = Long.parseLong(args[0]);


} catch (NumberFormatException e) {


 System.out.println(USAGE);


 System.exit(1);


}



doSomethingWith(foo, bar);



但我们都知道java variable might not have been initialized尝试构建时的错误。

对于这类问题,更好的设计模式是什么?

  • 避免使用奇怪的= null
  • 避免原语周围不必要的类包装
  • 不深入try
  • 不捕获或隐藏异常

时间:

奇怪的是编译器不知道System.exit(1);永远不会返回,

因此,你所要做的就是给它提供一些不会让你从catch块到try catch之后的东西,例如:


try {


 foo = Long.parseLong(args[0]);


 bar = Long.parseLong(args[0]);


} catch (NumberFormatException e) {


 System.out.println(USAGE);


 System.exit(1);


 throw new RuntimeError("Make sure the end of the catch block is unreachable");


}



如果你需要经常执行这个操作,则可能需要编写一个辅助方法,并抛出该方法的结果(你永远不会使用),


try {


 foo = Long.parseLong(args[0]);


 bar = Long.parseLong(args[0]);


} catch (NumberFormatException e) {


 System.out.println(USAGE);


 throw HelperClass.systemExit(1);


}



...



public class HelperClass {


 public static RuntimeException systemExit(int exitCode) {


 System.exit(1);


 throw new RuntimeException("We won't get here");


 }


}



这样:

  • 你可以单元测试用户错误(单元测试System.exit至少更笨拙)
  • 集中处理"如果用户出错,我该怎么办",而不是在多个地方包含System.out.println(USAGE)
  • 你没有遇到这个明确的任务

因此你的代码是:


try {


 foo = Long.parseLong(args[0]);


 bar = Long.parseLong(args[0]);


} catch (NumberFormatException e) {


 throw new UserInputException("foo and bar must both be valid integers");


}



这是另一个更清洁(但是更长)的解决方案。


// SomeModel(a: long, b: long)


public static Optional<SomeModel> validate(final String[] args) {


 try {


 // Probably some other null checks and things like that here also


 return Optional.of(new SomeModel(Long.parseLong(args[0]), Long.parseLong(args[1])));


 } catch (final NumberFormatException e) {


 System.out.println(USAGE);


 System.exit(1);


 }


 return Optional.empty(); // Or use some other"defaults" for that model


}



public static void doSomethingWith(final SomeModel input) { // ...signature changed!


 // Do your stuff here


}



public static void main(final String[] args) {


 validate(args).ifPresent(it -> doSomethingWith(it));


}



这个流程更清晰,但更详细,

...