【问题标题】:Compare two generic types in Java?比较 Java 中的两种泛型类型?
【发布时间】:2016-01-23 01:14:21
【问题描述】:

我有以下方法:

public <U, V> boolean isEqual(List<U> a, List<V> b) {
    // check if U == V
}

我想检查UV 是否是同一个类。

【问题讨论】:

  • 你为什么要这个?你的用例是什么?为什么不创建另一个具有单一类型U 的方法?如果U? extends Something 呢? U == V 是什么意思?
  • 我正在创建一个方法来测试两个对象的相等性。第一个条件应该是它们的类型相同
  • 我不明白这样做的目的。您能否详细说明您想要实现的目标?
  • 我想创建方法来比较两个对象与泛型类型。如果两个泛型类型不同,我想告诉用户这条消息“你的泛型类型不一样”。那我会继续比较这两个方法的对象。
  • 我想给用户发送两种不同类型的灵活性,我想告诉他它们是不相等的。

标签: java generics


【解决方案1】:

because of type erasure你做不到,就这么简单。

考虑以下几点:

public static void main(String[] args) {
    List<? extends Number> l1 = Arrays.asList(1L, 2, 3L);
    List<? extends Number> l2 = Arrays.asList(1);
    isEqual(l1, l2);
}

public static <U, V> boolean isEqual(List<U> a, List<V> b) {
    // is U == V here?
}

U == V 在吗? l1 包含 LongInteger 实例,但 l2 包含单个 Integer 实例。


我从你的评论中猜测:

第一个条件应该是它们的类型相同

您应该拥有的是单一类型U。在这种情况下,请使用以下签名:

public static <U> boolean isEqual(List<U> a, List<U> b) {

}

这样,上面的代码就无法编译了。


您还可以添加 2 个接受类的参数:

public static <U, V> boolean isEqual(List<U> a, List<V> b, Class<U> uClass, Class<V> vClass) {
    if (!uClass.equals(vClass)) {
        // classes are different
    }
}

在这种情况下,如果给定的类不相同,您可以打印一条消息。

【讨论】:

  • 我想给用户发送两种不同类型的灵活性,我想告诉他它们是不相等的。
  • @MahmoudHanafy 不幸的是,这是您无法做到的。
  • @Mahmoud 与其让他们灵活地发送两种不同的类型,你说这是你想通知他们的错误,为什么不干脆不让他们首先发送不同的类型呢?
【解决方案2】:

如果您正在创建自己的类,您可以要求将Class&lt;T&gt; 包含在构造函数中,如here 所示

例如:

public class SomeClass<T> {

    private final Class<T> clazz;

    public SomeClass(Class<T> clazz) {
        this.clazz = clazz;
    }

    public Class<T> getParam() {
        return clazz;
    }
}

现在您可以调用SomeClass#getParam() 来获取声明的类型参数。


还有a way to do this with reflection.


说了这么多,你必须为此做一些奇怪的变通办法是因为Type Erasure。基本上在运行时 Java 将所有泛型视为Object,因此在编译您的List 时可能是List&lt;Integer&gt;List&lt;Boolean&gt;,但在运行时它们都是List&lt;Object&gt;

【讨论】:

    【解决方案3】:

    如果您尝试比较两个列表的内容,那么您不应该自己实现类型比较。相反,您应该这样做:

        public static <U, V> boolean isEqual(List<U> a, List<V> b) {
            if (a.size() != b.size()) 
                return false;
            for (int i = 0; i < a.size(); i++)
                if (!a.get(i).equals(b.get(i)))
                    return false;
            return true;
        }
    

    这样你就可以依赖 U 和 V 类型来正确处理 equals() 了。以下是实现 equals() 的一些指导原则:http://www.javaworld.com/article/2072762/java-app-dev/object-equality.html

    我猜你想要做的是能够在类型不同的情况下快速返回。但是通过我给你的实现,你会得到相同的行为——你会在第一次迭代时返回。

    【讨论】:

      【解决方案4】:

      不要依赖

      a.getClass().equals(b.getClass())
      

      这是不正确的,它只会检查两者是否都是ArrayList类型而不是String,Integer等。

      只试试这个

      a.get(0).getClass().equals(b.get(0).getClass())
      

      一定要检查 null 条件,否则会在这里遇到 NullPointerException。

      【讨论】:

      • 这是比较两个列表的第一个元素的运行时类型,而不是列表本身的类型参数。
      【解决方案5】:

      我想您想检查是否 a == b 而不是 U == V。在这种情况下,您必须编写自己的 compare 方法来比较类 U 和 V 的实例。

      【讨论】:

        【解决方案6】:

        假设a和b不为null也不为空,

        a.get(0).getClass().equals(b.get(0).getClass())
        

        应该可以解决问题。

        【讨论】:

        • 这与this answer有何不同?
        • 这是比较列表的第一个元素的运行时类型,而不是列表的参数。如果一个包含Integer,另一个包含Double,则两个List&lt;Number&gt;s 将不相等。此外,如果 List&lt;Number&gt;List&lt;Double&gt; 首先都包含 Double,则它们将相等。
        猜你喜欢
        • 2018-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-27
        相关资源
        最近更新 更多