Java泛型:如何将泛型参数声明为另一个泛型参数的基类型?

Java泛型:如何将泛型参数声明为另一个泛型参数的基类型?,java,generics,types,type-inference,Java,Generics,Types,Type Inference,还一辆车而不是一辆坦克?所以,当我试图将第二个元素分配给Tank类型的变量时,会出现编译时错误?减少运行时异常的可能性 编辑: 在Scala中,我们可以这样做: twoCars.replaceFirst(new Tank()) [R>:T]确保R是T的基本类型,我们在Java中如何做到这一点 我如何确保java推断 PairJ<Car> twoCars = new PairJ(new Car(), new Car()); Tank actuallyACar = tw

还一辆车而不是一辆坦克?所以,当我试图将第二个元素分配给Tank类型的变量时,会出现编译时错误?减少运行时异常的可能性

编辑:

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

twoCars.replaceFirst(new Tank())
[R>:T]确保R是T的基本类型,我们在Java中如何做到这一点

我如何确保java推断

    PairJ<Car> twoCars = new PairJ(new Car(), new Car());
    Tank actuallyACar = twoCars.replaceFirst(new Tank()).second();
class Pair[T](val first: T, val second: T) {
  def replaceFirst[R >: T](newFirst: R): Pair[R] = new Pair[R](newFirst, second)
}
还一辆车而不是一辆坦克

显式提供类型参数

twoCars.replaceFirst(new Tank())
twoCars.replaceFirst(新油箱())
尝试调用时将出现编译器错误

twoCars.<Vehicle>replaceFirst(new Tank())
油箱实际YACAR=两辆车。更换第一辆(新油箱())。第二辆();

首先,请注意此表单:

Tank actuallyACar = twoCars.<Vehicle>replaceFirst(new Tank()).second();
第一个问题是:

PairJ<Car> twoCars = new PairJ<Car>(new Car(), new Car());
// or
PairJ<Car> twoCars = new PairJ<>(new Car(), new Car());
public <R> PairJ<R> replaceFirst(R newFirst) {
    return new PairJ<R>(newFirst, second());
}
上述操作失败,因为它需要绑定到
R,R
,而不是
R,T

第二个问题是:

PairJ<Car> twoCars = new PairJ<Car>(new Car(), new Car());
// or
PairJ<Car> twoCars = new PairJ<>(new Car(), new Car());
public <R> PairJ<R> replaceFirst(R newFirst) {
    return new PairJ<R>(newFirst, second());
}
您的层次结构要求,虽然
汽车
汽车
,而
坦克
汽车
a
汽车
不是
坦克,因此
ClassCastException
是合适的;你真的不能将
汽车
抛向
坦克

这将失败,因为它们不能在两者之间转换

class Vehicle {}

class Car extends Vehicle {}

class Tank extends Vehicle {}

这里有一个解决方案;如果您想保留这个API,那么您的类需要两个类型参数。这意味着您现在可以在调用
replaceFirst
时自由传入新类型
R

Tank actuallyACar = twoCars.replaceFirst(new Tank()).second();
正如我前面所说的,
坦克
不是
汽车
,所以这根本不起作用:

PairJ<Car, Car> twoCars = new PairJ<>(new Car(), new Car());
……但这将:

以上内容可以归结为类层次结构的布局方式。在Java中,如果从
坦克
转换为
汽车
,即使您在类中正确使用了泛型,它也永远不会起作用。虽然他们有共同的祖先,但一个不是另一个


(现代示例:您不能将
字符串
强制转换为
整数
,即使它们都是
对象
的子对象)

是否可以让java推断坦克和汽车的通用基本类型,而不是显式地进行此操作,但是我很好奇为什么java不承认这个符号。@CuiPengFei您声明了新的
T
type参数,但是您没有使用它。那又有什么关系呢?哦,好吧,我没意识到。我以为那两个T是一样的。那么如何引用随类一起声明的T呢?所以我可以有这样的东西:public Pair replaceFirst(R newFirst)@CuiPengFei我不相信你能在Java中做到这一点。我得复习一下。我的目的不是把车改装成坦克,我只想在用坦克替换汽车时得到一双。但在Java中,这似乎不是一项容易的任务。
class Vehicle {}

class Car extends Vehicle {}

class Tank extends Vehicle {}
Tank actuallyACar = twoCars.replaceFirst(new Tank()).second();
class PairJ<S, T> {
    private S first;
    private T second;

    // accessors modified

    public <R> PairJ<R, T> replaceFirst(R newFirst) {
        return new PairJ<>(newFirst, second());
    }
}
PairJ<Car, Car> twoCars = new PairJ<>(new Car(), new Car());
Tank actuallyACar = twoCars.replaceFirst(new Tank()).second();
Car actuallyACar = twoCars.replaceFirst(new Tank()).second();