⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tij0101.html

📁 学习java的经典书籍
💻 HTML
字号:
<html><body>

<table width="100%"><tr>
<td>
<a href="http://www.bruceeckel.com/javabook.html">Bruce Eckel's Thinking in Java</a>
</td>
<td align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0100.html">Prev</a> | <a href="tij0102.html">Next</a>
</td>
</tr></table>
<hr>

<H2 ALIGN=LEFT>
Exception
restrictions
<P><A NAME="Index947"></A><A NAME="Index948"></A></H2>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">When
you override a method, you can throw only the exceptions that have been
specified in the base-class version of the method. This is a useful
restriction, since it means that code that works with the base class will
automatically work with any object derived from the base class (a fundamental
OOP concept, of course), including exceptions.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
example demonstrates the kinds of restrictions imposed (at compile time) for
exceptions:
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#009900">//: StormyInning.java</font>
<font color="#009900">// Overridden methods may throw only the </font>
<font color="#009900">// exceptions specified in their base-class </font>
<font color="#009900">// versions, or exceptions derived from the </font>
<font color="#009900">// base-class exceptions.</font>

<font color="#0000ff">class</font> BaseballException <font color="#0000ff">extends</font> Exception {}
<font color="#0000ff">class</font> Foul <font color="#0000ff">extends</font> BaseballException {}
<font color="#0000ff">class</font> Strike <font color="#0000ff">extends</font> BaseballException {}

<font color="#0000ff">abstract</font> <font color="#0000ff">class</font> Inning {
  Inning() <font color="#0000ff">throws</font> BaseballException {}
  <font color="#0000ff">void</font> event () <font color="#0000ff">throws</font> BaseballException {
   <font color="#009900">// Doesn't actually have to throw anything</font>
  }
  <font color="#0000ff">abstract</font> <font color="#0000ff">void</font> atBat() <font color="#0000ff">throws</font> Strike, Foul;
  <font color="#0000ff">void</font> walk() {} <font color="#009900">// Throws nothing</font>
}

<font color="#0000ff">class</font> StormException <font color="#0000ff">extends</font> Exception {}
<font color="#0000ff">class</font> RainedOut <font color="#0000ff">extends</font> StormException {}
<font color="#0000ff">class</font> PopFoul <font color="#0000ff">extends</font> Foul {}

<font color="#0000ff">interface</font> Storm {
  <font color="#0000ff">void</font> event() <font color="#0000ff">throws</font> RainedOut;
  <font color="#0000ff">void</font> rainHard() <font color="#0000ff">throws</font> RainedOut;
}

