cuihtlauac
cuihtlauac

Reputation: 1878

Dynamic dispatch, overloading and generics

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

Answers (2)

Andy Turner
Andy Turner

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

Bathsheba
Bathsheba

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

Related Questions