Java 泛型参数绑定到任何类型的范围

Java generics parameter bounding to any of a range of types

是否有将泛型类型参数限制为一系列类型的语法或解决方法?

我知道您可以将一个类型限制为一系列类型的所有类型(即 AND 逻辑):

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

是否有 OR 逻辑版本,例如:

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

如果没有支持此的语法(我认为没有),是否有一种解决方法或方法是一种好的模式?

在某些情况下,一个示例用例可能是:

1
2
3
4
5
6
/** @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;
}

人们似乎对我上面的方法示例的确切语义感到困惑。让我们试试这个:

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

编辑:
我不会在编译时知道我可能会得到哪个(来自外部代码),所以我想避免每种类型都有具体的类。此外,我必须将我的课程交给调用我的 class.method 的外部系统,但另一个系统可以给我各种类的实例,但只是定义狭隘和已知的种类。

有些人评论说 instanceof 是"不纯的"。好吧,一种解决方法是使用工厂方法根据传入对象的类来选择我的具体类,但是该工厂方法必须使用 instanceof,所以你只是将 instanceof 移动到另一个地方- 你仍然需要 instanceof.

或者这个想法从来都不是一个好的想法?


1
public class MyWrapper<T extends A | B> {}

您不能对您无法控制的界面执行此操作,但对于您自己的东西,您可以使用空标记界面:

1
2
3
4
5
6
7
8
9
10
11
12
interface AOrB {
}

interface A extends AOrB {
    someMethodHere();
}

interface B extends AOrB {
    someOtherMethodHere();
}

public class MyClass<T extends AOrB> {}

不管纯粹主义者怎么说,在你需要的时候使用 instanceof 是完全可以的。


没有。除非所有类型都具有非空联合类型,否则它没有任何意义,例如他们都实现的接口,或者他们都扩展的基类,在这种情况下,您只需指定联合类型。


虽然Java 对T1 & T2 等"交集类型"的支持有限,但对"联合类型"的支持却很少。

带有通配符的泛型类型实际上是联合类型:G<? extends X> 是所有 G<S> 的联合,其中 SX 的子类型。

不支持任意两种类型的联合。

Java 7 的多捕获语法看起来支持任意异常类型的联合

1
catch (IOException|SQLException ex){ .. }

但不是真的,ex 的类型是一个固定的超类,而不是两个类的联合。


使用 instanceof 被认为不是很好的编程风格,并且允许您在泛型中使用 OR 意味着您将使用一个。


以下代码将与提供的示例执行相同的操作,但没有运行时类型检查和类型转换。

1
2
3
4
5
6
public boolean sameAs(MyClass obj) {
    return this.id.equals(obj.id);
}
public boolean sameAs(String obj) {
    return this.id.equals(obj);
}

NPE 检查可能是个好主意。