我是Java的新手。我正在编写一个程序来读取文件,计算其SHA1校验和,并将结果写入另一个文件。在任何错误上,我调用一个函数err_exit()
,它向stderr输出一条消息,并通过调用具有指定退出状态的System.exit()
来终止执行。这大约是我的main()
函数的样子:
public static void main(String[] args) {
String in_fname = "C:/tmp/test.txt"; // not reading args yet
String out_fname = "C:/tmp/test.sign";
byte[] file_data;
String hexdigest;
try {
file_data = readFileAsByteArray(in_fname);
}
catch (java.io.IOException ex) {
file_data = new byte[] {0}; // note this line well, please
err_exit(2, "error opening input file '" + in_fname + "'");
}
try {
hexdigest = hexdigestSha1(file_data);
}
catch (NoSuchAlgorithmException ex) {
hexdigest = ""; // note this line well, please
err_exit(3, "could not compute SHA1 message digest!");
}
try {
writeFileFromString(out_fname, hexdigest);
}
catch (java.io.IOException ex) {
err_exit(2, "error writing output file '" + out_fname + "'");
}
System.exit(0); // success
}
我要求你注意两行。这两行都只是为了防止编译器抱怨变量可能没有被初始化而存在。
就编译器而言,catch块可能会继续。实际上err_exit()
将永远不会返回,因此无法传递无效值。
所以,我的问题是:处理这类事情的常用Java习语是什么? try
/ catch
块的行有点难看;你会建议我让各种函数调用err_exit()
而不是像这样明确的代码吗?我认为我更喜欢显式检查,而main()
函数是进行检查的正确位置,但我对反馈感兴趣。
如果我要使用try
/ catch
块,这是否可以使编译器警告静音?
如果我在Python中这样做,我可能只是没有捕获异常,并让程序停止堆栈跟踪。错误的堆栈跟踪不会让这个程序的用户感到震惊,因为该用户就是我。在我看来,如果我将main()
函数声明为throws Exception
,那么我就无法捕获异常,它会表现得像Python一样。这是一个可怕的想法,会让正确思考的Java人回避我吗?
P.S。如果你有一本喜欢的书/网页/我应该阅读的任何Java习语,请提及它。
编辑:我为带有下划线的变量名称道歉。我已经在我的真实节目中重命名了那些,但是我将把它们留在这里。这实际上是因为我花了很多时间用Python和C编程;我要么使用Python“PEP 8”风格或通用C风格,请选择。答案 0 :(得分:2)
您似乎拥有强大的C背景。我假设编译器抱怨变量,如file_data。只需在try-catch块上方添加 file_data = null 。
以上几点:
答案 1 :(得分:2)
编译器理解throw永远不会返回,它不理解err_exit()不会返回。如果您使用忽略的异常重写,那么您的代码可能更清晰,编译器更快乐。 您还可以考虑使用Java命名约定。
public static void main(String[] args) {
String inFname = "C:/tmp/test.txt"; // not reading args yet
String outFname = "C:/tmp/test.sign";
try {
processFile(inFname, outFname);
} catch (Exception e) {
e.printStackTrace();
throw e; // rethrow and let main() die
}
}
public static void processFile(String inFname, String outFname)
throws IOException, NoSuchAlgorithmException {
Byte[] fileData = readFileAsByteArray(inFname);
String hexDigest = hexdigestSha1(fileData);
writeFileFromString(outFname, hexDigest);
}
在调用例程中,您可以捕获错误。如果你真的需要区分IOException可能发生的不同位置,那么你可以捕获你的例程并抛出描述性错误。
对代码的最小修复只是将变量初始化为设置它们的try catch块之外的null。然后编译器会很高兴。
答案 2 :(得分:2)
就个人而言,我喜欢“抛出空”;在调用一个根本无法返回的方法之后。
答案 3 :(得分:0)
如果我肯定我会在访问失败后立即退出,并且没有尝试代理对readFileAsByteArray等调用的结果,我可能会在以下位置分配空值申报网站。像这样......
byte[] file_data = new byte[] {0};
...代码的其余部分如下,没有catch块中的“伪造”分配。