7

根据 JLS:如果命名类的实例变量初始化程序或实例初始化程序可以抛出已检查的异常类,则这是编译时错误,除非该异常类或其超类之一在每个构造函数的 throws 子句中显式声明它的类并且该类至少有一个显式声明的构造函数。

所以如果我这样做 -

class A{
 {
  throw new FileNotFoundException();
 }
public A() throws IOException{
    // TODO Auto-generated constructor stub
}
}

这给出了编译时错误“初始化程序必须正常完成”

尽管

class A{
 {
  File f=new File("a");
  FileOutputStream fo=new FileOutputStream(f);
  fo.write(3);
 }
public A() throws IOException{
    // TODO Auto-generated constructor stub
}
}

此代码不显示任何编译时错误。为什么即使我在构造函数中声明了 throws 子句,前面的代码也无法编译?

4

3 回答 3

4

初始化程序实际上可以毫无例外地完成时应该有一些条件。

在你的情况下,它不可能发生。

尝试:

if(/*condition-to-fail*/) {
    /*Not always, only when something is wrong. Compiler knows that.*/
    throw new FileNotFoundException(); 
}

更新:

下面的语句实际上是在抛出异常。

throw new FileNotFoundException(); 

因此,没有任何条件,您的程序执行总是在那里结束。

虽然在以下 -

FileOutputStream fo = new FileOutputStream(f);

构造函数FileOutputStream(File)并不总是抛出该异常。

中的 throws 子句public FileOutputStream(File file) throws FileNotFoundException只是说它可能会抛出该异常,并且只有在运行时找不到文件时才会这样做,否则不会。

于 2013-02-23T15:38:26.553 回答
2

http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.6

如果实例初始化程序无法正常完成,则为编译时错误

http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.21

一个不是 switch 块的非空块可以正常完成,前提是它的最后一条语句可以正常完成。

...

if 语句,无论它是否具有 else 部分,都以不寻常的方式处理。因此,在本节末尾单独讨论。

...

为了让 if 语句方便地用于“条件编译”目的,实际规则有所不同。

...

于 2013-02-23T16:16:00.273 回答
1

在第一种情况下,编译器已经知道实例初始化程序永远不会正常完成,因为您已经明确地抛出FileNotFoundException了那里。你可以说它是编译器的智能代码评估。但是,如果您让编译器相信实例初始化程序有一点点成功完成的机会,那么编译器就不会在编译时抱怨。例如,在下面给出的代码中,虽然文件IDonotexist.txt在我的目录中不存在,我确信它会抛出FileNotFoundException,但编译器仍然会让它编译成功。为什么?因为文件的存在是在代码执行期间检查的,而不是在编译时检查的。

class A
{
    {
        FileReader fr = new FileReader(new File("IDonotexist.txt"));
    }
    public A() throws IOException
    {
        // TODO Auto-generated constructor stub
    }
    public static void main(String st[])throws Exception
    {
        A a = new A();
    }
}

这类似于最终变量初始化的情况。例如以下代码中的示例,编译器将显示编译时错误

public void calling()
    {
        final int i;
        int k = 90;
        if ( k == 90)
        {
            i = 56;
        }
        System.out.println(i);//Compiler will show error here as: variable i might not have been initialized
    }

但是,如果我将条件替换为if ( k == 90)thenif(true)编译器将不会显示错误。因为编译器现在知道i肯定会被赋予一些价值。

于 2013-02-23T16:20:16.403 回答