Java 中的泛型和子类型问题
Generics and Subtype problems in Java
首先,由于 java 有严格的类型系统,程序在编译时检查类型正确性,并在 classes 加载到字节码验证器时检查程序的字节码行刑前。
虽然泛型的引入拓宽了 Java 类型系统的潜力,但是由于 java 有子类型,所以在上面的例子中出现了很多问题:
String [] a ={"Hello"};
Object [] b= a;
b[0]= false;
String s=a[0];
System.out.println(s);
在上面的示例中,我们使用 String class 是 Object 的子class。
我的问题是编译器不对上述程序发出任何警告的原因是什么。当我尝试 运行 它(当然)会抛出异常。
还有 problems/consequences 上面的程序在 java 实现中可能有什么(我的意思是有什么明显的问题吗??)。
Java 中的数组是协变的,即。 String[]
可以传递给需要 Object[]
的对象。这就是编译器不阻止您将布尔值插入字符串数组的原因。
为了提供协变性同时也提供运行时保护,Java 工程师设计了数组,以便在编译时添加一个标记,用它的类型标记数组。即使我们可以在编译时添加布尔值,String[]
上的类型阻止我们在运行时添加布尔值 - 这就是触发 ArrayStoreException
的原因,您可能在 运行 时遇到代码。
这是 Java 在拥有协变数组和捕获向数组添加错误内容的步骤之间的权衡。这种权衡就是为什么某些语言(例如 Scala)选择不使用协变数组的原因。
创建通用数组是可能的,但并不简单,并且存在一些类型危险,因此这些方法适用于特定用例 - Josh Bloch 的 Effective Java 讨论了这些。
可以说使用泛型列表优于数组,因为您可以在编译时发现问题。
首先,由于 java 有严格的类型系统,程序在编译时检查类型正确性,并在 classes 加载到字节码验证器时检查程序的字节码行刑前。
虽然泛型的引入拓宽了 Java 类型系统的潜力,但是由于 java 有子类型,所以在上面的例子中出现了很多问题:
String [] a ={"Hello"};
Object [] b= a;
b[0]= false;
String s=a[0];
System.out.println(s);
在上面的示例中,我们使用 String class 是 Object 的子class。 我的问题是编译器不对上述程序发出任何警告的原因是什么。当我尝试 运行 它(当然)会抛出异常。 还有 problems/consequences 上面的程序在 java 实现中可能有什么(我的意思是有什么明显的问题吗??)。
Java 中的数组是协变的,即。 String[]
可以传递给需要 Object[]
的对象。这就是编译器不阻止您将布尔值插入字符串数组的原因。
为了提供协变性同时也提供运行时保护,Java 工程师设计了数组,以便在编译时添加一个标记,用它的类型标记数组。即使我们可以在编译时添加布尔值,String[]
上的类型阻止我们在运行时添加布尔值 - 这就是触发 ArrayStoreException
的原因,您可能在 运行 时遇到代码。
这是 Java 在拥有协变数组和捕获向数组添加错误内容的步骤之间的权衡。这种权衡就是为什么某些语言(例如 Scala)选择不使用协变数组的原因。
创建通用数组是可能的,但并不简单,并且存在一些类型危险,因此这些方法适用于特定用例 - Josh Bloch 的 Effective Java 讨论了这些。
可以说使用泛型列表优于数组,因为您可以在编译时发现问题。