Reputation: 187379
I'd like to define a generic type, whose actual type parameter can only be
Long
, Integer
, Float
, Double
)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
Upvotes: 8
Views: 6987
Reputation: 565
Maybe you could do what follows:
MyClass<T>
a package-default class, invisible to other components, or at least with a package-default ctors only, so that it cannot extended or instantiated outside the package.MyClass<T>
:MyNumericClass<T extends Number> extends MyClass<T> MyStringClass extends MyClass<String>
This way all subclasses of MyClass will be limited to those parametrized with a Number subclass or String.
Upvotes: 0
Reputation: 384
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.
Upvotes: 4
Reputation: 269797
While generics won't work here, a base type with derived types for Number
and String
will. Since a generic type would have erased to Object
anyway, any functionality you would have put there can go in an abstract base class. You're likely to need only a type-specific accessor on the subclass to get the value.
Also, be careful with the Number
class. It's not limited to boxing the primitive types, as anyone can extend it—e.g., BigInteger
.
Upvotes: 2
Reputation: 44667
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)
Upvotes: 11
Reputation: 165282
Interesting question, it boggled me a bit. However apparently this is impossible. I tried several different hacks, none really work.
Upvotes: 0