Reputation: 1878
Using this class:
public class Fallible<T> {
private final Exception exception;
private final T value;
public Fallible(final T value) {
this.value = value;
this.exception = null;
}
public Fallible(final Exception exception) {
this.value = null;
this.exception = exception;
}
}
Can I safely assume value
will never contain an Exception object?
Upvotes: 2
Views: 451
Reputation: 140328
No, you can't make such an assumption. For example:
Object obj = new Exception();
Fallible f = new Fallible(obj);
would invoke the generic constructor.
The only way to check this would be to check the type of value
explicitly using instanceof
:
public Fallible(final T value) {
if (value instanceof Exception) {
this.exception = (Exception) value;
this.value = null;
} else {
this.value = value;
this.exception = null;
}
}
Upvotes: 3
Reputation: 234715
No you can't.
This is easier to analyse if you consider the type-erased version that the runtime gets:
public Fallible(final T value)
becomes public Fallible(final java.lang.Object value)
.
So the overload Fallible(final Exception exception)
will be used if it's a better match; i.e. if exception
is of type Exception
or a child class of it.
Building a class that permits construction from a java.lang.Object
but forbids construction (at compile-time) from a child class is not possible in Java. You'll have to rely on runtime checks (instanceof
&c.). You can, by the way, solve this in C++ using templates. In this, and many other respects, Java when considered as an evolution of C++ is a case of one step forward and two steps back.
Upvotes: 2