【问题标题】:Checked exception and initializer block检查异常和初始化程序块
【发布时间】:2015-07-31 02:13:05
【问题描述】:

根据 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 子句,前面的代码还是编译不出来?

【问题讨论】:

  • 你告诉初始化程序块抛出无条件异常,你还能期待什么?

标签: java


【解决方案1】:

应该有一些条件才能真正完成初始化,没有任何异常。

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

试试:

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) 并不总是抛出该异常。

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

【讨论】:

  • +1 有效。但是为什么我们需要一个条件语句?不能只是抛出异常吗??
  • @PremGenError:这就像在没有条件检查的 return 语句之后编写代码。编译器也可以检测到这一点,在这种情况下也是如此。
  • 好的,但如果它总是抛出错误怎么办?我正在处理它。
  • @SalilMisra:“......总是抛出错误”。你能解释更多吗?
  • 让我说 if(true) 然后抛出这个异常。为什么这是允许的,而不是这个。
【解决方案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 语句用于“条件编译”目的,实际规则有所不同。

...

【讨论】:

    【解决方案3】:

    在第一种情况下,编译器已经知道实例初始化程序永远不会正常完成,因为您已经明确地将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(true) 替换条件if ( k == 90),那么编译器将不会显示错误。因为编译器现在知道i 肯定会被赋值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多