【问题标题】:Java generics parameter bounding to any of a range of typesJava 泛型参数绑定到任何类型的范围
【发布时间】:2011-07-06 07:17:01
【问题描述】:

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

我知道您可以将一个类型限制为 all 的一系列类型(即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 的外部系统,但另一个系统可以为我提供各种类的实例,但定义狭隘且已知种类。

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

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

【问题讨论】:

  • 提供两个重载的sameAs实现不是更好吗?
  • OR 语法没有意义。当您指定一个通用约束时,它是一个合同,它不能是任何一个或类型。在您的示例中,如果您要使用 instanceofobj 也可能不是通用的;就让它Object obj

标签: java generics polymorphism


【解决方案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 完全没问题。

【讨论】:

  • 查看问题:这两个类是不相关的,不是我的,而且通常是最终的(JDK)。
  • re instanceof: 我同意——工厂方法一直需要这个
【解决方案2】:

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

【讨论】:

  • 经过一番思考(2 个月 :))我同意 - 这没有任何意义。如果您不能同质处理类型,请不要尝试合并类型。
【解决方案3】:

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

【讨论】:

  • 实际上并不暗示它。例如,考虑一个通用静态辅助函数,它调用两个具有不同参数类型的同名具体函数之一。
【解决方案4】:

虽然 Java 对“intersection types”(如 T1 &amp; T2)的支持有限,但对“联合类型”的支持却很少。

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

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

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

catch (IOException|SQLException ex){ .. }

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

【讨论】:

    【解决方案5】:

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

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

    NPE 检查可能是个好主意。

    【讨论】:

    • 顺便说一句,instanceof 不需要 NPE :) - 返回 false
    • @Bohemian 确实,但这只是 instanceof 的副作用,而不是其主要目的。
    猜你喜欢
    • 1970-01-01
    • 2018-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多