简体   繁体   中英

Is there any way to don't use 'instance of' with objects that I can't extend?

I've a custom exception with few attributes that inherits from Exception class.

Depending on instance of Exception I would like to return a code. Code:

public int manageException(Exception exception) {               
    int code = 0;               

    if (exception instanceof MyCustomException) {       
        code = ((MyCustomException) exception).getCode();       
    } else if (exception instanceof NestedRuntimeException) {       
        code = 444;         
    } else if (exception instanceof HibernateException) {       
        code = 555;         
    } else {        
        code = 666;
    }       

    return code;
}

You can use overloading like this:

public int manageException(MyCustomException e) {
    return e.getCode();
}

public int manageException(NestedRuntimeException e) {
    return 444;
}

public int manageException(HibernateExceptionexception e) {
    return 555;
}

public int manageException(Exception e) {
    return 666;
}

Edit after comment from @TJ Crowder:

Keep in mind that you will still need multiple catch blocks in order to call the correct method. The overload is based on the compile-time type of the exception. Simply doing catch (Exception e) { int code = this.manageException(ex); } catch (Exception e) { int code = this.manageException(ex); } will always return 666 .

If

  • You need to handle these exceptions in multiple locations, and

  • You don't want multiple catch blocks (one for each exception type) in each location

...then instanceof is about as clean as you're likely to get in Java 7.

Having said that, though, you could do this:

public void manageException(Runnable r) {
    try {
        r.run();
    }
    catch (NestedRuntimeException nre) {
        throw new MyCustomException(444, nre);
    }
    catch (HibernateException he) {
        throw new MyCustomException(555, he);
    }
    catch (Exception e) {
        throw new MyCustomException(666, e);
    }
}

...and then everywhere you need it:

try {
    this.manageException(new Runnable() {
        @Override
        public void run() {
            // Do something
        }
    });
}
catch (MyCustomException mce) {
    int code = mce.getCode();
}

...but it's not buying you much and it's really ugly. :-)

In Java 8, it's a lot cleaner. manageException is the same, but the calls are just:

try {
    this.manageException(() => {
        // Do something here
    });
}
catch (MyCustomException mce) {
    int code = mce.getCode();
}

For me, the Java 8 version nearly starts winning over instanceof . The Java 7 version, not so much.

(Why Runnable in the above? Because the JDK authors decided not to define a new standard functional interface that accepts no arguments and has no return value; more in this question . They generalized the concept of Runnable instead. If the semantics bother you (they would me), you can define your own.)

If you want to map the type of exception to different error codes, you could use a map:

Map<Class<? extends Exception>, Integer> map = new HashMap<> ();
map.put (Exception.class, 5);
map.put (NullPointerException.class, 42);

try {
  throw null; //throws NPE
} catch (Exception e) {
  System.out.println (map.get (e.getClass ())); //output is 42
}

I think this would be easy expendable, as you could read the mapping from a config file instead of hard coding it, so you could add other exception and error codes without making changes to your code.

You have to test the return value of map.get() for null, as it could be an Exception you didn't specify before so there is no Integer mapped to it.

Attention: As mentioned in the first comment, this would only work if you want to have an exact mapping of Classes to error codes. If Subclasses of an exception should have the same error code as their super class, this solution won't work without modification.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM