最近看到BlogJava上有人在讨论为什么Java范型不支持数组http://www.blogjava.net/myqiao/archive/2005/08/08/9580.html
我想这个问题的答案是:因为这样做会破坏类型安全。核心的问题在于Java范型和C#范型存在根本区别:Java的范型停留在编译这一层,到了运行时,这些范型的信息其实是被抹掉的;而C#的范型做到了MSIL这一层。Java的做法不必修改JVM,减少了潜在的大幅改动和随之而来的风险,也许同时也反映出Java Bytecode规范在设计之初的先天不足;C#则大刀阔斧,连CLR一起改以支持更彻底的范型,换句话说,在范型这一点上,感觉C#更C++一点。
在Java中,Object[]数组可以是任何数组的父类,或者说,任何一个数组都可以向上转型成它在定义时指定元素类型的父类的数组,这个时候如果我们往里面放不同于原始数据类型 但是满足后来使用的父类类型的话,编译不会有问题,但是在运行时会检查加入数组的对象的类型,于是会抛ArrayStoreException:
String[] strArray = new String[20];
Object[] objArray = strArray;
objArray[0] = new Integer(1); // throws ArrayStoreException at runtime
因为Java的范型会在编译后将类型信息抹掉,这样如果Java允许我们使用类似
Map<Integer, String>[] mapArray = new Map<Integer, String>[20];
这样的语句的话,我们在随后的代码中可以把它转型为Object[]然后往里面放Map<Double, String>实例。这样做不但编译器不能发现类型错误,就连运行时的数组存储检查对它也无能为力,它能看到的是我们往里面放Map的对象,我们定义的<Integer, String>在这个时候已经被抹掉了,于是而对它而言,只要是Map,都是合法的。想想看,我们本来定义的是装Map<Integer, String>的数组,结果我们却可以往里面放任何Map,接下来如果有代码试图按原有的定义去取值,后果是什么不言自明。
所以,Java编译器不允许我们new范型数组。
分享到:
相关推荐
在Java中,数组的大小是在创建时固定的,一旦定义,就不能改变。如果我们需要一个可动态调整大小的数组,可以选择使用ArrayList或其他集合框架类。这些集合类提供了增加、删除和修改元素的能力,而它们内部就是通过...
这可能包括HTML、CSS和JavaScript文件,用于创建静态页面,以及用Java、C++或其他支持范型的语言编写的代码示例。通过分析这些示例,你可以看到范型是如何被用来创建灵活的代码结构,以及如何使用特定工具或框架生成...
Java范型是Java编程语言中的一个重要特性,它允许在类、接口和方法中使用类型参数,从而提高了代码的重用性和安全性。范型在Java中引入的主要目标是增强类型安全,减少强制类型转换,并帮助开发者编写更清晰、更易于...
总的来说,范型和容器类是Java集合框架的关键组成部分,它们为处理各种数据结构提供了强大的支持。理解并熟练运用这些概念,能够帮助开发者编写更加高效、安全和易于维护的代码。在实际开发中,根据需求选择合适的...
一切都是对象 2.1 用引用操纵对象 2.2 必须由你创建所有对象 2.2.1 存储到什么地方 2.2.2 特例:基本类型 2.2.3 Java中的数组 2.3 永远不需要销毁对象 2.3.1 作用域 2.3.2 对象的作用域 2.4 创建新的数据类型:类 ...
在Java编程语言中,集合与范型是两个非常重要的概念,它们构成了Java处理对象数组的基础。本实验将深入探讨这两个主题,旨在帮助你理解和熟练应用它们。以下是对这两个概念的详细解释。 首先,集合(Collections)...
本书虽然以JavaScript为出发点,但实际上其目的是探讨更广泛的编程范型,特别是命令式编程和函数式编程这两种主要的编程范型。 命令式编程是一种基于操作和状态变化的编程风格。在这一范型中,程序员通过明确指定一...
在Java 1.5版本之后,这一特性大大简化了开发者的代码,例如可以直接将整型数值10添加到List中,而无需创建Integer对象。 2. **优化的循环**: Java 1.5引入了类似于C#的foreach循环,也称为增强for循环。它使得...
一个Node.js模块,可从Object数组创建通用类型对象的数组或字典 安装 npm install @caliatys/array-typer --save 用法 Java脚本 设置示例 // Let's create our own object type let MyObject = /** @class */ ( ...
2.2.3 Java中的数组 2.3 永远不需要销毁对象 2.3.1 作用域 2.3.2 对象的作用域 2.4 创建新的数据类型:类 2.4.1 域和方法 2.4.2 基本成员默认值 2.5 方法、参数和返回值 2.5.1 参数列表 2.6 构建一个Java程序 2.6.1 ...
初步认识面向对象编程,Java视一切为对象。 使用输入和输出语句编写简单的Java应用程序。 区分applet与application(浏览器和虚拟机上运行)。 编写简单的applet,并嵌入HTML文档,掌握其...
**JDK 1.5,也称为Java 5.0,是Java开发工具包的一个重要版本,它引入了许多显著的新特性,极大地提升了编程的便利性和效率。以下将详细阐述这些特性:** ### 变长参数(Varargs) 变长参数允许在方法声明中使用一...
2.2.3 Java中的数组 2.3 永远不需要销毁对象 2.3.1 作用域 2.3.2 对象的作用域 2.4 创建新的数据类型:类 2.4.1 域和方法 2.4.2 基本成员默认值 2.5 方法、参数和返回值 2.5.1 参数列表 2.6 构建一个Java程序 2.6.1 ...
这需要检查栈是否为空,然后将栈顶元素复制到目标变量,从数据数组中移除,并减少栈的大小。 5. **查看栈顶元素(peek)**:查看栈顶元素但不移除。这只需要返回栈顶元素的副本,而无需修改栈的状态。 6. **检查栈...
- **动态创建二维数组**:通过循环的方式为每一行分配内存空间。 #### 4. 面向对象:继承与抽象类 - **基础知识**: - **面向对象**:是一种编程思想,主要特征包括封装、继承、多态。 - **继承**:允许子类...
链表不同于数组,它不连续存储数据。每个链表节点包含两部分:数据域(存储元素)和指针域(指向下一个节点)。这使得插入和删除操作相对数组更为高效,因为它们只需要改变相邻节点的指针,而不需要移动大量数据。 ...
- **创建方式**:Java中可以通过继承Thread类或者实现Runnable接口来创建线程。 - **生命周期**:包括新建状态、就绪状态、运行状态、阻塞状态和终止状态。 - **同步与锁**:为了保证多线程环境下的数据安全,需要...