繁体   English   中英

为什么Eclipse Java编译器会抱怨内部派生类型的未经检查的强制转换?

[英]Why does the Eclipse Java compiler complain about an unchecked cast for inner derived types?

请考虑以下具有非静态内部类的泛型类Base<ID>

public class Base<ID> {
  ID id;

  public Base(ID id) {
    this.id = id;
  }

  public ID getId() {
    return id;
  }

  protected class BaseInner {
    String text = "Inner";
  }

  protected void method(BaseInner o) {
    o.text = "Foo";
  }
}

该方法Base.method采用类型的参数BaseInner 现在考虑以下派生类。

public class Sub<ID> extends Base<ID> {
  public Sub(ID id) {
    super(id);
  }

  @Override
  protected void method(BaseInner o) {

    if (o instanceof Sub.SubInner) {
      SubInner sub = (SubInner) o; // Why does this cast emit an "unchecked cast" warning

      sub.text = "Bar";
      sub.value = 1337;
    }
  }

  protected class SubInner extends BaseInner {
    Number value = 42;
  }
}

Sub类派生自Base ,内部类SubInner派生自内部类BaseInner Sub的泛型类型参数ID作为类型参数传递给基类Base

我的问题:为什么编译器SubInnerSub的重写method中抱怨从BaseInnerSubInner

为了理解警告,我试图构建一个用例,其中使用Sub<B>.SubInner调用Sub<A>method来证明警告是正确的。 但是,如果类型不兼容,我能想到的任何内容(包括? extends? super )会在方法调用上发出编译器错误。

所以我猜没有理由在method中对未经检查的强制转换进行警告。 我错过了什么?

由于方法覆盖发生在Sub<ID>实现中,编译器能够将SubInner的泛型类型SubInnerSub<ID>.SubInner 所以质疑这不是重复!

Eclipse编译器警告是

类型安全:未经检查从Base <ID> .BaseInner转换为Sub <ID> .SubInner

如果我使用Base<ID>.BaseInner作为方法参数,也不在演员表达式中使用Sub<ID>.SubInner ,那么Sub<ID>.SubInner也不会改变。

这接缝是Eclipse编译器问题。

Oracle编译器( javac )不会在此处省略任何警告。

在这种情况下,未经检查的强制转换意味着您正在从非限定类型转换为泛型类型。

Set<String> set = new HashSet();

此行也将生成未经检查的分配警告。

出现此警告是因为编译器无法在编译时删除强制转换是否安全。

SubInner实例具有对Sub实例的引用。 您正在从Base.BaseInner进行强制转换,因此您也从Base转换为Sub <ID>。 因此,您正在收到此警告。

编辑

解决方案是使用泛型参数。

public class Base<ID> {
    ID id;

    public Base(ID id) {
        this.id = id;
    }

    public ID getId() {
        return id;
    }

    protected class BaseInner {
        String text = "Inner";
    }

    protected void method(Base<ID>.BaseInner o) {
        o.text = "Foo";
    }
}


public class Sub<ID> extends Base<ID> {
    public Sub(ID id) {
        super(id);
    }

    @Override
    protected void method(Base<ID>.BaseInner o) {
        SubInner sub = (SubInner) o; 
        sub.text = "Bar";
        sub.value = 1337;
    }

    protected class SubInner extends BaseInner {
        Number value = 42;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM