- forenroll
- 等级: 初级会员
- 性别:
- 文章: 3
- 积分: 40
- 来自: 西安
|
zhoujiangzi 写道 泛型是在编译期间进行检查的,在实际运行期间不会存在,你可以这样来试验下
先定义一个带泛型的List : List<Integer> list = new ArrayList<Integer>();
这个list已经添加泛型,存放integer数据类型,这时我们添加一个list.add("abc"); 编译器就会报错
但是你可以通过反射来往list中添加"abc" ,这就是运行期没有检查
了解了,多谢了。
|
返回顶楼 |
|
|
- fxl545826
- 等级: 初级会员
- 性别:
- 文章: 11
- 积分: 30
- 来自: 北京
|
chenjingbo 写道 fxl545826 写道
public void test(List<String> list) {
}
public void test(List<Integer> list) {
}
这样的例子才能说明是 Java 是使用了类型擦除的方式来实现的泛型,因为这样是错误的,使用了类型擦除导致两个重载的方法是完全一样的,所以是无法编译通过的,你打印getName在编译期间都搞定了,当然打印出来没问题了。
亲,无法编译通过,不代表运行期也无法运行哦..无法编译通过只能说无法不符合java语言规范.但是与jvm规范还是不一样的
jvm运行需要编译后的class,你编译不通过怎么搞出这个class文件让jvm运行么?再就是哪里说jvm规范执行java不遵循JLS了?
|
返回顶楼 |
|
|
- chenjingbo
- 等级: 初级会员
- 性别:
- 文章: 50
- 积分: 50
- 来自: 杭州
|
fxl545826 写道 chenjingbo 写道 fxl545826 写道
public void test(List<String> list) {
}
public void test(List<Integer> list) {
}
这样的例子才能说明是 Java 是使用了类型擦除的方式来实现的泛型,因为这样是错误的,使用了类型擦除导致两个重载的方法是完全一样的,所以是无法编译通过的,你打印getName在编译期间都搞定了,当然打印出来没问题了。
亲,无法编译通过,不代表运行期也无法运行哦..无法编译通过只能说无法不符合java语言规范.但是与jvm规范还是不一样的
jvm运行需要编译后的class,你编译不通过怎么搞出这个class文件让jvm运行么?再就是哪里说jvm规范执行java不遵循JLS了?
你上面说的只是javac的编译.jvm能运行的不只是javac编译的二进制(注意,这里说的是二进制,不是说class文件).比如eclipse也有自己的编译器ECJ.另外,goovy python 都是运行在jvm上的.javac编译不通过的,不一定goovy就编译不通过.
:>
|
返回顶楼 |
|
|
- fxl545826
- 等级: 初级会员
- 性别:
- 文章: 11
- 积分: 30
- 来自: 北京
|
chenjingbo 写道 fxl545826 写道 chenjingbo 写道 fxl545826 写道
public void test(List<String> list) {
}
public void test(List<Integer> list) {
}
这样的例子才能说明是 Java 是使用了类型擦除的方式来实现的泛型,因为这样是错误的,使用了类型擦除导致两个重载的方法是完全一样的,所以是无法编译通过的,你打印getName在编译期间都搞定了,当然打印出来没问题了。
亲,无法编译通过,不代表运行期也无法运行哦..无法编译通过只能说无法不符合java语言规范.但是与jvm规范还是不一样的
jvm运行需要编译后的class,你编译不通过怎么搞出这个class文件让jvm运行么?再就是哪里说jvm规范执行java不遵循JLS了?
你上面说的只是javac的编译.jvm能运行的不只是javac编译的二进制(注意,这里说的是二进制,不是说class文件).比如eclipse也有自己的编译器ECJ.另外,goovy python 都是运行在jvm上的.javac编译不通过的,不一定goovy就编译不通过.
:>
那 Eclipse 的编译器这句话能过么?还有就是你看 JVM 规范里面定义泛型的事?因为泛型最终由编译器编译之后,给 JVM 的时候是按照 JVM 定义的 class 的规范给的,到了class里面其实就没泛型的事了,就已经类型擦除了。
|
返回顶楼 |
|
|
- chenjingbo
- 等级: 初级会员
- 性别:
- 文章: 50
- 积分: 50
- 来自: 杭州
|
fxl545826 写道
chenjingbo 写道
fxl545826 写道
chenjingbo 写道
fxl545826 写道
public void test(List<String> list) {
}
public void test(List<Integer> list) {
}
这样的例子才能说明是 Java 是使用了类型擦除的方式来实现的泛型,因为这样是错误的,使用了类型擦除导致两个重载的方法是完全一样的,所以是无法编译通过的,你打印getName在编译期间都搞定了,当然打印出来没问题了。
亲,无法编译通过,不代表运行期也无法运行哦..无法编译通过只能说无法不符合java语言规范.但是与jvm规范还是不一样的
jvm运行需要编译后的class,你编译不通过怎么搞出这个class文件让jvm运行么?再就是哪里说jvm规范执行java不遵循JLS了?
你上面说的只是javac的编译.jvm能运行的不只是javac编译的二进制(注意,这里说的是二进制,不是说class文件).比如eclipse也有自己的编译器ECJ.另外,goovy python 都是运行在jvm上的.javac编译不通过的,不一定goovy就编译不通过. :>
那 Eclipse 的编译器这句话能过么?还有就是你看 JVM 规范里面定义泛型的事?因为泛型最终由编译器编译之后,给 JVM 的时候是按照 JVM 定义的 class 的规范给的,到了class里面其实就没泛型的事了,就已经类型擦除了。
请仔细看我的第一个回复.我反驳的是
写道
你用javac不让编译为例子,说明sun的jvm实现泛型的方式是类型擦除.这是不合理的. 我并没有说,sun的jvm不是用类型擦除的方式来实现泛型.
|
返回顶楼 |
|
|
- fxl545826
- 等级: 初级会员
- 性别:
- 文章: 11
- 积分: 30
- 来自: 北京
|
@chenjingbo
引用 这样的例子才能说明是 Java 是使用了类型擦除的方式来实现的泛型,因为这样是错误的,使用了类型擦除导致两个重载的方法是完全一样的,所以是无法编译通过的,你打印getName在编译期间都搞定了,当然打印出来没问题了。
第一:我表达的主要意思是 JLS 定义的泛型是使用类型擦除,那么我只是拿其中一个javac的编译器来做个例子,请问哪里错了呢?
第二,假设你有自己的编译器不是sun的,自己写的最终类型还是得擦除,我的例子你可能编译过去了,但是你怎么解析呢?你自己的jvm在runtime的时候不按照jvm定义的class的规范?因为jvm的class规范中是没泛型的。
这些我真没觉得我说的哪里不对,如果你觉得不对,也请说的详细点,大家都看看嘛
|
返回顶楼 |
|
|
- chenjingbo
- 等级: 初级会员
- 性别:
- 文章: 50
- 积分: 50
- 来自: 杭州
|
fxl545826 写道
@chenjingbo 引用
这样的例子才能说明是 Java 是使用了类型擦除的方式来实现的泛型,因为这样是错误的,使用了类型擦除导致两个重载的方法是完全一样的,所以是无法编译通过的,你打印getName在编译期间都搞定了,当然打印出来没问题了。
第一:我表达的主要意思是 JLS 定义的泛型是使用类型擦除,那么我只是拿其中一个javac的编译器来做个例子,请问哪里错了呢? 第二,假设你有自己的编译器不是sun的,自己写的最终类型还是得擦除,我的例子你可能编译过去了,但是你怎么解析呢?你自己的jvm在runtime的时候不按照jvm定义的class的规范?因为jvm的class规范中是没泛型的。 这些我真没觉得我说的哪里不对,如果你觉得不对,也请说的详细点,大家都看看嘛
我们抛开这个泛型不谈
static {
while (true){
System.out.println("test");
}
}
这样的代码,在javac编译的时候,是不让编译通过的.但是这个代码是符合java specs 的.理论上,完全可以通过修改二进制码来做出上面的效果.
写道
这个代码在javac下编译不通过,不代表它不符合jvm规范
|
返回顶楼 |
|
|
- fxl545826
- 等级: 初级会员
- 性别:
- 文章: 11
- 积分: 30
- 来自: 北京
|
chenjingbo 写道
fxl545826 写道
@chenjingbo 引用
这样的例子才能说明是 Java 是使用了类型擦除的方式来实现的泛型,因为这样是错误的,使用了类型擦除导致两个重载的方法是完全一样的,所以是无法编译通过的,你打印getName在编译期间都搞定了,当然打印出来没问题了。
第一:我表达的主要意思是 JLS 定义的泛型是使用类型擦除,那么我只是拿其中一个javac的编译器来做个例子,请问哪里错了呢? 第二,假设你有自己的编译器不是sun的,自己写的最终类型还是得擦除,我的例子你可能编译过去了,但是你怎么解析呢?你自己的jvm在runtime的时候不按照jvm定义的class的规范?因为jvm的class规范中是没泛型的。 这些我真没觉得我说的哪里不对,如果你觉得不对,也请说的详细点,大家都看看嘛
我们抛开这个泛型不谈
static {
while (true){
System.out.println("test");
}
}
这样的代码,在javac编译的时候,是不让编译通过的.但是这个代码是符合java specs 的.理论上,完全可以通过修改二进制码来做出上面的效果.
写道
这个代码在javac下编译不通过,不代表它不符合jvm规范
但是这个不妨碍这个例子的正确性,我只是写代码的时候看见javac给我提示了所以我才说了编译不通过,其实严谨一点说应该是这个类是不符合JLS规范的。还有就是你那句话其实你写个java文件不需要考虑jvm规范,只是考虑JLS就可以了,因为泛型等任何语言特性jvm都是根据新jls来做的支持的。
|
返回顶楼 |
|
|