2

I have two classes inheriting from java.lang.Exception. They both have a method with the same signature void a(){...}. They both can be thrown in a code block. If I do:

catch (SubException1 | SubException2 e)
    {
        e.a();
    }

Then it won't compile because method a() does not belong to Exception. Is it a Java language flaw? How should I design my code properly to prevent code redundancy?

Mureinik
  • 297,002
  • 52
  • 306
  • 350
pHneutre
  • 1,091
  • 3
  • 12
  • 29
  • The signature does not matter, is it the same method of some common superclass? Is `a` defined in some common superclass of `SubException1` and `SubException2`? – luk2302 Jun 01 '17 at 17:04
  • 1
    You can eliminate redundancy by giving them a common ancestor that has prescribed method `void a()`. Then you can catch the ancestor and call `e.a()` – Ishnark Jun 01 '17 at 17:05
  • When using multicatch, actual type of exception local variable is the closest common supertype, which it looks like it is `Exception` in your case. So it doesn't really matter that `SubException1` has `a()`. You can solve this by having a common supertype with `a()` on both methods, as already was suggested. – M. Prokhorov Jun 01 '17 at 17:08

2 Answers2

3

When you catch multiple exception types in a single catch statement the inferred type of the caught exception is the greatest common denominator of those classes. In your case, the greatest common denominator is Exception, which doesn't have the method void a(). In order to make it accessible to the catch block you could either extract it to a common base class, or (arguably) more elegantly, define it in an interface that both classes implement:

public interface SomeExceptionInterface {
    void a();
}

public class SomeException extends Exception implements SomeExceptionInterface {
    // Implementation...
}

public class SomeException2 extends Exception implements SomeExceptionInterface {
    // Implementation...
}
Mureinik
  • 297,002
  • 52
  • 306
  • 350
2

If you need to access a method called a(), you need a type that provides that method. A simple solution could be:

public class AbstractSubException extends Exception {
    public abstract void a();
}

public class SubException1 extends AbstractSubException {
    @Override public void a() { ... }
}

public class SubException2 extends AbstractSubException {
    @Override public void a() { ... }
}

Then you can catch the way you did or (somewhat simpler):

catch (AbstractSubException e) {
    e.a();
}

Maybe the code for the method a is the same in all sub classes. Then you can make it concrete and put the code into the parent class.

Seelenvirtuose
  • 20,273
  • 6
  • 37
  • 66