【问题标题】:What does it mean when the main method throws an exception?main方法抛出异常是什么意思?
【发布时间】:2012-12-08 00:56:46
【问题描述】:

我正在复习我为明天早上的期末考试做的期中考试。这个问题我答错了,但没有指出正确的答案,我忘了问教授。

考虑以下代码sn-p:

public static void main(String[] args) throws FileNotFoundException

以下关于这段代码的说法正确的是?

  1. main 方法旨在捕获和处理所有类型的异常。
  2. main 方法旨在捕获和处理FileNotFoundException
  3. 如果出现FileNotFoundException,主方法应该简单地终止。
  4. 如果发生任何异常,主方法应该简单地终止。

我选择了第二个选项。

【问题讨论】:

    标签: java exception


    【解决方案1】:

    答案是4,

    4.- 如果发生任何异常,主方法应该简单地终止。

    throws 子句仅声明该方法抛出一个检查过的 FileNotFoundException 并且调用方法应该捕获或重新抛出它。如果在 main 方法中抛出(而不是捕获)未经检查的异常,它也会终止。

    检查这个测试:

    public class ExceptionThrownTest {
    
        @Test
        public void testingExceptions() {
    
            try {
                ExceptionThrownTest.main(new String[] {});
            } catch (Throwable e) {
                assertTrue(e instanceof RuntimeException);
            }
    
        }
    
        public static void main(String[] args) throws FileNotFoundException {
    
            dangerousMethod();
    
            // Won't be executed because RuntimeException thrown
            unreachableMethod();
    
        }
    
        private static void dangerousMethod() {
            throw new RuntimeException();
        }
    
        private static void unreachableMethod() {
            System.out.println("Won't execute");
        }
    }
    

    如您所见,如果我抛出RuntimeException,即使抛出的异常不是FileNotFoundException,该方法也会终止

    【讨论】:

    • 嗯,但问题是关于 public static void main(String[] args) throws FileNotFoundException 签名,不是一般的
    • 好吧,测试一下,如果你抛出除FileNotFoundException 之外的检查异常,它将无法编译。否则,如果该方法抛出一个未经检查的异常,那么它将简单地结束传播未经检查的异常。
    • 你觉得我的回答怎么样?
    • 也许 Effective Java 的第 59 条 Item 59: Avoid unnecessary use of checked exceptions 发挥作用:If the programmer using the API can do no better, an unchecked exception would be more appropriate. 换句话说,在 main throws XException... 的情况下,未检查的异常可能更合适。
    • @rimalonfire 在那里使用单元测试来展示它。只是一个例子。
    【解决方案2】:

    伙计,有点晚了,但答案是 3 号。

    数字 1 为假,因为它没有处理 FileNotFoundException

    出于同样的原因,数字 2 是错误的。

    第 3 点是正确的。如果抛出 FileNotFoundException,main 方法将终止。

    数字 4 是错误的。如果出现任何异常,它不会终止。它只会在未经检查的异常或 FileNotFoundException 的情况下终止。如果 'throws' 子句中没有声明其他检查异常,则表示它们正在方法中处理。

    【讨论】:

    • 这个答案显然是错误的。为什么对此没有任何 cmets 或否决票?只有throws 没有任何try-catch 语句的方法将处理异常。
    • 我认为这个练习的目的是想象 main 方法里面有什么。我同意它为模棱两可和假设留下了空间。但是,由于它抛出 FileNotFoundException 我假设正在处理任何其他检查的异常(使用 try-catch)。另外我认为它没有处理未经检查的异常。
    • @user3437460 你错了。您不需要函数中的try 块来让函数抛出异常。如果列出为抛出异常的函数调用 另一个 抛出该异常的函数,则该异常将简单地向上传递到堆栈。
    【解决方案3】:

    main 方法没有捕获任何异常,而是通过将 FileNotFoundException 扔给调用 main 方法的源来处理它。

    系统运行时启动JVM类,JVM类中的一个特定类调用main方法。

    在这种情况下,对 main 方法的 throws 的处理由 JVM 类决定。

    • 您可以在 Oracle 提供的Java language specification 中了解它。
    • 此外,您还可以查看一些可用的 JVM 的源代码,尽管走这条路会带您转向其他编程语言,OpenJdk

    我想在这个主题上分享我的小型研究外壳,希望它对好奇的人有所帮助:)

    【讨论】:

      【解决方案4】:

      我同意其他一些答案,即问题的正确答案是选项 3。选项 4 说:

      1. 如果发生任何异常,主方法应该简单地终止。

      注意此选项中的“任何”。下面是一个发生异常但main() 没有终止的代码示例:

      public static void main(String[] args) throws FileNotFoundException {
          try {
              methodThatThrowsACheckedException();
          } catch (SomeCheckedException e) {
              // do something to handle this exception
          }
      }
      

      在此代码中发生了异常,但该方法并未终止,因为它已设置为处理此异常。如果异常是未捕获的UncheckedException,那么该方法当然会终止。但是,选项 4 的要点是,任何反例都会使其无效,因为它说发生了“任何”异常。

      然而,选项 3 将这种终止限制为仅在引发方法签名中的异常时发生:

      1. 如果出现FileNotFoundException,主方法应该简单地终止。

      选项 3 更有意义的原因是因为下面的代码在实践中没有意义:

      public static void main(String[] args) throws FileNotFoundException {
          try {
              methodThatThrowsFileNotFoundException();
          } catch (FileNotFoundException e) {
              // do something to handle this exception
          }
      }
      

      声明一个方法抛出异常没有多大意义,但在方法中捕获该异常(除非,也许,你在做某事后重新抛出它,在这种情况下,选项 3 仍然成立,因为方法最终终止)。

      【讨论】:

        【解决方案5】:

        仅凭main()的声明,无法判断哪个答案是客观正确的。根据方法的定义,任何陈述都可能为真。

        1. main 方法旨在捕获和处理所有类型的异常。

        2. main 方法旨在捕获和处理FileNotFoundException

        以上两种说法都适用于以下情况:

        public static void main(String[] args) throws FileNotFoundException {
            while (true) {
                try {
                    doSomething();
                }
                catch (Exception e) {}
            }
        }
        

        main() 从未抛出声明的异常,但这不是错误;只是毫无意义和误导。

        1. 如果出现FileNotFoundException,主方法应该简单地终止。

        2. 如果发生任何异常,主方法应该简单地终止。

        以上两种说法都适用于以下情况:

        public static void main(String[] args) throws FileNotFoundException {
            try {
                doSomething();
            }
            catch (Exception e) {
                return;
            }
        } 
        

        当然,我们可以根据一个体面且合理的程序员可能打算与此方法签名进行通信来猜测问题的意图。这将是他们打算使用该方法抛出FileNotFoundException,并必须处理其他已检查的Exceptions。我们也可以合理地假设“handle”不仅仅意味着“process”,而且特别是它不会(重新)抛出这样的异常。

        这些假设立即排除了 #1 和 #2。

        剩下的问题是“简单终止”是包括抛出异常,还是只包括显式的return/System.exit()。在前一种情况下,#3 和#4 都可能为真:

        public static void main(String[] args) throws FileNotFoundException {
            try {
                doSomething();
            }
            catch (FileNotFoundException fnfe) {
                throw fnfe;
            }
            catch (Exception e) {
                return;
            }
        }
        

        在后一种情况下,#3 和 #4 都不可能为真,同时满足main() 将抛出FileNotFoundException 的假设。


        总之,选项措辞不好。如果我必须选择一个答案,那将是基于 MartinV 答案的逻辑的#3。我的假设是#3中的“应该”这个词是教授的一个不幸的选择,而像“可能”这样的词会是一个更好的选择。使用比“简单终止”(并且可以说是“处理”)更精确的语言也是一个好主意。

        【讨论】:

        • “发生”这个词也不是特别精确。我想说一个在内部抛出和捕获的异常仍然“发生”,但不会影响 main 的行为。
        【解决方案6】:
        1. main() 最终会抛出 all 未处理的异常,对吧?因此,有效地添加 throws FileNotFoundException 是多余的。

        2. throws 语句没有暗示方法如何处理异常。这个main()方法确实可以处理FileNotFoundException,然后重新抛出。

        所以,throws 声明没有说明任何异常是如何被捕获和处理的。只有当我们假设它没有处理了有问题的异常时,问题 3 和 4 才有效。没有这个假设,问题是不确定的。有了这个假设,3 和 4 都是真的!

        正确的答案是要求学校为这门课退款——即使是在 6.5 年后。

        能否转发一下这位老师的联系方式?我想和他们谈谈。

        【讨论】:

          【解决方案7】:

          虽然已经为这个问题选择了答案,但我认为你的测试的正确答案是数字 3:

          1. 如果发生 FileNotFoundException,主方法应该简单地终止。

          因为它说应该,而不是
          我的意思是,方法中的代码可以捕获任何异常,包括已检查和未检查的异常,或者吞下、恢复或重新抛出异常——或者根本无法捕获它们。

          但是,如果它捕获了 FileNotFoundException 而没有最终(重新)抛出它,那么它就违反了自己的合同:任何调用者都不会看到方法签名中所述的异常,因为方法处理了它(甚至可能在这种情况下编译器可能会抱怨,说永远不会抛出异常,但我不确定)。

          我认为你的期中考试提出了一个关于设计而不是具体实现的问题。

          【讨论】:

          • throws FileNotFoundException 合约指定它可能抛出该异常,而不是它必须抛出它。我同意,只有在打算在某些情况下抛出它时才包含它是合理的,但这不是合同要求。
          【解决方案8】:

          答案是 2 和 3。

          2.main方法是为了捕捉和处理FileNotFoundException而设计的。 3.如果发生 FileNotFoundException,main 方法应该简单地终止。

          但是如果即使它被设计来处理它也无法处理异常,并且程序会异常终止。

          throws 关键字用于让JVM处理我们懒惰处理的异常,它编译成功但在运行时显示异常(如果你在main方法中处理它,它编译并运行成功)。

          4.如果发生任何异常,主方法应该简单地终止。 并不总是正确的,因为发生的异常可能在 main 方法中处理。

          1.main方法旨在捕获和处理所有类型的异常。不正确,因为JVM不处理未经检查的异常。

          【讨论】:

            猜你喜欢
            • 2011-01-04
            • 1970-01-01
            • 2014-08-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多