Function Overloading with Subclass Parameters in Java [duplicate] - java

This question already has answers here:
Overloaded method selection based on the parameter's real type
(7 answers)
Closed 3 years ago.
I have a class that extends another class (In this case, it's an Exception):
public class NewTypeException extends Exception {
private String exceptionField;
public String getExceptionField() {
return exceptionField;
}
public void setExceptionField(String exceptionField) {
this.exceptionField = exceptionField;
}
public NewTypeException(String cause, String reason) {
super(cause);
exceptionField = reason;
}
}
And another class (for sake of example, lets call this PrintUtil) that has two methods with similar signatures, the only difference being the Exception type changes to the subclass:
void doStuff(Exception ex) {
System.out.println(ex.getMessage());
}
void doStuff(NewTypeException ex) {
System.out.println("New Type Exception");
System.out.println(ex.getExceptionField());
System.out.println(ex.getMessage());
}
In a lot of places in my code, I have a bunch of
try {
// code
} catch (Exception ex) {
printUtil.doStuff(ex);
}
After adding this new exception type, I want to have this line call the most specific method it can, depending on the argument. However, it seems when I test this, this will only use the method for Exception even if the runtime type fits another method (e.g. NewTypeException). Is there any way to do this other than replace hundreds of sections of
try {
// code
} catch (Exception ex) {
printUtil.doStuff(ex);
}
with
try {
// code
} catch (NewTypeException ex) {
printUtil.doStuff(ex);
} catch (Exception ex) {
printUtil.doStuff(ex);
}
? This seems like something really basic a OOP language should be able to do...

Not possible the way you're doing it. Method calls check the parameters arguments at compile time taking into account the declared types.
You may move the exception handling code somewhere else, but either you would need to instanceof or catch specific exceptions:
try {
// code
} catch (Exception ex) {
printUtil.handleExceptions(ex);
}
With utility class:
class PrintUtil {
public static handleExceptions(Exception e) {
try {
throw e;
} catch (NewTypeException ex) {
doStuff(ex);
} catch (AnotherTypeException ex) {
doStuff(ex);
}
}
...
}

Related

Java re-throw Exception

I have a Project with two classes. One Object class and one GUI class.
I would like to throw my own declared Exception if an error occurs.
I have two methods:
public class getValueClass {
private List<Value> liste;
public List<Value> getValues() {
try {
liste = this.getVal();
} catch (ValueException ex) {
System.out.println("EXCEPTION!! " + ex.getMessage());
ex.printStackTrace();
}
return liste;
}
public List<Value> getVal() throws ValueException
{
liste = null;
try {
// initialize list
// do some stuff
//test exception
if(1 == 1)
{
throw new Exception();
}
} catch (Exception ex) {
throw new ValueException("QWE " + ex);
}
return liste;
}
}
Now the exception is thrown and I catch the exception in my getValues Method and print the Message/Stack
But I call the Method getValues in my GUI-Class and I want to catch the Exception there and print some Information in my dialog!
GUI:
public void myMethod()
{
try
{
l = cs.getValues();
}
catch(Exception ex)
{
System.out.println("TEST " + ex.getMessage());
}
}
But I don't get there because I already catch it in the getValues() method.
Is it possible to make it like this WITHOUT adding throws at method declaration for getValues() method? ( I get this method from an interface and will not change it)
You could throw an unchecked RuntimeException such as IllegalArgumentException or customized RuntimeException subclass.
public List<Value> getValues() {
try {
liste = this.getVal();
} catch (ValueException ex) {
throw new IllegalArgumentException(ex.getMessage(), ex);
}
return liste;
}
There is a way to do what you want, but I advise against it depending on your intended purpose of ValueException, as it could be the source of future bugs
You can have ValueException extend RuntimeException. The RuntimeException set of exceptions, as the name implies, are thrown at runtime and are not declared at compile time, and need to be explicitly caught. This way you wouldn't have to add a throws declaration to the getValues() method, but would still catch it in your main method.
Disclaimer explained:
The reason I am not a fan of this idea (and RuntimeExceptions in general) is because they're uncaught until explicitly looked for. This in my mind doesn't make for easy-to-use code, and while it has it's very handy uses, I don't feel right using them because of the uncertainty they carry
Again, this is my opinion, not Java's

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;
}
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.)
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 #T.J. 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); } will always return 666.
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.

DRY for Exception Wrapping

I'm working on some server-side code that wraps all exceptions before passing them to the client side, due to this all client facing methods have the following code
try{
DoSomething();
} catch (ExceptionA e) {
throw new CustomException(AType, e);
} catch (ExceptionB e) {
throw new CustomException(BType, e);
} catch (Exception e) {
throw new CustomException(Unexpected, e);
}
to have this repeated in every method seems to violate the DRY principle and I was wondering what the best way to refactor it would be. For instance I was thinking a wrapper method such as:
private void wrapException(Exception e) {
if (e instanceof ExceptionA) {
throw new CustomException(AType, e);
}
etc...
Take a look at AspectJ soften exception.
Also look at Guava's Throwables.
There is also Lamboks sneaky exception.
The other option is to use Anonymous object instances aka closures.
public abstract class Wrapper {
public void execute() {
try {
// do some boiler plate before
this.wrap();
// do some boiler plate after.
} catch (ExceptionA | ExceptionB ex) {
Type t = determineType(ex);
throw new CustomException(t, ex);
}
}
public void abstract wrap();
}
Now in your code you do something like:
new Wrapper() {
public void wrap() {
DoSomething();
}
}.execute()
This is possible in Java7 and up:
http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
Copy-paste example from above doc:
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}
This is one way to go about it:
Exception caughtEx = null;
String extraInfo = null;
try{
DoSomething();
} catch (ExceptionA e) {
caughtEx = e;
extraInfo = AType;
} catch (ExceptionB e) {
caughtEx = e;
extraInfo = BType;
} catch (Exception e) { // catching Exception is usually a bad idea, just let it bubble up without catching...
caughtEx = e;
extraInfo = Unexpected;
}
if (caughtEx != null) throw new CustomException(extraInfo, caughtEx);

