Overriden method doesn't throw Exception, super may.

V

VisionSet

class Super {

public void myMethod() throws MyException {
other();
}

protected void other() throws MyException {
// may throw MyException
}
}

class Sub extends Super {

protected void other() {
// does not throw MyException
}

public static void main(String[] args) {
// but still MyException must be caught
new Sub().myMethod();
}

}

What is the best way to deal with this
from a nice code point of view?
 
V

VisionSet

VisionSet said:
class Super {

public void myMethod() throws MyException {
other();
}

protected void other() throws MyException {
// may throw MyException
}
}

class Sub extends Super {

protected void other() {
// does not throw MyException
}

public static void main(String[] args) {
// but still MyException must be caught
new Sub().myMethod();
}

}

What is the best way to deal with this
from a nice code point of view?

Liz said:
what exactly is your question?
deal with what?
what is nice other than a unix command?

Too cryptic for you?

Executing the main method shown, I know at compile time there won't be an
exception thrown, yet I must still catch it.
How best to deal with this, since from a self documenting stance this is
misleading.
 
C

Chris Smith

VisionSet said:
What is the best way to deal with this
from a nice code point of view?

In a generalized form, this is a fairly common problem. It arises
frequently, for example, when using ByteArrayInputStream (which never
throws IOException) with code that's written to use a generic
InputStream. In your case, the more generic code is inherited from the
superclass, but the same principles apply.

If you feel that you can prove the exception is impossible, then catch
it, wrap it in RuntimeException, and rethrow. Ensure, as always, that
you don't ignore RuntimeException (i.e., at the very least do some form
of logging) so that you can troubleshoot easier when your assumption is
violated in future versions of the code.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
J

Java Architect

Actually, it's not a problem at all. If the overridden method doesn't throw
the exception, it doesn't throw it. Compile the app and see that you don't
get a single complaint.

Now, if you turn it around (super doesn't declare an exception, but the
sub-class impl does) you have a design problem.
 
V

VisionSet

Java Architect said:
Actually, it's not a problem at all. If the overridden method doesn't throw
the exception, it doesn't throw it. Compile the app and see that you don't
get a single complaint.

MyMethod is declared to throw a checked Exception (Okay I didn't explicitly
say that MyException was checked, but it was;-) Therefore it must be caught
or passed down the line. The code would not compile therefore since the
call in main does not do that.
Now, if you turn it around (super doesn't declare an exception, but the
sub-class impl does) you have a design problem.

naturally.

(Thanks Chris!)
 
C

Chris Smith

Java said:
Actually, it's not a problem at all. If the overridden method doesn't throw
the exception, it doesn't throw it. Compile the app and see that you don't
get a single complaint.

You mistake the situation. It's more complicated than that. Go back a
few posts and read Mike's code, and you'll see that there is indeed a
problem. It belongs to a fairly common class of situations in which you
call a method that's declared to throw an exception, yet you have inside
information telling you that the exception will be impossible. Here's
another example, which I mentioned in an earlier response to Mike:

try
{
Properties p = new Properties();
p.setProperty("a", "b");
p.setProperty("c", "d");

ByteArrayOutputStream out = new ByteArrayOutputStream();
p.store(out);
}
catch (IOException e)
{
// What do you do here? This exception is not really possible.
// My answer:
throw new RuntimeException(e);
}

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
T

Tony Morris

VisionSet said:
class Super {

public void myMethod() throws MyException {
other();
}

protected void other() throws MyException {
// may throw MyException
}
}

class Sub extends Super {

protected void other() {
// does not throw MyException
}

public static void main(String[] args) {
// but still MyException must be caught
new Sub().myMethod();
}

}

What is the best way to deal with this
from a nice code point of view?

Super s = new Sub();

try {
s.other();
}
catch(MyException me) {
throw new RuntimeException("You should never ever see this!");
}

OR

Sub s = new Sub();
s.other();

Which you choose depends on design requirements.
 
J

Java Architect

Converting to a runtime exception is dangerous and unnecessary.

* You have a reference type of the superclass, and it says that the method
might throw an exception. You have to catch it or declare that you don't
handle it. It doesn't matter that you know the subclass doesn't throw it. If
you want to rely on the fact that it's a subclass implementation you're
dealing with, catch it and do nothing: Dangerous because the underlying code
may change in the future.

* Converting to a runtime exception puts you in the undesireable position of
having to modify all the calling code should the implementation change. This
would be devastating if you're publishing a library or framework where it
may be third party software that's doing the calling.

* The 3rd pillar of OOP is encapsulation. You're breaking that by relying on
the internal implementation of a subclass when you're code says you're
dealing with the superclass.

BTW, please don't take this as argumentative. I'm just trying to help create
more robust code.
 
J

Java Architect

If the main method doesn't handle the exception, and you don't want to
bother with it (because you think it will never happen) then declare the
Main method to throw it:

public void main(String[] args) throws IOException
{
...
}

Hope this helps.
 
C

Chris Smith

Unfortunately, you still don't seem to understand the question being
asked. You're answering the problem of how to deal with this:

public abstract class A
{
public abstract void someMethod() throws MyException;
}

public abstract class B extends A
{
public void someMethod() { ... }
}

A a = new B();
a.someMethod();

Your answer makes a lot of sense for that scenario. Unfortunately,
though, the problem being discussed is different. It looks like this:

public abstract class A
{
public abstract void someMethod() throws MyException
{
otherMethod();
}

public abstract void otherMethod() throws MyException;
}

public abstract class B extends A
{
public void otherMethod() { ... }
}

B b = new B();
b.someMethod()

or, my alternative form of the same problem from earlier in this thread
(which uses standard API classes to avoid some of the complex details):

Properties p = new Properties();
p.setProperty("a", "b");
p.setProperty("c", "d");

ByteArrayOutputStream out = new ByteArrayOutputStream();
p.store(out);

In the first case, encapsulation and such is important and nesting a
checked exception into a runtime exception is indeed dangerous and
unnecessary. In the latter case, throwing a checked exception from the
client code is not only perfectly safe, but is in fact crucial for
maintaining a level of abstraction and encapsulation that is proper for
that section of code.

You're right that there is a piece of code in all of cases that doesn't
carry knowledge that a subclass implementation is being used. In Mike's
formulation (but my code above), it's the implementation of someMethod()
in A. In my example with Properties, it's the implementation of
store(OutputStream) in Properties. Neither piece of code *should* know
about the subclass.

That doesn't change the fact that the client code should -- and in fact
DOES -- know that you're using a subclass, and therefore that the
exception will not be thrown! That leaves you with three choices:

1. Catch the checked exception and continue without throwing an
exception. This is an immensely horrible idea, and I'm sure no one is
seriously suggesting this. Just getting it out of the way.

2. Catch the checked exception and wrap it in a RuntimeException. This
is my suggestion. Frankly, I don't understand your claim that this
causes client code to have to change due to changes in implementation
detail. In fact, it prevents that problem, relative to the third choice
below...

3. Declare these false exceptions in the 'throws' clause of a method,
and leave it up to the client code to handle them. As opposed to
preserving encapsulation, this is in fact a blatant violation of it. It
exposes the implementation details of the underlying method's code
(i.e., that it uses an I/O stream to do its work, even if that I/O
stream is only used to write to memory). Because of that, it causes the
client interface to logically change as a result of changes to the
implementation details such as use of an in-memory I/O stream.

Basically, building wrong abstractions is never the way to improve code
reliability -- or do anything else except confusion for that matter.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
J

Java Architect

Chris,

You're right. I don't understand the 'problem.' I believe you're talking
about something like this:

public class A { String f() throws Exception { return "a"; } }

public class B extends A { String f() { return "b"; } }

public class C {
public static void main(String[] args) {
B b = new B();
System.out.println(b.f());
}
}

If' I've correctly exemplified your 'problem', then there is no problem.
This compiles and runs (output is "b") just fine.

You only get compile errors if C's main method looked like:

public static void main(String[] args) {
A b = new B();
System.out.println(b.f())
}