<font color="#0000ff">public</font> <font color="#0000ff">class</font> StormyInning <font color="#0000ff">extends</font> Inning 
    <font color="#0000ff">implements</font> Storm {
  <font color="#009900">// OK to add new exceptions for constructors,</font>
  <font color="#009900">// but you must deal with the base constructor</font>
  <font color="#009900">// exceptions:</font>
  StormyInning() <font color="#0000ff">throws</font> RainedOut, 
    BaseballException {}
  StormyInning(String s) <font color="#0000ff">throws</font> Foul, 
    BaseballException {}
  <font color="#009900">// Regular methods must conform to base class:</font>
<font color="#009900">//! void walk() throws PopFoul {} //Compile error</font>
  <font color="#009900">// Interface CANNOT add exceptions to existing</font>
  <font color="#009900">// methods from the base class:</font>
<font color="#009900">//! public void event() throws RainedOut {}</font>
  <font color="#009900">// If the method doesn't already exist in the</font>
  <font color="#009900">// base class, the exception is OK:</font>
  <font color="#0000ff">public</font> <font color="#0000ff">void</font> rainHard() <font color="#0000ff">throws</font> RainedOut {}
  <font color="#009900">// You can choose to not throw any exceptions,</font>
  <font color="#009900">// even if base version does:</font>
  <font color="#0000ff">public</font> <font color="#0000ff">void</font> event() {}
  <font color="#009900">// Overridden methods can throw </font>
  <font color="#009900">// inherited exceptions:</font>
  <font color="#0000ff">void</font> atBat() <font color="#0000ff">throws</font> PopFoul {}
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
    <font color="#0000ff">try</font> {
      StormyInning si = <font color="#0000ff">new</font> StormyInning();
      si.atBat();
    } <font color="#0000ff">catch</font>(PopFoul e) {
    } <font color="#0000ff">catch</font>(RainedOut e) {
    } <font color="#0000ff">catch</font>(BaseballException e) {}
    <font color="#009900">// Strike not thrown in derived version.</font>
    <font color="#0000ff">try</font> {
      <font color="#009900">// What happens if you upcast?</font>
      Inning i = <font color="#0000ff">new</font> StormyInning();
      i.atBat();
      <font color="#009900">// You must catch the exceptions from the</font>
      <font color="#009900">// base-class version of the method:</font>
    } <font color="#0000ff">catch</font>(Strike e) {
    } <font color="#0000ff">catch</font>(Foul e) {
    } <font color="#0000ff">catch</font>(RainedOut e) {
    } <font color="#0000ff">catch</font>(BaseballException e) {}
  }
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Inning</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you can see that both the constructor and the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>event(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method say they will throw an exception, but they never do. This is legal
because it allows you to force the user to catch any exceptions that you might
add in overridden versions of 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>event(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
The same idea holds for 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>abstract</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods, as seen in 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>atBat(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface
Storm
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is interesting because it contains one method (
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>event(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)that
is defined in 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Inning</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and one method that isn&#8217;t. Both methods throw a new type of exception, 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>RainedOut</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
When 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>StormyInning</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>extends
Inning
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>implements
Storm
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you&#8217;ll see that the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>event(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method in 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Storm</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>cannot</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
change the exception interface of 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>event(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Inning</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Again, this makes sense because otherwise you&#8217;d never know if you were
catching the correct thing when working with the base class. Of course, if a
method described in an 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is not in the base class, such as 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>rainHard(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">then
there&#8217;s no problem if it throws exceptions.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
restriction on exceptions does not apply to <A NAME="Index949"></A><A NAME="Index950"></A>constructors.
You can see in 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>StormyInning
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">that
a constructor can throw anything it wants, regardless of what the base-class
constructor throws. However, since a base-class constructor must always be
called one way or another (here, the default constructor is called
automatically), the derived-class constructor must declare any base-class
constructor exceptions in its exception specification.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
reason 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>StormyInning.walk(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
will not compile is that it throws an exception, while 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Inning.walk(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
does not. If this was allowed, then you could write code that called 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Inning.walk(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and that didn&#8217;t have to handle any exceptions, but then when you
substituted an object of a class derived from 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Inning</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
exceptions would be thrown so your code would break. By forcing the
derived-class methods to conform to the exception specifications of the
base-class methods, substitutability of objects is maintained.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
overridden 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>event(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method shows that a derived-class version of a method may choose to not throw
any exceptions, even if the base-class version does. Again, this is fine since
it doesn&#8217;t break any code that is written assuming the base-class version
throws exceptions. Similar logic applies to 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>atBat(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which throws 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>PopFoul</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
an exception that is derived from 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Foul</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
thrown by the base-class version of 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>atBat(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
This way, if someone writes code that works with 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Inning</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and calls 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>atBat(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
they must catch the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Foul</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
exception. Since 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>PopFoul</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is derived from 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Foul</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
the exception handler will also catch 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>PopFoul</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
last point of interest is in 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Here you can see that if you&#8217;re dealing with exactly a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>StormyInning</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object, the compiler forces you to catch only the exceptions that are specific
to that class, but if you upcast to the base type then the compiler (correctly)
forces you to catch the exceptions for the base type. All these constraints
produce much more robust exception-handling code.
</FONT><A NAME="fnB43" HREF="#fn43">[43]</A><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">It&#8217;s
useful to realize that although exception specifications are enforced by the
compiler during inheritance, the exception specifications are not part of the
type of a method, which is comprised of only the method name and argument
types. Therefore, you cannot overload methods based on exception
specifications. In addition, because an exception specification exists in a
base-class version of a method doesn&#8217;t mean that it must exist in the
derived-class version of the method, and this is quite different from
inheriting the methods (that is, a method in the base class must also exist in
the derived class). Put another way, the &#8220;exception specification
interface&#8221; for a particular method may narrow during inheritance and
overriding, but it may not widen &#8211; this is precisely the opposite of the
rule for the class interface during inheritance.
</FONT><a name="_Toc408018601"></a><P></DIV>
<HR><DIV ALIGN=LEFT><A NAME="fn43" HREF="#fnB43">[43]</A><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
ANSI/ISO C++ added similar constraints that require derived-method exceptions
to be the same as, or derived from, the exceptions thrown by the base-class
method. This is one case in which C++ is actually able to check exception
specifications at compile time.
</FONT><P></DIV>


<div align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0100.html">Prev</a> | <a href="tij0102.html">Next</a>
</div>
</body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -