【问题标题】:Restrict generic upcasting [duplicate]限制通用向上转换[重复]
【发布时间】:2020-07-26 03:48:25
【问题描述】:

假设我有两个参数的泛型方法。

<T> void compare(T a, T b) {}

事实证明,可以传递任何类型的参数:T 可能总是被解析为Object,因为任何其他类型都是一个Object

有没有办法让接受完全相同参数的方法与任何类型都一样?

【问题讨论】:

  • 这里说的是同一个编译时类型还是同一个运行时类型?
  • 考虑以下:Object a = new Object(), b = new Object(); inst.compare(a, b); 这样可以吗?
  • 如果需要检查它们是否具有相同的运行时类型:a.getClass() == b.getClass().
  • 编译时间 - 我希望 compare("foo", 42) 编译时出错

标签: java generics


【解决方案1】:

一模一样在同一个班?不会。如果 A 和 B 共享一个父类 P,您将始终能够将它们都传递给期望 P 的泛型方法。

我认为限制它的唯一方法是添加这样的参数:

<T> void compare(T a, T b, Class<T> clazz) {}

这将起作用,因为 Java 泛型是不变的,这意味着如果 A extends BG&lt;A&gt;G&lt;B&gt; 是完全不相交的类型(一个不扩展另一个)。例如,List&lt;Person&gt;List&lt;Student&gt; 是不兼容的类型,即使 Student extends Person。这不直观,只是语言的限制,其他一些语言,如 Scala 可以选择创建泛型类型:

  • 不变(就像 Java)
  • 协变(如果A extends B 那么G&lt;A&gt; extends G&lt;B&gt;
  • 逆变(如果A extends B 那么G&lt;B&gt; extends G&lt;A&gt;

【讨论】:

    【解决方案2】:

    好的,让我们深入了解您的要求:
    你有方法

    <T> void compare(T a, T b) {}
    

    并且你想确保它只被相同的类型调用。

    好的,让我们使用两个对象:

    Object a = new Object();
    Object b = new Object();
    compare(a, b);
    

    在这里,我将两个对象传递给您的方法。当然任何东西都是对象,所以这个小改动也是有效的:

    Object a = "Also an Object";
    Object b = 42; // Boxing conversion
    compare(a, b);
    

    如果你想接受任何类型,你还必须接受Objects。任何东西都可以是对象。

    所以,你的要求在编译时是不可能满足的。


    但是运行时呢?

    这实际上是可行且非常容易的:

    <T> void compare(T a, T b) {
        if (a.getClass() != b.getClass()) throw new IllegalArgumentException("not the same type");
    }
    

    【讨论】:

    • 是的,好点。我在这里真正想要的是限制"Also an Object"42 向上转换为Object。这可能与 OOP 概念背道而驰……
    【解决方案3】:

    据我所知,没有办法强制所有类型的参数都属于同一类型(see other Stack Overflow question)

    但是,您可以在调用方法时指定类型参数,尽管显然这需要您知道在给定情况下要使用的类型,例如

    <Integer>compare(10, 22);
    

    【讨论】:

    • 您应该将此问题标记为重复。但是找到它做得很好。
    • 谢谢,我实际上并不知道我有权标记重复的问题。我现在已经这样做了。
    猜你喜欢
    • 2014-07-29
    • 2019-07-30
    • 2010-10-18
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-05
    相关资源
    最近更新 更多