Java 范围和可见性规则
Java Scoping & Visibility Rules
我在 Java 时隔了很长时间后回来写代码 - 过去几年我的大部分编码工作都在 PHP & JavaScript - 和我发现我必须更加努力地工作才能满足 Java 编译器的要求,该编译器在变量范围和异常处理等问题上要严格得多。下面是一段给我带来麻烦的代码
File file = new File(path, fname);
FileOutputStream stream = null;
try
{
stream = new FileOutputStream(file);
stream.write(tosave.getBytes());
}
finally
{
try
{
if (null != stream) {stream.close();}
return true;
}
catch(Exception e){return false;}
}
这是编译器接受的。然而,在我到达这里之前,我 运行 遇到了几个问题。
- 第一次尝试:没有捕获块。编译器拒绝参与,因为它要我处理无法创建 FileOutputStream 的可能性。写入该流的同上。我理解这个推理背后的逻辑并且喜欢它。
- 第二次尝试:Catch 块但是...:我在
try
块中声明并创建了 stream
变量。编译器再次出现问题 - stream
变量在 finally
块中超出范围。
如您所见,我通过在 try
块上方声明 stream
并将其初始化为空来解决了这个问题。
这行得通。然而,考虑到我的 Java 技能有多生疏,我想我会问:是否有 正确的方法 来编写这样的代码?
现代 Java 版本(自 Java 7 起)处理此类场景的惯用方法是使用 try-with-resource 块来处理所有丑陋的关闭 "logic" 为你。您仍然必须捕获异常或将其向上传播,但这是一个相对较小的问题。考虑以下因素:
public static boolean writeToFile(String path, String fname) {
File file = new File(path, fname);
try (FileOutputStream stream = new FileOutputStream(file)) {
stream.write(tosave.getBytes());
} catch (IOException e) {
// Should probably log the exception too
return false;
}
return true;
}
您可以简单地使用以下代码片段:
try (FileOutputStream stream = new FileOutputStream(file)){
stream.write(tosave.getBytes());
}catch(IOException e) {
e.printStackTrace();
return false;
}
return true;
这是 Java 7.
中引入的新功能 (try-with-resources Statement)
"right"的方法就是用Java7的try with resources。已经等了很长时间了,但它确实很好地清理了这种样板代码。
如果您卡在较早的 Java 版本上,那就倒霉了:)
我认为您正在为不重要的事情挂断电话。是的,在某些情况下编码 try/catch/finally 很重要,因为您实际上需要做一些事情来修复错误。
但是对于opening/closing一个文件,你不想为了满足编译器而让自己陷入困境。代码可读性更为重要。
怎么样:
String path="somepath";
String fname="somefile";
String tosave="somedata";
try {
File file = new File(path, fname);
FileOutputStream stream = new FileOutputStream(file);
stream.write(tosave.getBytes());
stream.close();
}
catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
我在 Java 时隔了很长时间后回来写代码 - 过去几年我的大部分编码工作都在 PHP & JavaScript - 和我发现我必须更加努力地工作才能满足 Java 编译器的要求,该编译器在变量范围和异常处理等问题上要严格得多。下面是一段给我带来麻烦的代码
File file = new File(path, fname);
FileOutputStream stream = null;
try
{
stream = new FileOutputStream(file);
stream.write(tosave.getBytes());
}
finally
{
try
{
if (null != stream) {stream.close();}
return true;
}
catch(Exception e){return false;}
}
这是编译器接受的。然而,在我到达这里之前,我 运行 遇到了几个问题。
- 第一次尝试:没有捕获块。编译器拒绝参与,因为它要我处理无法创建 FileOutputStream 的可能性。写入该流的同上。我理解这个推理背后的逻辑并且喜欢它。
- 第二次尝试:Catch 块但是...:我在
try
块中声明并创建了stream
变量。编译器再次出现问题 -stream
变量在finally
块中超出范围。
如您所见,我通过在 try
块上方声明 stream
并将其初始化为空来解决了这个问题。
这行得通。然而,考虑到我的 Java 技能有多生疏,我想我会问:是否有 正确的方法 来编写这样的代码?
现代 Java 版本(自 Java 7 起)处理此类场景的惯用方法是使用 try-with-resource 块来处理所有丑陋的关闭 "logic" 为你。您仍然必须捕获异常或将其向上传播,但这是一个相对较小的问题。考虑以下因素:
public static boolean writeToFile(String path, String fname) {
File file = new File(path, fname);
try (FileOutputStream stream = new FileOutputStream(file)) {
stream.write(tosave.getBytes());
} catch (IOException e) {
// Should probably log the exception too
return false;
}
return true;
}
您可以简单地使用以下代码片段:
try (FileOutputStream stream = new FileOutputStream(file)){
stream.write(tosave.getBytes());
}catch(IOException e) {
e.printStackTrace();
return false;
}
return true;
这是 Java 7.
中引入的新功能 (try-with-resources Statement)"right"的方法就是用Java7的try with resources。已经等了很长时间了,但它确实很好地清理了这种样板代码。
如果您卡在较早的 Java 版本上,那就倒霉了:)
我认为您正在为不重要的事情挂断电话。是的,在某些情况下编码 try/catch/finally 很重要,因为您实际上需要做一些事情来修复错误。
但是对于opening/closing一个文件,你不想为了满足编译器而让自己陷入困境。代码可读性更为重要。
怎么样:
String path="somepath";
String fname="somefile";
String tosave="somedata";
try {
File file = new File(path, fname);
FileOutputStream stream = new FileOutputStream(file);
stream.write(tosave.getBytes());
stream.close();
}
catch (Exception e) {
e.printStackTrace();
return false;
}
return true;