论坛首页 Java企业应用论坛

关于java泛型的疑惑,大家一起讨论一下

浏览 8417 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-11-01  
zhoujiangzi 写道
泛型是在编译期间进行检查的,在实际运行期间不会存在,你可以这样来试验下

先定义一个带泛型的List : List<Integer> list = new ArrayList<Integer>();
这个list已经添加泛型,存放integer数据类型,这时我们添加一个list.add("abc"); 编译器就会报错

但是你可以通过反射来往list中添加"abc" ,这就是运行期没有检查


了解了,多谢了。
0 请登录后投票
   发表时间:2013-11-01  
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了?
0 请登录后投票
   发表时间:2013-11-01  
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就编译不通过.
:>
0 请登录后投票
   发表时间:2013-11-01  
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里面其实就没泛型的事了,就已经类型擦除了。
0 请登录后投票
   发表时间:2013-11-01  
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不是用类型擦除的方式来实现泛型.

 

 

0 请登录后投票
   发表时间:2013-11-01  
@chenjingbo

引用
这样的例子才能说明是 Java 是使用了类型擦除的方式来实现的泛型,因为这样是错误的,使用了类型擦除导致两个重载的方法是完全一样的,所以是无法编译通过的,你打印getName在编译期间都搞定了,当然打印出来没问题了。


第一:我表达的主要意思是 JLS 定义的泛型是使用类型擦除,那么我只是拿其中一个javac的编译器来做个例子,请问哪里错了呢?

第二,假设你有自己的编译器不是sun的,自己写的最终类型还是得擦除,我的例子你可能编译过去了,但是你怎么解析呢?你自己的jvm在runtime的时候不按照jvm定义的class的规范?因为jvm的class规范中是没泛型的。

这些我真没觉得我说的哪里不对,如果你觉得不对,也请说的详细点,大家都看看嘛
0 请登录后投票
   发表时间:2013-11-01  
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规范

 

 

 

 

 

0 请登录后投票
   发表时间:2013-11-01  
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来做的支持的。

0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics