Java 泛型 : how to declare a generic parameter as the base type of another generic parameter?

标签 java generics types type-inference

public class PairJ<T> {
    private T first;
    private T second;

    public PairJ(T first, T second) {
        this.first = first;
        this.second = second;
    }

    public T first() {
        return this.first;
    }

    public T second() {
        return this.second;
    }

    public <R> Pair<R> replaceFirst(R newFirst) {
        return new Pair(newFirst, second());
    }
}

class Vehicle {}

class Car extends Vehicle {}

class Tank extends Vehicle {}

代码可以编译。 但是当我这样做时:

    PairJ<Car> twoCars = new PairJ(new Car(), new Car());
    Tank actuallyACar = twoCars.replaceFirst(new Tank()).second();

它仍然可以编译,但在运行时会给出强制转换异常,因为该对中的第二个元素是汽车,而不是坦克。

所以我把它改成这样:

public <R, T extends R> Pair<R> replaceFirst(R newFirst) {
    return new Pair(newFirst, second());
}

但是这段代码仍然可以编译并给出相同的异常:

    PairJ<Car> twoCars = new PairJ(new Car(), new Car());
    Tank actuallyACar = twoCars.replaceFirst(new Tank()).second();

似乎 T extends R 的声明在这里不起作用。

如何在这里强制执行类型安全?

更具体地说,我如何确保 java 推断

twoCars.replaceFirst(new Tank())

返回一对车辆而不是一对坦克?因此,当我尝试将其第二个元素分配给 Tank 类型的变量时,会出现编译时错误?并减少出现运行时异常的机会?

编辑:

在 Scala 中,我们可以这样做:

class Pair[T](val first: T, val second: T) {
  def replaceFirst[R >: T](newFirst: R): Pair[R] = new Pair[R](newFirst, second)
}

[R >: T] 确保 R 是 T 的基类型,我们如何在 Java 中做同样的事情?

最佳答案

how can I make sure that java infers

twoCars.replaceFirst(new Tank())

to return a Pair of Vehicle instead of a Pair of tanks?

显式提供类型参数

twoCars.<Vehicle>replaceFirst(new Tank())

尝试调用时会出现编译器错误

Tank actuallyACar = twoCars.<Vehicle>replaceFirst(new Tank()).second();

关于Java 泛型 : how to declare a generic parameter as the base type of another generic parameter?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24338511/

相关文章:

java - 将文件解密到列表中时被分割的行

c# - 我无法读取 foreach 循环中的 IEnumerable 项目

android - 在 Kotlin 中使用星投影作为父类(super class)型

c# - 通用类 : conditional method based on type

c# - 根据给定的字符串输入确定类型

c++ - 比 double 更精确的 float 据类型?

c - 从文件中读取短值并将它们存储到 int 缓冲区中

java - 操作栏 : Center text on navigation bar buttons

java - Android JNI 中的 native 崩溃 SIGSEGV

java - 如何在 Java 中决定 wait() 的循环条件