Reputation: 448
I have a parent class for all of my custom exceptions, ParentException. I want all child exceptions to have a method that adds a message to the exception. To do this I created a generic method that returns an object of generic type after adding the message to it. I use this
in the parent class method to add the message then return this
but since the method returns the generic type I casted it to the generic type T. This seems to work, but gives a warning. My code is as follows:
public class ParentException extends RuntimeException{
private String message;
public ParentException() {
message = "";
}
public void addToMessage(String msg) {
message += msg;
}
public void printMessage() {
System.out.println(message);
}
public <T extends ParentException> T withMessage(String msg) {
this.addToMessage(msg);
return (T) this; // This line gives the warning
}
}
The warning given by that line is Unchecked cast from ParentException to T
. The method does seem to work as expected, so I'm not worried but I'd like a better understanding of why this gives a warning in the first place.
Will this cast always be safe? Otherwise what case would cause a runtime error?
Upvotes: 0
Views: 1952
Reputation: 33845
Consider this case:
class SubException extends ParentException {...}
ParentException ex = new ParentException();
SubException sub = ex.withMessage("blah");
The last line will throw a class cast exception, because ParentException
can not be cast to SubException
.
You could create a static helper method:
class ParentException extends RuntimeException{
...
protected static <T extends ParentException> T withMessage(T instance, String msg) {
instance.addToMessage(msg);
return instance;
}
public ParentException withMessage(String msg) {
return withMessage(this, msg);
}
}
And use covariant return types to override this method:
class SubException extends ParentException {
@Override
public SubException withMessage(String msg) {
return withMessage(this, msg);
}
}
Then, if you have a SubException
variable, the call to withMessage
will return a SubException
too.
Upvotes: 1
Reputation: 44308
The following code will compile, but will fail at runtime:
class ChildException extends ParentException { }
ParentException p = new ParentException();
ChildException c = p.withMessage("Connection failed");
I realize it wouldn’t make much sense to write that, but the point is that the compiler warning about an unsafe cast can prevent this landmine in the first place.
Upvotes: 1