5
public class try
{
    public static void main(String[] args)
    {
        try
        {
            if(true)
                throw new A();
            if(true)
                throw new B();
        }
        catch( A | B e)
        {
            e.doit();
        }
    }
}

class A extends Exception
{
    public void doit() {}
}

class B extends Exception
{
    public void doit() {}
}

This doesn't compile

18: error: cannot find symbol
        e.doit();
         ^
symbol:   method doit()
location: variable e of type Exception

The variable e seems to end up as type Exception rather than the actual type - this seems logical because at compile type the compiler doesn't know what kind is going to be thrown. However, is there a way to make this work without making A & B both derive from some common base class or implement a common interface?

user93353
  • 13,733
  • 8
  • 60
  • 122
  • 2
    `Exception` is the only type it can be, as this is the only type `A` and `B` have in common. If creating an intermediate class is not an option, why not just use separate catch blocks? – PeterK Oct 17 '14 at 09:29
  • sorry to interrupt. What is that or symbol doing in the catch block? What is it called? Haven't done java for couple of years so bit behind. – Oliver Watkins Oct 17 '14 at 10:07
  • 1
    @OliverWatkins - http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html#multiple - this is Java 7 feature. – user93353 Oct 17 '14 at 14:32

3 Answers3

4

Well no, because Java doesn't support duck typing.

Doing an instanceof and casting e to either A or B is obviously going to work, but what you probably want to do in this case is doing it in the traditional way of writing two catch blocks.

I mean, it makes sense, right? Multi-catch is appropriate in the case where you want to treat different kinds of exceptions equally. In this case, the behaviour can be drastically different (even if the methods are named the same).

Jan Van den bosch
  • 3,542
  • 3
  • 26
  • 38
1

You should just create a super class that both A and B extend, give that class an doIt() method, and then implement that method for both A and B, like this:

  class A extends C {
    public void doit() {
    }
  }

  class B extends C {
    public void doit() {
    }
  }

  abstract class C extends Exception {
    public abstract void doit();
  }

You can then catch C, like this:

try
{
  if(true)
    throw new A();
  if(true)
    throw new B();
}
catch( C e)
{
  e.doit();
}
PeterK
  • 1,697
  • 10
  • 20
1

If not using interface, can I use instanceof instead. A little tedious. BTW, why you don't write two catch block to catch the two exceptions separately.

public class Try
{
    public static void main(String[] args)
    {
        try
        {
            if(true)
                throw new A();
            if(true)
                throw new B();
        }
        catch(A | B e)
        {
            if(e instanceof A){
                ((A) e).doit();             
            }else if (e instanceof B){
                ((B) e).doit();             
            }
        }
    }
}

class A extends Exception 
{
    public void doit() {}
}

class B extends Exception 
{
    public void doit() {}
}

Another way is using reflect.

package com.stackoverflow;

import java.lang.reflect.Method;

public class Try
{
    public static void main(String[] args) throws Exception
    {
        try
        {
            if(true)
                throw new A();
            if(true)
                throw new B();
        }
        catch(A | B e)
        {
            Class cls = e.getClass();  
            Method doit = cls.getMethod("doit");
            doit.invoke(e, null);
        }
    }
}

class A extends Exception
{
    public void doit() {}
}

class B extends Exception
{
    public void doit() {}
}

The interface may help.

paco alcacer
  • 381
  • 2
  • 13
  • Updated my question - I had already said "without making both of them derive from some common base class" - added implementing a common interface to that line. – user93353 Oct 17 '14 at 09:29
  • @user93353 I don't suggest you using the Java reflection. But I think it works here. – paco alcacer Oct 17 '14 at 09:55