【问题标题】:Generics and Subtype problems in Java [duplicate]Java中的泛型和子类型问题[重复]
【发布时间】:2017-01-15 15:15:25
【问题描述】:

首先,由于 java 有严格的类型系统,程序在编译时检查类型正确性,并在执行前将类加载到字节码验证器时检查程序的字节码。

虽然泛型的引入拓宽了Java类型系统的潜力,但是由于java有子类型,所以在上面的例子中出现了很多问题:

 String [] a ={"Hello"};
        Object [] b= a;
        b[0]=  false;
        String s=a[0];

        System.out.println(s);

在上面的例子中,我们使用 String 类是 Object 的子类。 我的问题是编译器没有对上述程序产生任何警告的原因是什么。当我尝试运行它时(当然)会引发异常。 此外,上述程序在 java 实现中可能存在哪些问题/后果(我的意思是有什么明显的问题吗??)。

【问题讨论】:

  • 您可以从阅读 Bracha 的泛型教程开始。
  • 关于问题本身,这是一个重复:stackoverflow.com/questions/18666710/…
  • 如果你想进行一些高级别的 Arch 讨论,programmers.se 似乎更适合这类问题。
  • 如果你想知道关于java类型系统的JVM impl的一些very具体细节,你应该用jvm标签询问very具体问题.
  • 这个问题与泛型无关,因为您谈论的是作为 Java 语言自然组成部分的数组。泛型是 java 1.5 中添加的一项功能,允许您创建具有特定类型的数据结构,例如 ArrayList 和 Trees:ArrayList、Tree

标签: java generics types programming-languages


【解决方案1】:

Java 中的数组是协变的,即。 String[] 可以传递给期望 Object[] 的东西。这就是为什么编译器不会阻止您将布尔值粘贴到 String 数组中的原因。

为了提供协方差并提供运行时保护,Java 工程师设计了数组,以便在编译时添加一个标记,该标记用它的类型标记数组。即使我们可以在编译时添加布尔值,String[] 上的类型也会阻止我们在运行时添加布尔值 - 这是触发您在运行代码时可能遇到的 ArrayStoreException 的原因。

这是在 Java 中使用协变数组和捕捉向数组中添加错误内容的步骤之间的权衡。这种权衡就是为什么某些语言(如 Scala)选择不使用协变数组的原因。

可以创建通用数组,但并不简单,并且存在一些类型危险,因此这些方法适用于特定用例 - Josh Bloch 的 Effective Java 讨论了这些。

可以说使用泛型列表而不是数组更好,因为这样您就可以在编译时发现问题。

【讨论】:

  • @Nio ,非常感谢这个帮助,现在很清楚为什么要编译它。因为我没有太多的java经验,这是否会导致java实现中的进一步问题? (它是否有进一步的影响 - 不要求广泛的答案)。
  • @coder,我不能 100% 确定我明白你的问题,但如果我理解正确,那么我会说你不需要担心进一步的影响。我想说,如果您对 Java 没有那么丰富的经验,那么请避免使用数组并使用泛型列表,因为编译器会阻止您将错误的内容添加到列表中。如果你真的想使用数组,那么你只需要非常小心地保护这些数组,即。不要从方法中返回它们,否则你会冒有人添加错误的东西的风险,这些东西可能直到运行时才会显现出来。
  • Nio,谢谢你的回答帮了大忙!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多