tags:

views:

1411

answers:

5

Hi,

I'd like to define a generic type, whose actual type parameter can only be

  1. One of the numeric primitive wrapper classes (Long, Integer, Float, Double)
  2. String

I can meet the first requirement with a definition like this

public final class MyClass<T extends Number> {
    // Implementation omitted
}

But I can't figure out how to meet both of them. I suspect this is not actually possible, because AFAIK there's no way to specify "or" semantics when defining a formal type parameter, though you can specify "and" semantics using a definition such as

public final class MyClass<T extends Runnable & Serializable > {
    // Implementation omitted
}

Cheers, Don

A: 

Interesting question, it boggled me a bit. However apparently this is impossible. I tried several different hacks, none really work.

Yuval A
+7  A: 

Java generics does not support union types (this parameter can be A OR B).

On a related note that may be of interest to some, it does support multiple bounds, if you want to enforce multiple restrictions. Here's an example from the JDK mentioned in the Java generics tutorial:

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
Dave L.
Markus
+2  A: 
erickson
A: 

It's called Multiple Inheritance and is not supported in Java (for several reasons).

Pål GD
+3  A: 

You could use factory methods for all supported types and make the constructor private/protected. You have to fix the generic type in the constructor anyway so that it makes sense, so you could probably code it like this:

public final class MyClass<T> {
    public static MyClass<Integer> newInstance(int i) {
        return new MyClass<Integer>(i);
    }
    public static MyClass<String> newInstance(String s) {
        return new MyClass<String>(s);
    }
    //More factory methods...

    protected MyClass(T obj) {
        //...
    }
}

Or if you do not want the constructor parameter, something like this: public final class MyClass { public static MyClass newIntegerInstance() { return new MyClass(); } //... }

As erickson stated, the common implementation can rely only on Object anyway, so the only restriction is, that you can create other implementations for other types besides the primitive and String.

Markus