So, again, go back and read my 'solutions.' Converting a checked exception
to a runtime exception is a bad idea and should only be done if absolutely
necessary (comes up when extending poorly designed API's).
 
J

Java Architect

As for breaking encapsulation, I was referring to the problem:

A a = new B();
try {
a.f();
}
catch (Exception ignore) {
// Ignored because the implementation doesn't actually throw this
}

This is violating Encapsulation, converting to a RuntimeException absolutely
does not change that.
 
J

Java Architect

Sorry, hotkey'd the post before I was finished...

Your solution to this kind of problem by simply converting to a
RuntimeException is flat horrid. In the OP's post, he's talking about the
main method, so yes, if you're not going to handle the exception, just
declare it in the throws clause and move on.

In the case of a generic library that other code will depend on, hide the
implementation details by creating an Exception class that is checked but
not implementation dependent:

Let's reframe the issue in terms of a DAO. You're right Say you are writing
a DAO for an app that needs to find a set of X's given some search S. Let's
develop the method signature. First attempt might be:

public interface Dao {
Set findX(Search s);
}

Of course, this puts us in a similar situation to what you are describing.
Using your idea (throw a runtime exception), and assuming our original
implementation is a JDBC implementation, the code would look something like:

public class jdbcDao implements Dao {
Set findX(Search s) {
try {
// JDBC stuff
}
catch (SQLException err) {
throw new RuntimeException(err);
}
}
}

Ouch! See how bad this is for the calling code? Let's make things better:

public interface Dao {
Set findX(Search s) throws SQLException;
}

public class jdbcDao implements Dao {
Set findX(Search s) throws SQLException {
// Some JDBC stuff
}
}

Okay (ignore the possible leaking connections ;)), now calling code knows
that it has to deal with an exception, but, tomorrow, your boss says he
wants an implementation using LDAP. Uh oh!

public class jndiDao implements Dao {
Set findX(Search s) throws SQLException {
try {
// some JNDI stuff to access the LDAP server
}
catch (NamingException err) {
throw new RuntimeException(err);
}
}
}

Just as bad as our first solution, and brought on by the fact that the
interface itself breaks encapsulation. Better would have been:

public DaoException extends Exception { ... }

public interface Dao { Set findX(Search s) throws DaoException; }

public class jdbcDao implements Dao {
Set findX(Search s) throws DaoException {
try {
// Some Jdbc stuff
}
catch (SQLException err) {
throw new DaoException(err);
}
}
}

public class jndiDao implements Dao {
Set findX(Search s) throws DaoException {
try {
// some JNDI stuff to access the LDAP server
}
catch (NamingException err) {
throw new DaoException(err);
}
}
}

You're right, building bad abstractions is a bad thing. However, instead of
simply converting to a runtime exception, build a better abstraction.


public Dao
 
T

Tony Morris

Your solution to this kind of problem by simply converting to a
RuntimeException is flat horrid. In the OP's post, he's talking about the
main method, so yes, if you're not going to handle the exception, just
declare it in the throws clause and move on.

I disagree.
Throwing a RuntimeException when an application enters a state that should
have never been encountered (unforeseeable) is a perfectly valid reason for
doing so - perhaps even the only valid reason.

int i = 7;
if(i != 7) {
/// should never get here.
throw new RuntimeException("i should be 7");
}


InputStream in = new SomeInMemoryStreamThatNeverFails();
try {
in.read();
}
catch(IOException ioe) {
throw new RuntimeException("Should never get here");
}

These two situations are analogous.
 
C

Chris Smith

Java said:
You're right. I don't understand the 'problem.' I believe you're talking
about something like this:

public class A { String f() throws Exception { return "a"; } }

public class B extends A { String f() { return "b"; } }

public class C {
public static void main(String[] args) {
B b = new B();
System.out.println(b.f());
}
}

No, we're NOT talking about that. I've explained that three times, now,
and I give up. If my previous posts confuse you, then please go back
and ask about the parts that are confusing. Right now, you seem to be
ignoring me, so I'm doubtful that repeating myself for a fourth time
would help the situation.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
J

John C. Bollinger

Chris said:
That doesn't change the fact that the client code should -- and in fact
DOES -- know that you're using a subclass, and therefore that the
exception will not be thrown! That leaves you with three choices:

1. Catch the checked exception and continue without throwing an
exception.
[...]

2. Catch the checked exception and wrap it in a RuntimeException.
[...]

3. Declare these false exceptions in the 'throws' clause of a method,
and leave it up to the client code to handle them.

[...]

4. "assert false;" in the catch block.
As this will generate an AssertionFailedError if triggered, it is in
fact rather similar to Chris' recommendation, (2). It does lose the
details of the exception that caused the problem, but debugging is going
to be necessary anyway and the location of the bad assumption is still
pinpointed. The Error is less likely to be mishandled up the call stack
than a RuntimeException is, but it won't get generated at all if
assertions are disabled at runtime. The assertion has one (to my mind)
clear advantage code-wise: it makes it absolutely clear that it is a
violation of the programmer's assumptions for the unexpected exception
to occur.


John Bollinger
(e-mail address removed)
 
J

Java Architect

Apologies. I finally realized what I was missing about the problem. I
haven't been ignoring you, I've actually been trying to understand the
problem. Now I think I do, and here is how I would handle it (using the
original code):

