为什么使用泛型不会抛出运行时或编译时异常?

Ray*_*Ray 16 java generics

我在类中有一个方法,它具有通过使用泛型指定的返回类型.

public class SomeMain {

  public static void main(String[] args) {

    Foo<Integer> foo = new Foo<Integer>();
    System.out.println(foo.getFoo()); // Works, prints out "Foo"

  }

  public static class Foo<E>  {
    public E getFoo() {
      return (E) "Foo";
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

使用泛型返回类型,我假设上面示例中的返回值将评估为:

return (Integer) "Foo";  // Inconvertible types !!!
Run Code Online (Sandbox Code Playgroud)

而是String返回并正确打印.

如果我将调用更改为:我收到编译错误:

String fooString = foo.getFoo(); // Compile error, incompatible types found
System.out.println(fooString);
Run Code Online (Sandbox Code Playgroud)

我错过了什么来帮助我理解这里发生的事情以及为什么原始版本不会导致编译错误.

Swe*_*per 18

这是因为重载决议解决了你的println调用println(Object),因为没有println(Integer).

请记住,Java的泛型在运行时会被删除.和类似(E) "Foo"的演员表被删除,并被移动到呼叫网站.有时这不是必需的,因此只有在需要时才会将事物转换为正确的类型.

换句话说,内部不会执行任何演员表getFoo.语言规范支持:

第5.5.2节 Checked Casts和Unchecked Casts

  • 演员阵容完全不受限制.

    没有对这样的演员表执行运行时动作.

擦除后,getFoo返回Object.而且这种情况会传递进去println(Object),这非常好.

如果我调用此方法并通过foo.getFoo,我收到一个错误:

static void f(Integer i) {
    System.out.println(i);
}
// ...
f(foo.getFoo()); // ClassCastException
Run Code Online (Sandbox Code Playgroud)

因为这次需要进行铸造.