在阅读Why can't overriding methods throw exceptions之后,我理解如果声明为抛出Checked异常的方法,则子类中的重写方法只能声明抛出该异常或其子类:
class A {
public void foo() throws IOException {..}
}
class B extends A {
@Override
public void foo() throws SocketException {..} // allowed
@Override
public void foo() throws SQLException {..} // NOT allowed
}
因为SocketException
IS-A IOException
我可以将覆盖方法声明为抛出IOException
的任何子类。
在我的程序中,我想调用声明为throws FileNotFoundException
IS-A IOException
的重写方法。也用try-catch块处理
import java.io.*;
class Sub extends Super{
public static void main (String [] args){
Super p = new Sub();
try {
p.doStuff();
}catch(FileNotFoundException e){
}
}
public void doStuff() throws FileNotFoundException{}
}
class Super{
public void doStuff() throws IOException{}
}
Sub.java:6: error: unreported exception IOException; must be caught or declared to be thrown
p.doStuff();
^
这是什么原因?我有点困惑,因为Base类也可用于子类。
除了Exception
(与Overriding概念相反)之外,捕捉Throwable
和IOException
的能力也更加令人困惑。
答案 0 :(得分:14)
您的对象引用的类型为Super
,即使您在运行时知道它是Sub
对象。因此,编译器正在检查Super
的方法定义,并为您提供此编译错误。
与获取以下编译器错误没有什么不同:
Object o = new String("Hello World");
o.charAt(2); //Obviously not allowed
重要的是要记住throws
子句是方法定义的一部分。
答案 1 :(得分:11)
这是什么原因?我有点困惑,因为Base类也可用于子类。
您需要抓住IOException
而不是FilenotFoundException
。这是因为虽然子类中的doStuff
方法将在运行时调用,但编译器还不知道这一点。它只知道超类中的doStuff
方法,它声明它throws
和IOException
。
解决您的编辑:catch
块可以选择捕获try
块中预期的确切异常,或者它可以选择捕获异常的超类。这背后的原因与方法覆盖没有任何关系。
答案 2 :(得分:5)
编译器不考虑对象的类型,但是您使用的引用类型为Super
。
作为Super.doStuff() throws IOException
,这是你必须抓住的。
BTW我强烈建议您使用IDE,您会发现它的效率更高。
答案 3 :(得分:3)
将p声明为超级
Super p = ...
您的编译器只知道p
是某种Super
。 Super
doStuff()
引发了IOException
,但您的代码只捕获了IOException
FileNotFoundException
的特例。如果您想告诉您的编译器,这肯定是Sub
而不是Super
,只需将p
声明为Sub
即可。
在这种情况下,它显式未声明为Sub
,而是Super
,因此可能会发生任何Super
或其子项并抛出任何可能不会IOException
FileNotFoundException
是SELECT COUNT(*) As 'Deployed',
DATENAME(YEAR, LastModified) As 'Year',
DATEPART(Month, LastModified),
DATENAME(Month, LastModified) As 'Month'
FROM [InventoryDatabase].[dbo].[Hardware_RefreshList]
WHERE Asset_Type = 'Laptop' AND Status = 'Completed' AND Department != 'SNBc'
AND DATENAME(YEAR, LastModified) = '2017'
GROUP BY DATEPART(Month, LastModified), DATENAME(YEAR, LastModified),
Month(LastModified), DATENAME(Month, LastModified),
DATEADD(MONTH, DATEDIFF(MONTH, 0, LastModified), 0)
ORDER BY DATEPART(Month, LastModified)
或其中任何一个孩子。
答案 4 :(得分:2)
那是因为你使用的是静态类型Super的对象。 编译器无法知道在运行时p指向Sub对象,因此它想要捕获由超类中声明的方法抛出的异常
答案 5 :(得分:2)
因为它按声明的类型进行检查,在本例中为Super
。
我们p
仅包含Sub
的实例,但未知(或已检查)。此外,定义一个超类变量并仅使用它并且仅用于1个特定子类是没有意义的。
因此,您的Super p
包含Super.class
的实例。它的方法doStuff()
可以抛出所有扩展IOException
的内容,比如说UnsupportedEncodingException
,但是你只能抓住FileNotFoundException
,这样Unsupported...
可能会被抛出必须处理。