泛型中的类型擦除和代码生成

时间:2019-03-22 11:36:03

标签: java generics type-erasure

我有此示例代码/层次结构,以了解编译器在这种特殊情况下的行为。

我有以下类/接口;

#1:

abstract class Vehicle<T extends Steering> {

   protected T mSteering;

   public Vehicle(T mSteering) {
       this.mSteering = mSteering;
   }

   void turnLeft() {
       mSteering.toLeft();
   }

   void turnRight(){
      mSteering.toRight();
   }
}

class Car<T extends Steering> extends Vehicle<T> {

    Car(T mSteering) {
        super(mSteering);
    }

    T getSteering(){
        return mSteering;
    }
}

#2:

interface Steering {
    void toRight();
    void toLeft();
}

class XSteering implements Steering {

    @Override
    public void toRight() {

    }

    @Override
    public void toLeft() {
        System.out.println("steering left by XSteering");
    }
}

public class YSteering implements Steering {

    @Override
    public void toRight() {

    }

    @Override
    public void toLeft() {
        System.out.println("steering left by YSteering");
    }
}

#3:

public static void main(String[] args) {

    Car c1 = new Car<>(new XSteering());
    c1.turnLeft();
    // XSteering steering1 = c1.getSteering(); // DOES NOT COMPILE

    Car c2 = new Car<>(new YSteering());
    c2.turnLeft();
}

代码按预期输出;

steering left by XSteering
steering left by YSteering

因此,当我删除以下行中的注释时;

XSteering steering1 = c1.getSteering();

它不能编译。

因此,当在编译期间进行类型擦除时,我希望方法的返回类型被Steering getSteering()取代,因为它是最左侧的边界。还行吧。我的问题更多是关于呼叫站点上发生的事情。由于getSteering()具有通用的返回类型,因此我还期望编译器在调用函数的位置添加必要的强制转换,这样就不会添加显式强制转换来使其正常工作(换句话说,编译器不会给出并发症错误)。我能理解的人在这种情况下会失败吗?

1 个答案:

答案 0 :(得分:2)

您在Car c1 = new Car<>(new XSteering());中使用raw type,这就是为什么没有类型检查并且编译器将不会添加任何强制类型转换的原因。 T将是Steering,因为它受T的约束。只需使用:

Car<XSteering> c1 = new Car<>(new XSteering());

查看更多What is a raw type and why shouldn't we use it?