Java Generic Method to Instantiate any Class with any Constructor using Reflection

As we know Java uses erasure, so any Generic class cannot do
T t = new T();
So I was trying out Java reflection to have a class with Static methods, to instantiate any Class with any Constructor. Here is the code.
import java.lang.reflect.*;
public class GenericNewInstance {
public static <T> T createInstance(Class<T> cObj) {
try {
return cObj.newInstance();
} catch (InstantiationException e) {
System.out.println("Instantiation Exception");
return null;
} catch (IllegalAccessException e) {
System.out.println("Illegal Access Exception");
return null;
}
}
public static <T> T createInstanceUsingRelection(Class<T> c, Object... initArgs) {
Constructor<T> cTor = null;
Class<?>[] cObjs = new Class<?>[initArgs.length];
int i = 0;
for(Object o : initArgs) {
cObjs[i++] = o.getClass();
}
try {
cTor = c.getConstructor(cObjs);
} catch (SecurityException e) {
System.out.println("security exception. Cannot get Constructor");
return null;
} catch (NoSuchMethodException e) {
System.out.println("NoSuchMethodException Cannot get constructor");
return null;
}
try {
return cTor.newInstance(initArgs);
} catch (IllegalArgumentException e) {
System.out.println("Illegal Argument Exception");
return null;
} catch (InstantiationException e) {
System.out.println("Instantiation Exception");
return null;
} catch (IllegalAccessException e) {
System.out.println("Illegal Access Exception");
return null;
} catch (InvocationTargetException e) {
System.out.println("Invocation Target Exception");
return null;
}
}
}
Example for using this.
Integer i = GenericNewInstance.createInstanceUsingRelection(Integer.class, "0");
So my questions:
Is this the right way to implement it? (or is it verbose?)
What are the typical use cases of doing this?
Can/Should we avoid using Reflection while using Generics?
Your code will fail at c.getConstructor(cObjs) since this doesn't take into account the type hierarchy. If any argument is a subtype of the constructor's declared param type, this call will not return it. You'll need quite a lot more type juggling to get it working. I advise you to take a look at the code that already solves this problem. Perhaps you can even use that library as-is, your choice. It's the implementation code for Clojure, a JVM-based dynamic language that needs exactly this stuff. The library is available from the Maven central repo.
BTW Your exception handling is redundant. Either just declare throws Exception or catch any Exception and wrap it in a RuntimeException. When something fails, the original exception is the best diagnostic.

exception.getMessage() output with class name

I'm trying to fix an issue, in my application I have this code
try {
object1.method1();
} catch(Exception ex) {
JOptionPane.showMessageDialog(nulll, "Error: "+ex.getMessage());
}
and the object1 would do something like that:
public void method1() {
//some code...
throw new RuntimeException("Cannot move file");
}
I get a messsage in my option pane like this:
Error: java.lang.RuntimeException: Cannot move file
but I used getMessage and not toString method, so the name of the class shouldn´t appear, right?
What I am doing wrong?
I already tryied with a lot of exceptions, even Exception itself. I'm looking to solve this no without the need to implement my own Exception subclass
PROBLEM SOLVED - thank you all!
The try and catch were actually being called in get() method from SwingWorker which constructs an ExecutionException with my exception thrown from doInBackground()
I fixed doing this:
#Override
protected void done() {
try {
Object u = (Object) get();
//do whatever u want
} catch(ExecutionException ex) {
JOptionPane.showMessageDialog(null, "Error: "+ex.getCause().getMessage());
} catch(Exception ex) {
JOptionPane.showMessageDialog(null, "Error: "+ex.getMessage());
}
}
I think you are wrapping your exception in another exception (which isn't in your code above). If you try out this code:
public static void main(String[] args) {
try {
throw new RuntimeException("Cannot move file");
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
}
}
...you will see a popup that says exactly what you want.
However, to solve your problem (the wrapped exception) you need get to the "root" exception with the "correct" message. To do this you need to create a own recursive method getRootCause:
public static void main(String[] args) {
try {
throw new Exception(new RuntimeException("Cannot move file"));
} catch (Exception ex) {
JOptionPane.showMessageDialog(null,
"Error: " + getRootCause(ex).getMessage());
}
}
public static Throwable getRootCause(Throwable throwable) {
if (throwable.getCause() != null)
return getRootCause(throwable.getCause());
return throwable;
}
Note: Unwrapping exceptions like this however, sort of breaks the abstractions. I encourage you to find out why the exception is wrapped and ask yourself if it makes sense.
My guess is that you've got something in method1 which wraps one exception in another, and uses the toString() of the nested exception as the message of the wrapper. I suggest you take a copy of your project, and remove as much as you can while keeping the problem, until you've got a short but complete program which demonstrates it - at which point either it'll be clear what's going on, or we'll be in a better position to help fix it.
Here's a short but complete program which demonstrates RuntimeException.getMessage() behaving correctly:
public class Test {
public static void main(String[] args) {
try {
failingMethod();
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
private static void failingMethod() {
throw new RuntimeException("Just the message");
}
}
Output:
Error: Just the message

Categories

Resources