java - Oracle Java 泛型教程

标签 java generics

<分区>

我正在学习 Oracle Java 教程。我目前正在学习泛型,我对类(class)末尾的问题 8 感到困惑,下面提供了解决方案。 具体来说,我不明白 T 背后的基本原理扩展 ObjectComparable<? super T> . T还不够吗?简单地扩展 Comparable<? super T> ,有什么优势T扩展Object还有吗?

问题:

编写一个通用方法来查找列表范围 [begin, end) 中的最大元素。

回答:

import java.util.*;

public final class Algorithm {
    public static <T extends Object & Comparable<? super T>>
        T max(List<? extends T> list, int begin, int end) {

        T maxElem = list.get(begin);

        for (++begin; begin < end; ++begin)
            if (maxElem.compareTo(list.get(begin)) < 0)
                maxElem = list.get(begin);
        return maxElem;
    }
}

最佳答案

我能找到拥有 <T extends Object & Comparable<? super T> 的唯一原因,而不是 T extends Comparable<? super T> , 是为了在生成方法时向后兼容。

根据 Angelika Langer 的 Java Generics FAQ :

Occasionally, one must pay attention to the fact that a generification might change the signature of some methods in the byte code. Changing the signature will break existing code that cannot be recompiled and relies on the binary compatibility of the old and new version of the .class file.

在这种情况下,Java 自己的 Collections.max用于返回 Object 1.5之前,泛型的到来。泛型化时,可以在没有 extends Object 的情况下声明此方法,它会在隔离状态下正常工作。

public static <T extends Comparable<? super T>> T max(Collection <? extends T> coll)

但是,出于字节码目的,删除此方法会使此方法返回 Comparable , 而不是 Object ,这是向后不兼容。

要解决此问题,extends Object被作为第一个边界插入,因此此方法的返回类型的删除将保留 Object .

这解决了 1.5 中 Java 泛型的向后不兼容问题。

然而,教程中的问题指出:

Write a generic method to find the maximal element in the range [begin, end) of a list.

您正在编写自己的新方法,因此尚无向后兼容性需要维护。 extends Object在本教程问题的答案中是不必要的。

此外

在字节码(javap -c Algorithm.class)中,所有类型都经过类型删除,即使是局部变量maxElem。 .

  public static <T extends java.lang.Comparable<? super T>> T max(java.util.List<? extends T>, int, int);
Code:
   0: aload_0
   1: iload_1
   2: invokeinterface #2,  2            // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;

get方法返回了 Object .那么它是如何调用compareTo的呢?在 Comparable

   7: astore_3
   8: iinc          1, 1
  11: iload_1
  12: iload_2
  13: if_icmpge     49
  16: aload_3
  17: checkcast     #3                  // class java/lang/Comparable
  20: aload_0
  21: iload_1
  22: invokeinterface #2,  2            // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
  27: invokeinterface #4,  2            // InterfaceMethod java/lang/Comparable.compareTo:(Ljava/lang/Object;)I

编译器已将隐式转换插入到 Comparable这样 compareTo方法可以调用。它断言列表中的对象是 Comparable因为第二个上限,Comparable<? super T> .

  32: ifge          43
  35: aload_0
  36: iload_1
  37: invokeinterface #2,  2            // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
  42: astore_3
  43: iinc          1, 1
  46: goto          11
  49: aload_3
  50: areturn
}

关于java - Oracle Java 泛型教程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33089846/

相关文章:

java - 用于从 MySQL 数据库获取信息的 AsyncTask 与工作线程

java - 使用java swing加密html文件

Java 泛型 - 使用上限和下限通配符进行迭代

C# 如何在其类型为 List<T> 且我有一个 List<object> 时设置 PropertyInfo 值

generics - 避免在泛型方法中强制转换为Nothing

java - 首次未加载带有毕加索的 map 标记点图像

java - Websphere MQ 主题 - 它们是否严格排序?

java - 通用集合作为 Java 方法参数

java - Spring BeanUtils 无法实例化泛型类

c# - C# 中是否有 "anonymous"通用标记,如 Java 中的 '?'?