DANCE WITH JAVA

开发出高质量的系统

常用链接

统计

积分与排名

好友之家

最新评论

再次证明JDK1.5泛型实现原理

在这篇文章中用Jad说明了JDK1.5中的泛型是擦拭法实现,实际是通过编绎前处理,或者编译器实现的。但有人说Jad还不支持1.5的语法,那么从另一个角度证明一下,就有了这篇文章。

import  java.util.ArrayList;


public   class  Generic  {

    
public   static   void  main(String[] args)  {
        ArrayList list1 
=   new  ArrayList();
        list1.add(
" 1 " );
        String str1 
=  (String)list1.get( 0 );
        
        ArrayList
< String >  list2  =   new  ArrayList < String > ();
        list2.add(
" 1 " );
        String str2 
=  list2.get( 0 );
    }


}

取得上边这段代码的字节码:(如何取得字节码见这里)
// class version 49.0 (49)
// access flags 33
public class Generic {

  
// compiled from: Generic.java

  
// access flags 1
  public <init>()V
   L0 (
0)
    LINENUMBER 
4 L0
    ALOAD 
0
    INVOKESPECIAL java
/lang/Object.<init>()V
    RETURN
   L1 (
4)
    LOCALVARIABLE 
this LGeneric; L0 L1 0
    MAXSTACK 
= 1
    MAXLOCALS 
= 1

  
// access flags 9
  public static main([Ljava/lang/String;)V
   L0 (
0)
    LINENUMBER 
7 L0
    NEW java
/util/ArrayList
    DUP
    INVOKESPECIAL java
/util/ArrayList.<init>()V
    ASTORE 
1
   L1 (
5)
    LINENUMBER 
8 L1
    ALOAD 
1
    LDC 
"1"
    INVOKEVIRTUAL java
/util/ArrayList.add(Ljava/lang/Object;)Z
    POP
   L2 (
10)
    LINENUMBER 
9 L2
    ALOAD 
1
    ICONST_0
    INVOKEVIRTUAL java
/util/ArrayList.get(I)Ljava/lang/Object;
    CHECKCAST java
/lang/String
    ASTORE 
2
   L3 (
16)
    LINENUMBER 
11 L3
    NEW java
/util/ArrayList
    DUP
    INVOKESPECIAL java
/util/ArrayList.<init>()V
    ASTORE 
3
   L4 (
21)
    LINENUMBER 
12 L4
    ALOAD 
3
    LDC 
"1"
    INVOKEVIRTUAL java
/util/ArrayList.add(Ljava/lang/Object;)Z
    POP
   L5 (
26)
    LINENUMBER 
13 L5
    ALOAD 
3
    ICONST_0
    INVOKEVIRTUAL java
/util/ArrayList.get(I)Ljava/lang/Object;
    CHECKCAST java
/lang/String
    ASTORE 
4
   L6 (
32)
    LINENUMBER 
14 L6
    RETURN
   L7 (
34)
    LOCALVARIABLE args [Ljava
/lang/String; L0 L7 0
    LOCALVARIABLE list1 Ljava
/util/ArrayList; L1 L7 1
    LOCALVARIABLE str1 Ljava
/lang/String; L3 L7 2
    LOCALVARIABLE list2 Ljava
/util/ArrayList; L4 L7 3
    
// signature Ljava/util/ArrayList<Ljava/lang/String;>;
    
// declaration: java.util.ArrayList<java.lang.String>
    LOCALVARIABLE str2 Ljava/lang/String; L6 L7 4
    MAXSTACK 
= 2
    MAXLOCALS 
= 5
}

仔细看一下,每个代码块对应的都有
INVOKEVIRTUAL java/util/ArrayList.get(I)Ljava/lang/Object;
CHECKCAST java/lang/String
有没有泛型的字节码是一样的,说明在运行时,都进行了转型,所以说上一篇文章的说明应改是正确的。

posted on 2006-11-10 13:05 dreamstone 阅读(3536) 评论(5)  编辑  收藏 所属分类: jdk相关

评论

# re: 再次证明JDK1.5泛型实现原理 2006-11-13 15:46 Tin

对,对。就是擦拭法。编译时大部分元信息被擦拭了,不过继承和泛型方法的Generic Type还可以在编译后获取回来,这就挺够用了,但是够Tricky。  回复  更多评论   

# re: 再次证明JDK1.5泛型实现原理 2006-11-14 01:08 dreamstone

嗯,不过Java的实现方式导致的一个结果就是泛型只简化了代码,并没有提高效率。但是dot net利用C++类似的template的方式来实现,效率提升很大。  回复  更多评论   

# re: 再次证明JDK1.5泛型实现原理[未登录] 2007-03-22 20:25 a

有没有效率提升测试了才知道..  回复  更多评论   

# re: 再次证明JDK1.5泛型实现原理[未登录] 2007-03-22 20:38 a

经过实际测试发现,JDK1.5泛型 确实比以前效率有所提升

代码如下:(这是没有采用泛型的代码,采用泛型只要改三个地方然后在测试)
public static void main(String[] args){

//--测试JDK1.4 和 JDK5的性能...

System.out.println(NormMisc.getStDateTime());
long startime = 0;
long ttime = 0;
for(int j=0;j<30;j++){
startime = System.currentTimeMillis();
for(int ii=0;ii<5000;ii++){
ArrayList l = new ArrayList();
for(int i=0;i<10;i++){
Car c = new Car();
c.setDesc("Desc");c.setName("name-"+i);c.setNumber("Number");
l.add(c);
}
for(int i = 0;i<l.size();++i){
Car c = (Car)l.get(i);
String cs = c.toString();
//System.out.println(cs);
}
l.clear();
}
ttime += (System.currentTimeMillis()-startime);
}
System.out.println(NormMisc.getStDateTime());
System.out.println("平均时间:"+ttime/10);
}
}

class Car{
private String name;
private String number;
private String desc;
/**
* @return desc
*/
public String getDesc() {
return desc;
}
/**
* @param desc 要设置的 desc
*/
public void setDesc(String desc) {
this.desc = desc;
}
/**
* @return name
*/
public String getName() {
return name;
}
/**
* @param name 要设置的 name
*/
public void setName(String name) {
this.name = name;
}
/**
* @return number
*/
public String getNumber() {
return number;
}
/**
* @param number 要设置的 number
*/
public void setNumber(String number) {
this.number = number;
}


public String toString(){
return "name "+name+",number "+number+",desc "+desc;
}

}
  回复  更多评论   

# re: 再次证明JDK1.5泛型实现原理 2007-03-23 10:48 dreamstone

@a
先不管你这段代码写的如何,逻辑上就有问题,jdk1.5编绎后比jdk1.4运行快就一定是因为泛型吗?

就用你这段代码,不使用泛型的情况下,你用jdk1.4和 jdk1.5分别编绎运行一下看到差别了吧。差别不是因为泛型,而是因为别的原因。不要只看表面现象,要知到原因。  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航: