Take the 2-minute tour ×

Is there a syntax or workaround to constrain a generic type parameter to any of a range of types?

I am aware that you can constrain a type to be all of a range of types (ie AND logic):

public class MyClass<T extends Comparable<T> & Serializable> { } // legal syntax

Is there an OR logic version, ie something like this:

public class MyClass<T extends Comparable<T> | Serializable> { } // illegal syntax

If there isn't a syntax that supports this (I don't think there is), is there a workaround or approach that is a good pattern?

For some context, one example use case might be:

/** @return true if the obj is either has the same id, or if obj is the same as id */
public <T extends MyClass | String> boolean sameAs(T obj) {
    if (obj instanceof String) return this.id.equals(obj);
    if (obj instanceof MyClass) return this.id.equals(((MyClass)obj).id);
    return false;

People seem to be getting hung up on the exact semantic of my method example above. Let's try this instead:

public class MyWrapper<T extends A | B> {
    // my class can wrap A or B (unrelated classes). Yes I will probably use instanceof

I won't know at compile time which I might get (coming from external code), so I want to avoid having concrete classes for each type. Also, I have to give my class to a foreign system who invokes my class.method, but the other system can give me instances of a variety of classes, but a narrowly defined and known variety.

Some people have commented on instanceof being "impure". Well, one workaround is to use a factory method to pick my concrete class based on the class of the incoming object, but that factory method would have to use instanceof, so you're just moving the instanceof to another place - you still need the instanceof.

Or is this idea just not ever a good one?

share|improve this question
Would it not be better to provide two overloaded sameAs implementations? –  01es Jul 6 '11 at 7:24
The OR syntax does not make sense. When you specify a generic constraint, it's a contract and it cannot be either or type. In your example, obj might as well not be generic if you are going to use instanceof; just make it Object obj. –  Bala R Jul 6 '11 at 7:29
add comment

5 Answers

up vote 3 down vote accepted

No. It wouldn't make any sense unless all the types had a non-empty union type, e.g. an interface they all implemented, or a base class they all extended, in which case you just specify the union type.

share|improve this answer
After some thought (2 months :)) I agree - it doesn't make sense. If you can't deal with the types homogeneously, don't try to merge the types. –  Bohemian Sep 13 '11 at 21:38
add comment
public class MyWrapper<T extends A | B> {}

You can't do this for interfaces that you don't have control over, but for your own stuff you could use an empty marker interface:

interface AOrB {

interface A extends AOrB {

interface B extends AOrB {

public class MyClass<T extends AOrB> {}

Regardless of what purists say, using instanceof is perfectly fine when you need it.

share|improve this answer
See question: The two classes are unrelated, not mine, and often final (JDK). –  Bohemian Jul 6 '11 at 9:11
re instanceof: i agree - factory methods need this all the time –  Bohemian Jul 6 '11 at 9:12
add comment

Using of instanceof is considered as not very good style of programming, and allowing you to use OR in generics implies you will use one.

share|improve this answer
add comment

The following code would do the same thing as in the provided example, but without runtime type checking and typecasts.

public boolean sameAs(MyClass obj) {
    return this.id.equals(obj.id);
public boolean sameAs(String obj) {
    return this.id.equals(obj);

NPE checking might be a good idea.

share|improve this answer
btw, NPE not required for instanceof :) - returns false –  Bohemian Jul 6 '11 at 8:01
@Bohemian Indeed, however this is rather a side effect of instanceof than its primary purpose. –  01es Jul 6 '11 at 8:07
add comment

While Java has limited support for "intersection types" like T1 & T2, support for "union types" is scanty.

Generic types with wildcard are actually union types: G<? extends X> is the union of all G<S> where S is a subtype of X.

No support for union of arbitrary two types.

Java 7's multi-catch syntax looks like it supports union of arbitrary exception types

catch (IOException|SQLException ex){ .. }

but not really, the type of ex is a fixed super class, not a union of the two classes.

share|improve this answer
add comment

Your Answer