class Super {

public void myMethod() throws MyException {
other();
}

protected void other() throws MyException {
// may throw MyException
}
}

class Sub extends Super {

protected void other() {
// does not throw MyException
}

// Why not override this as well and bury the non-thrown exception in
// the first place?
public void myMethod() {
// Not good practice to completely ignore the exception, but, the
rule of this
// particular case is that the exception will NEVER be thrown, so,
violating
// the rule of thumb, here, is not particularly bothersome. You
could just as
// easily throw a runtime exception from within the catch, but
that's just a matter
// of style. My take on it is, if the exception can't occur, then
why bother
// writing code to convert it? If you think that there's an off
chance that it might,
// then you should keep it as a checked exception anyway (whether or
not you
// convert it to something that doesn't give away the implementation
details is
// still another style matter.
try { super.myMethod(); } catch (MyException ignore) {}
}

public static void main(String[] args) {
// No need to catch the exception now.
new Sub().myMethod();
}

}

BTW, your example, using the properties file is slightly different and
wouldn't work here because it isn't subclassing the Properties class, so
can't override the method to hide the exception. In Mike's case, he can use
this, which, to me at least is cleaner.

Chris Smith said:
Java said:
You're right. I don't understand the 'problem.' I believe you're talking
about something like this:

public class A { String f() throws Exception { return "a"; } }

public class B extends A { String f() { return "b"; } }

public class C {
public static void main(String[] args) {
B b = new B();
System.out.println(b.f());
}
}

No, we're NOT talking about that. I've explained that three times, now,
and I give up. If my previous posts confuse you, then please go back
and ask about the parts that are confusing. Right now, you seem to be
ignoring me, so I'm doubtful that repeating myself for a fourth time
would help the situation.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
C

Chris Smith

Java said:
Apologies. I finally realized what I was missing about the problem. I
haven't been ignoring you, I've actually been trying to understand the
problem. Now I think I do, and here is how I would handle it (using the
original code):
Okay,

// Why not override this as well and bury the non-thrown exception in
// the first place?

Yes, that would be nice. Hasn't it already been mentioned in this
thread? Nevertheless, as you recognize, it's just moving the problem.
public void myMethod() {
try { super.myMethod(); } catch (MyException ignore) {}
}

Here, then, is where you solve the problem, and you do it by catching
and ignoring the exception? This is pretty universally accepted as a
really bad idea. Essentially, when things are so out of control that
your basic assumptions are being violated, you choose to ignore it and
continue as if nothing happened?

What if myMethod was supposed to calculate the newest data for a
critical file and store it in fields? Wouldn't it be far better to fail
obviously and let someone know that there's a problem, rather than
continue without any notification or error reporting, and end up
overwriting all of their data with zeros?

The point is that people do make mistakes. But far more importantly, as
the code changes with maintenance in the future, assumptions that were
true become false. If you fail obviously, then you are to some extent
protected from that. Not that it's always justified to go out of your
way to check every possible assumption about program state; but in this
case you are forced to check your assumption anyway. The only
difference is whether you type one line of code to report the failure,
or find out about it and then intentionally avoid telling anyone.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
J

Java Architect

Chris Smith said:
Yes, that would be nice. Hasn't it already been mentioned in this
thread? Nevertheless, as you recognize, it's just moving the problem.


Here, then, is where you solve the problem, and you do it by catching
and ignoring the exception? This is pretty universally accepted as a
really bad idea. Essentially, when things are so out of control that
your basic assumptions are being violated, you choose to ignore it and
continue as if nothing happened?
[SNIP]

Dude, what's your prob? You snipped my comments that say I don't like the
idea of ignoring the exception, and then try to blast me for it? The point
is, as has been pointed out, the exception is NEVER thrown because the
subclass doesn't throw it. There is an overriden 'other' method that CANNOT
throw the exception because it is not declared.

I will restate the comment that, if you think there is the possibility that
MyException will be thrown, you cannot ignore it, and converting it to a
runtime exception is just as bad. The solution in that case would be to
create a checked exception class to throw and convert the MyException to
that so that the underlying implementation is hidden from the caller, but
the fact that an exception is thrown is not.

Converting to a runtime exception is just as bad an idea here as ignoring
the exception.

Now, if you want to dispute my solution, do it with my entire argument, not
a heinously distorted version. I understand that you try to make a name for
yourself here and generate some consulting fees, but that's no reason to try
to defend a mistake by misquoting someone who's only interest is providing
some help to the original poster. Congratulations, you've made my ignore
list.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top