Java自类型方法: cannot safely cast to actual type

标签 java generics self-type

考虑下面的类,我相信它正确地称为 self-typed类:

public abstract class Example<E extends Example<E>> {
  /** Constructs an instance of the subclass */
  protected abstract E construct();

  /** Do a private operation in the base class */
  private void specialOp() {}

  public E get1() {
    E obj = construct();
    // Error: The method specialOp() from the type Example<E> is not visible
    obj.specialOp();
    return obj;
  }

  public E get2() {
    Example<E> obj = construct();
    obj.specialOp();
    // Warning: Type safety: Unchecked cast from Example<E> to E
    return (E)obj;
  }

  public E get3() {
    E obj = construct();
    ((Example<E>)obj).specialOp();
    return obj;
  }
}

也就是说,扩展此类的实现将具有如下所示的类型签名:

public class SubExample extends Example<SubExample>

三个中的每一个 get*()方法表面上做同样的事情 - 构造 Example 的子类,在实例上执行私有(private)方法,并将其作为其子类型返回。但是,只有最后一个示例可以在没有警告的情况下进行编译。

get1() 中的行为即使没有泛型也是一个错误,请考虑:

public class Example {
  private void specialOp() {};

  public void get(SubExample e) {
    // Error: The method specialOp() from the type Example is not visible
    e.specialOp();
  }

  public static class SubExample extends Example {}
}

我理解,即使这对我来说似乎是不必要的限制。同样get3()有道理,虽然我不喜欢这样的 Actor 。但是get2()让我困惑。我明白了E从技术上讲,是 Example<E> 的子类型,但这个泛型的边界不能确保所有 Example<E>也是E是?如果是这样,为什么这样类型转换不安全?是否可以从 Example<E> 进行转换至E没有警告?

最佳答案

并非全部Example<E> s 必须是 E s:

public class A extends Example<A> { ... }
public class B extends Example<A> { ... }

Example<A> notAnA = new B();

所以编译器是正确的。

请注意get3()也可以写成:

public E get3() {
    E obj = construct();
    Example<E> objAsEx = obj;
    objAsEx.specialOp();
    return obj;
}

因此,即使没有显式强制转换,编译器也知道代码是正确的。不过,它似乎并没有应用这些知识来允许私有(private)成员在不手持的情况下进行访问。

关于Java自类型方法: cannot safely cast to actual type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24115354/

相关文章:

java - JDK 7 中泛型和三元运算符的编译错误

scala - 编译器无法识别自类型注释

scala - 还有什么是Scala惯用: trait TraitA extends TraitB or trait TraitA { self: TraitB => }

java - 当实际有很多行时,结果集只显示 1 行

java - 如何获取类的类型进行比较

scala - 如何在Scala中为任何Traversable实现通用算法?

scala - 在 Scala 中使用 self 类型时如何保持单一责任?

java - 当在登录 Activity 中按下退格键时,Android 在登录屏幕上关闭

Java数组: Finding how many numbers are less then the Mean

java - 使用相同的参数类型创建通用映射来保存类型的键和值