Java自类型方法:无法安全地强制转换为实际类型 [英] Java self-typed methods: cannot safely cast to actual type

查看:137
本文介绍了Java自类型方法:无法安全地强制转换为实际类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下类别,我认为该类别正确称为自类型类:

Consider the following class, which I believe is correctly called a self-typed class:

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

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

That is to say, implementations extending this class would have a type signature like so:

public class SubExample extends Example<SubExample>

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

Each of the three get*() methods ostensibly do the same thing - construct a subclass of Example, execute a private method on the instance, and return it as its subtype. However only the last example compiles without warnings.

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

The behavior in get1() is an error even without generics, consider:

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()也很有意义,尽管我不喜欢这样进行强制转换.但是get2()使我感到困惑.我了解E从技术上讲是Example<E>的子类型,但是这种泛型的范围不能确保所有Example<E>也是E吗?如果是这样,为什么这样铸造不安全?是否有可能在没有警告的情况下从Example<E>投射到E?

Which I understand, even if it seems unnecessarily restrictive to me. And similarly get3() makes sense, though I dislike needing to cast like that. But get2() confuses me. I understand E is technically a subtype of Example<E>, but don't the bounds of this generic ensure that all Example<E>s are also Es? If so, why is it not safe to cast like this? Is it ever possible to cast from Example<E> to E without a warning?

推荐答案

并非所有Example<E>都必须是E s:

Not all Example<E>s must be Es:

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

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

So the compiler knows that code is correct, even without an explicit cast. It doesn't seem to apply this knowledge to allow the private member access without having it's hand held, though.

这篇关于Java自类型方法:无法安全地强制转换为实际类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