java - 为什么这个泛型类型没有删除到指定的类

标签 java generics

考虑以下 Java 代码:

public class Program {
    static class Value {
        public String getString() {
            return "value";
        }
    }

    static class BetterValue extends Value {
        public String getBetterString() {
            return "better_value";
        }
    }

    static class Container<V extends Value> {
        public final V value;

        // EDIT #2: to mitigate the NPE:
        public Container(V value) {
            this.value = value;
        }
    }

    static class BetterContainter<V extends BetterValue> extends Container<V> {
        // EDIT #2: to mitigate the NPE:
        public BetterContainter(V value) {
            super(value);
        }
    }

    public static void main(String[] args) {
        // EDIT #2: to mitigate the NPE:
        Container container = new Container(new Value());
        System.out.println(container.value.getString());

        // EDIT #2: to mitigate the NPE:
        BetterContainter betterContainer = new BetterContainter(new BetterValue());
        System.out.println(betterContainer.value.getBetterString());
    }
}

当我尝试编译时,我得到:

Error:(28, 49) java: cannot find symbol
  symbol:   method getBetterString()
  location: variable value of type V

BetterContainer 中的“value”字段不应该删除为 BetterValue 吗?为什么它会删除容器的值?

编辑:为了减轻“不使用原始类型”的争论并使问题更接近我实际处理的问题,假设添加以下代码:

static class Consumer<C extends Container> {
  protected final C container;

  public Consumer(C container) {
    this.container = container;
  }

  public void consume() {
    System.out.println(container.getValue().getValue());
  }
}

static class BetterConsumer<C extends BetterContainer> extends Consumer<C> {

  public BetterConsumer(C container) {
    super(container);
  }

  @Override
  public void consume() {
    System.out.println(container.getValue().getBetterValue());
  }
}

我该如何解决能够做到的事情

System.out.println(container.getValue().getBetterValue());

没有类型转换?

最佳答案

@Slaw 的回答解释了原因:当使用原始类型时,Container 类中的 V 字段将被删除为 Value,即使它是从 BetterContainer 访问的。

要解决您的消费者示例的问题,您需要向消费者类添加一个类型变量(本例中为 ? 通配符):

static class Consumer<C extends Container<?>> {
    protected final C container;

    public Consumer(C container) {
        this.container = container;
    }

    public void consume() {
        System.out.println(container.value.getString());
    }
}

static class BetterConsumer<C extends BetterContainer<?>> extends Consumer<C> {

    public BetterConsumer(C container) {
        super(container);
    }

    @Override
    public void consume() {
        System.out.println(container.value.getBetterString());
    }
}

虽然在您的示例中没有必要,但您也可以使用绑定(bind)类型变量:

static class Consumer<T extends Value, C extends Container<T>> {

关于java - 为什么这个泛型类型没有删除到指定的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60927255/

相关文章:

java - java.lang 的正式规范在哪里?

java - 为什么静态泛型方法的返回类型前面应该有<T>

java - 如何从文件中读取和重写单例对象?

Java-将每个单词添加到数组列表?

scala - 检查范围是否包含 Scala 中的值的通用方法

c# - 编译时泛型语法

oop - 在 TypeScript 中扩展 React 组件

Scala:使用隐式证据的通用方法无法编译

java - Spring-Kafka 使用 ConcurrentKafkaListenerContainerFactory 来处理多个 @Kafkalistener

java - Spring-mvc中的JDBC异常处理