访问创建它的try/catch块之外的文件对象(Java)

Dis*_*ser 2 java

我想创建一个RandomAccessFile对象(在Java中),并写入并读取它.我的问题是,据我所知,我似乎需要在try/catch块中创建文件.如果我尝试在try/catch块之外创建它,然后像这样在块中初始化它,

RandomAccessFile valueFile; 

try
{
    valueFile = new RandomAccessFile("valuefile.txt", "rw");
    for (int i=0; i<numOfNums; i++)
        valueFile.writeDouble(randomizer.nextDouble()*200);
}
catch (Exception e)
{
    System.out.println("Couldn't find the values file.");
    System.exit(0);
}

for (int i=0; i<numOfNums; i++)
{
    double total = 0;
    valueFile.seek(0); // go to beginning of file to start reading it.
}
Run Code Online (Sandbox Code Playgroud)

然后我得到错误"未报告的异常java.io.IOException;必须被捕获或声明被抛出".(我也得到"变量valueFile可能尚未初始化".)

但是,当我的try/catch内创建它,这样,

try
{
    RandomAccessFile valueFile = new RandomAccessFile("valuefile.txt", "rw");
    for (int i=0; i<numOfNums; i++)
        valueFile.writeDouble(randomizer.nextDouble()*200);
}
catch (Exception e)
{
    System.out.println("Couldn't find the values file.");
    System.exit(0);
}

for (int i=0; i<numOfNums; i++)
{
    double total = 0;
    valueFile.seek(0);
}
Run Code Online (Sandbox Code Playgroud)

我在程序的后半部分得到"找不到符号:变量值文件".我认为那是因为valueFile被认为是try/catch块的本地?但是,我如何创建valueFile,因此它不是 try/catch块的本地?

Jon*_*eet 5

第一个版本几乎是正确的 - 但有两个问题:

  1. 您的方法没有声明它可以 throw IOException,但您的使用valueFile.seek可能会引发异常。您要么需要更改方法声明,要么捕获并处理异常。

  2. 编译器不知道它System.exit(0)永远不会正常返回——它认为这是一个正常的方法。所以你必须改变你的 catch 块,以这样的方式结束:

    return;
    
    Run Code Online (Sandbox Code Playgroud)

    或者

    throw new AssertionError("We'll never get here.");
    
    Run Code Online (Sandbox Code Playgroud)

    在这一点上,编译器知道如果它超出了 try/catch 块,valueFile 肯定会被赋值。

请注意,如果您移动块内的所有内容catch,两个问题都会消失 - 但我建议您最好不要捕捉任何东西,而只是声明该方法可能会抛出IOException

public void foo(int iterations) throws IOException {
    RandomAccessFile valueFile = new RandomAccessFile("valuefile.txt", "rw");
    for (int i = 0; i < iterations; i++) {
        valueFile.writeDouble(randomizer.nextDouble()*200);
    }

    for (int i = 0; i< iterations; i++) {
        double total = 0;
        valueFile.seek(0);
        // Presumably you'd read the contents here?
    }
}
Run Code Online (Sandbox Code Playgroud)

...除非您在完成文件后应该关闭该文件,如果您使用的是 Java 7,则使用 try-with-resources 语句,否则仅使用 try/finally 块。


Dao*_*Wen 5

我认为你的第一种方法是正确的.错误不是由文件创建引起的,而是由valueFile.seek(0);调用引起的.这也可以抛出IO异常,因此您也需要在try/catch块中使用它.

编辑:正如Jon指出的那样,您的代码仍然无法编译,因为valueFile可能未初始化.只需初始化它就可以了null.

RandomAccessFile valueFile = null; 
Run Code Online (Sandbox Code Playgroud)

您可以使用Jon的答案中描述的方法之一来说服编译器valueFile在到达时实际初始化valueFile.seek(0).他的方法更安全,但只是初始化null是一个很好的快速修复,因此您不必使用无法访问的throw语句混乱您的代码.

但是,我认为如果您只是移动声明,使用新的初始化RandomAccessFile以及对同try一块内的文件的所有访问都会更好.我想不出有什么好理由将它们分开.