好的,这是代码,我的问题是为什么我必须把FileReader inputstream = null;
和FileWriter
相同。为什么不能稍后在try块中简单地创建对象呢?我是不是错过了什么……我可能是。
public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
FileReader inputStream = null;
FileWriter outputStream = null;
try {
inputStream = new FileReader("In.txt");
outputStream = new FileWriter("Out.txt");
int c;
while ((c = inputStream.read()) != -1){
outputStream.write(c);
}
}
finally {
if (inputStream != null){
inputStream.close();
}
if (outputStream != null){
outputStream.close();
}
}
因为您无法在finally
块中引用它们,因此您将无法关闭它们
顺便说一句,如果它们是reader和writer,您最好这样命名变量,而不是xStream
。
I/O处理一直很乏味,这就是为什么Java 7引入了"try with resource"
因为对于FileReader inputstream = null
,您不创建对象,而只是一个名为inputStream
的对对象的引用。哪一个?无,引用初始化为null。稍后,您可能会或可能不会创建对象(但是如果new FileReader(...)
抛出异常会发生什么?);finally块中的检查需要对初始化的变量起作用。
这都是关于明确的分配规则。Java只允许您使用局部变量,如果它可以保证该变量已被初始化。
考虑这个简化版本的代码:
FileReader inputStream; // not initialized here ...
try {
inputStream = new FileReader("In.txt");
// do stuff
} finally {
if (inputStream != null) {
inputStream.close();
}
}
No假设FileReader
构造函数没有找到In.txt
文件,并抛出FileNotFoundException
。构造函数"异常地"终止,并且没有给inputStream
赋值。然后我们到达finally
块,在那里我们尝试测试inputStream
不是null
。但是此时,inputStream
仍然是未初始化的,Java不允许我们获取未初始化的局部变量的值,这样就会出现编译错误。
看似无用的null
赋值给inputStream
,通过确保在到达finally
块时始终初始化变量,解决了这个问题。
Java语言规范用了整整一章来说明明确的赋值规则;即编译器用来决定变量是否在任何给定点初始化的规则。这些规则是相当保守的,在某些情况下,编译器会说某些东西没有被明确赋值,而一个大脑发达的人可以推断出它是赋值的。您只需要忍受它,偶尔添加不必要的初始化或永远无法执行的return
语句。
我经常使用以下
FileReader in = new FileReader("In.txt");
try {
// do reading
} finally {
in.close();
}
这意味着封闭方法抛出IOException(即FileNotFoundException)。这也适用于Java 7:
try (FileReader in = new FileReader("In.txt"); FileWriter ...) {
// do reading
}