代码之家  ›  专栏  ›  技术社区  ›  Ray

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

  •  16
  • Ray  · 技术社区  · 6 年前

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

    对于泛型返回类型,我假设上面示例中的返回将计算为:

    return (Integer) "Foo";  // Inconvertible types !!!
    

    而是一个 String 返回并正确打印。

    如果将调用更改为:

    String fooString = foo.getFoo(); // Compile error, incompatible types found
    System.out.println(fooString);
    

    我遗漏了什么来帮助我理解这里发生了什么,以及为什么原始版本没有导致编译错误。

    3 回复  |  直到 6 年前
        1
  •  18
  •   Community CDub    5 年前

    这是因为超载解决了你的问题 println println(Object) ,因为没有 println(Integer) .

    (E) "Foo" 已删除,并移动到调用站点。有时这是不必要的,所以只有在需要的时候才铸造正确的类型。

    换言之,内部不执行强制转换 getFoo . 语言规范支持这一点:

    • 演员阵容是完全不受约束的。

      不会对此类强制转换执行任何运行时操作。

    擦除之后, 格特福 Object . 这就被传给了 println(对象) ,非常好。

    如果我调用这个方法并通过 foo.getFoo ,我

    static void f(Integer i) {
        System.out.println(i);
    }
    // ...
    f(foo.getFoo()); // ClassCastException
    

    因为这一次 需要 要铸造。

        2
  •  3
  •   ernest_k Petronella    6 年前

    System.out.println Integer . 所以这句话:

    System.out.println(foo.getFoo());
    

    正在呼叫 System.out.println(Object); .

    要验证它是否会失败,请尝试:

    Foo<Integer> foo = new Foo<Integer>();
    Integer fooInt = foo.getFoo(); //class cast exception
    

    以下操作将以相同的方式失败:

    public static void main(String[] args) throws Exception {
        Foo<Integer> foo = new Foo<Integer>();
        print(foo.getFoo()); //Would also fail with a class cast exception
    }
    static void print(Integer in) {
        System.out.println(in);
    }
    

    String fooString = foo.getFoo(); //can't work
    

    foo Foo<Integer> foo.getFoo() 返回一个 整数 编译器可以检测到这一点。

        3
  •  2
  •   Oleksandr Pyrohov Andreas    6 年前

    我想在会议期间补充一下 type erasure E Object 因此 Foo

    public static class Foo {
        public Object getFoo() {
            return "Foo";
        }
    }
    

    Object obj = foo.getFoo();
    System.out.println(obj);
    

    Foo<Integer> foo = new Foo<Integer>();
    String fooString = foo.getFoo(); // you're trying to trick the compiler (unsuccessfully)
               ^
    incompatible types: Integer can not be converted to String
    

    这是我们的主要责任 仿制药 -编译时检查。

    然而,故事还有另一面——执行时间。例如,如果你写:

    Integer value = foo.getFoo();
    

    ClassCastException 在运行时抛出(Java编译器插入 checkcast foo.getFoo() 可以投给 Integer ).