【问题标题】:Bounded type parameter vs plain base class [closed]有界类型参数与普通基类 [关闭]
【发布时间】:2020-07-30 18:54:29
【问题描述】:

在编译时,javac erases 泛型有界类型并将其替换为上限。

例如编译器会转换

<T extends Base> void foo(T p) {}

void foo(Base p) {}

在这种特定情况下,我认为泛型绝对比其他选项更受欢迎。但我想知道具体的优势。

【问题讨论】:

  • 不等价。仅编译之后。但是编译期间,编译器可以使用实际的T 来确保类型安全,而不仅仅是Base。因此,仅仅因为泛型在运行时被删除,并不意味着它们没有用。编译器可以确保完全的泛型类型安全。因此,在系统已经被验证为正确和安全之后,保持泛型存活并没有多大意义(尽管这并不完全正确)。
  • @Zabuzard 很好的解释!所以问题是,我应该在更广泛的范围内看待它,因为好处确实存在于编译之前发生的事情。

标签: java generics type-erasure


【解决方案1】:

让我通过一个例子来正确解释有界类型的需要

假设您正在编写一个将被其他人使用的库或框架。假设在某个地方(在某个类方法中)您需要执行一些数字 加法、减法、乘法等。那么,您需要什么类型的数据呢?当然是 Neumeric 类型。因此,您所做的是创建了一个 Number 类。但是,有各种类型的数字,例如 Floating pointInteger 等。所以,您已经创建了 IntegerFloat 子类等。现在,您还创建了一个类 NumberUtil,它为用户提供了一些功能,例如查找平均值、查找数字频率等。当然,一句话: NumberUtil 很棒,每个人都想用它。现在,让我们谈谈您的 NumberUtil 类中的平均方法(让我们编写一些代码):

class NumberUtil<T extends Number> {
  T[] nums;
  public NumberUtil(T[] nums) {
    this.nums = nums;
  }
  public Double average() {
    Double sum = 0.0;
    for(int i=0; i<nums.length; i++) {
      sum = sum + nums[i].doubleValue(); // note, you've ensured T must be a number
      // so, T must able to convert it's value to double value
    }
    return sum / nums.length;
  }
}

现在,让我们假设,其他一些人正在使用您的库,特别是 NumberUtil(因为,它太棒了),但他们使用的是自己的名为 SomeNumberType 的类型.但是有可能,这个 SomeNumberType 没有子类 Number (或者,如果你声明了它,它没有实现 Number 接口数字作为接口)。因此,您不能保证 SomeNumberType 会提供 doubleValue() 方法。但是,通过编写 T extends Number,您可以确保在 编译时 SomeNumberType 必须是 Number 的子类 一切都会好起来的(至少,它具有 Number 类的特性,这意味着它还有一个 doubleValue() 方法)。

【讨论】:

    【解决方案2】:

    请参考this link here

    但简而言之,有两点需要注意:

    泛型方法是引入自己的类型参数的方法。这类似于声明泛型类型,但类型参数的范围仅限于声明它的方法。允许使用静态和非静态泛型方法,以及泛型类构造函数。

    —https://docs.oracle.com/javase/tutorial/java/generics/methods.html

    类型推断是 Java 编译器查看每个方法调用和相应声明以确定使调用适用的类型参数(或参数)的能力。推理算法确定参数的类型,如果可用,还确定分配或返回结果的类型。最后,推理算法尝试找到适用于所有参数的最具体的类型。

    —https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html

    【讨论】:

    • 对不起,先生。我是新手,正在学习如何在平台上发布答案。并感谢您重新安排答案,非常感谢先生。
    • 太棒了 =) 感谢您接受反馈
    猜你喜欢
    • 2015-08-30
    • 2016-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-18
    相关资源
    最近更新 更多