Java 泛型参数绑定到一系列类型中的任何一种

2022-09-03 07:00:54

是否有语法或解决方法将泛型类型参数限制为类型范围中的任何一个?

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

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

有没有一个逻辑版本,即像这样:OR

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

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

对于某些上下文,一个示例用例可能是:

/** @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;
}

人们似乎被上面的方法示例的确切语义所困扰。让我们试试这个:

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

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

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

还是这个想法从来都不是一个好主意?


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

对于您无法控制的接口,您无法执行此操作,但对于您自己的内容,您可以使用空标记接口:

interface AOrB {
}

interface A extends AOrB {
    someMethodHere();
}

interface B extends AOrB {
    someOtherMethodHere();
}

public class MyClass<T extends AOrB> {}

无论纯粹主义者说什么,当你需要它时,使用是完全可以的。instanceof


答案 2

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


推荐