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

Java泛型类型强制

  •  1
  • Kitten  · 技术社区  · 6 年前

    这里我有以下代码:

    public final class Generics {
        private Generics() {}
    
        public static <T> T unchecked(Object obj) {
            return (T)obj; //unchecked cast warning
        }
    
        public static void main(String[] args) {
            //correct
            ArrayList<String> str = new ArrayList<String>();
            str.add("Hello");
            str.add("World");
            System.out.println(str);
    
            //"correct" - not type safe at all but due to type erasure this is almost legal
            ArrayList<Object> obj = Generics.<ArrayList<Object>>unchecked(str);
            obj.add(1);
            System.out.println(obj);
    
            //obviously wrong but still compiles (ClassCastException at runtime)
            Exception except = Generics.<Exception>unchecked(str);
            System.out.println(except);
        }
    }
    

    通常是铸模 ArrayList<Object> obj = (ArrayList<Object>)str 这将是一个致命的编译错误,因为这将违反使用该列表的预期。(可以将非字符串的对象插入到仅字符串列表中)

    这个场景中的“未选中”警告是什么,以及如何使用 unchecked() 方法不同于直接铸造参考?如何绕过编译器的类型检查?

    2 回复  |  直到 6 年前
        1
  •  4
  •   Andy Turner    6 年前

    checkcast

    public static <T> T unchecked(Object obj) {
        return (T)obj; //unchecked cast warning
    }
    

    T Object obj

    Exception except = Generics.<Exception>unchecked(str);
                   // ^ cast here!
    

    Exception except = (Exception) Generics.unchecked(str);
    

    ClassCastException

    unchecked null

    Exception except = (Exception) str;
    

    Exception except = (Exception) (Object) str;
    

        2
  •  1
  •   Daniele    6 年前

    ArrayList<Object> obj = (ArrayList<Object>)str

    ArrayList<String> ArrayList<Object> Double String

    unchecked

      // ArrayList<String> to ArrayList (raw) is legal
      ArrayList<Object> obj = (ArrayList<Object>)(ArrayList) str;
      // you can also cast to an interface-
      // at runtime, str could as well extend that interface!
      // and then Runnable can be downcasted to Exception
      // obviousy wrong, but still legal
      Exception except = (Exception)(Runnable)(str);
    

    Runnable ArrayList

    JLS, 5.1.6