Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用Java泛型理解类型安全异常_Java_Generics_Java 8 - Fatal编程技术网

用Java泛型理解类型安全异常

用Java泛型理解类型安全异常,java,generics,java-8,Java,Generics,Java 8,我有以下代码: public static void main(String[] args) { List<String> s = new ArrayList<String>(); s.add("kshitiz"); //This is not typesafe. It should blow up at runtime List<Integer> i = new ArrayList(s); System.out.pr

我有以下代码:

public static void main(String[] args) {
    List<String> s = new ArrayList<String>();
    s.add("kshitiz");

    //This is not typesafe. It should blow up at runtime
    List<Integer> i = new ArrayList(s);
    System.out.println(i.get(0));
}
例外情况:

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

这里发生了什么?

我想您应该知道,泛型类型在运行时已经消失了。现在,为了了解幕后发生了什么,让我们看看这段代码

public static Class<?> getClass(final Object object) {
    return object.getClass();
}

public static void main(final String[] args) {
    final List<String> s = new ArrayList<String>();
    s.add("kshitiz");

    // This is not typesafe. It should blow up at runtime
    final List<Integer> i = new ArrayList(s);
    System.out.println(getClass(i.get(0)));
    System.out.println(i.get(0).getClass());
}
在第二次调用中,字符串被转换为整数,而在第一次调用中,它被视为一个对象。
因此,只要字符串像处理任何其他对象一样处理,一切都很好,但只要调用列表元素类型的方法,对象就会转换为该类型。

java中的泛型会被设计破坏

在您的
列表中,i=新的数组列表您有一个原始
数组列表
。这意味着您忽略了类型参数,它的工作原理就像它是一个
对象一样。然后(隐式地)将
ArrayList
强制转换为
列表
,但在运行时不检查泛型,因此JVM不关心不匹配

执行
System.out.println(i.get(0))
时,不会将
String
转换为
Integer
,因为调用了“println(Object)`方法


System.out.println(i.get(0.getClass())
中,这个魔术刹车是因为出于某种原因(您可能可以在规范中找到这个原因,但我建议您不要这样做)您的
字符串被强制转换为
整数

请指定Java版本它会引发什么异常?
线程“main”中的异常java.lang.ClassCastException:java.lang.String不能转换为java.lang.Integer
您忽略了一些重要的编译器警告。您的IDE或编译器应该警告您访问原始类型。这里很好地解释了为什么编译器会进行这种不必要的强制转换。您可以讨论如果代码在
ArrayList
ArrayList
的赋值中失败,或者在调用
get
时失败是否更好,我看不出有足够的差异来证明将当前行为称为“设计破坏”是合理的。毕竟,结果是一样的,忽略编译时警告会导致运行时异常…
public static Class<?> getClass(final Object object) {
    return object.getClass();
}

public static void main(final String[] args) {
    final List<String> s = new ArrayList<String>();
    s.add("kshitiz");

    // This is not typesafe. It should blow up at runtime
    final List<Integer> i = new ArrayList(s);
    System.out.println(getClass(i.get(0)));
    System.out.println(i.get(0).getClass());
}
  [...]
  26: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
  29: aload_2
  30: iconst_0
  31: invokeinterface #9,  2            // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
  36: invokestatic  #10                 // Method getClass:(Ljava/lang/Object;)Ljava/lang/Class;
  39: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
  42: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
  45: aload_2
  46: iconst_0
  47: invokeinterface #9,  2            // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
  52: checkcast     #12                 // class java/lang/Integer
  55: invokevirtual #2                  // Method java/lang/Object.getClass:()Ljava/lang/Class;
  58: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
  61: return