首页 文章

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

提问于
浏览
3

考虑以下具有非静态内部类的泛型类 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 .

My question: 为什么编译器在 Sub 的覆盖 method 中抱怨从 BaseInnerSubInner 的强制转换?

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

所以我想没有理由在 method 中对未经检查的演员进行警告 . 我错过了什么?

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

Eclipse编译器警告是

类型安全:取消选中从Base <ID> .BaseInner到Sub <ID> .SubInner的强制转换

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

2 回答

  • 1

    这接缝是Eclipse编译器问题 .

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

  • 0

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

    Set<String> set = new HashSet();
    

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

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

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

    Edit

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

    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;
        }
    }
    

相关问题