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 閱讀(3628) 評論(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分別編繹運行一下看到差別了吧。差別不是因為泛型,而是因為別的原因。不要只看表面現象,要知到原因。  回復  更多評論   

          主站蜘蛛池模板: 三亚市| 邵东县| 定南县| 蒲城县| 遵义县| 孙吴县| 峨眉山市| 沂源县| 兰西县| 肇庆市| 蕲春县| 田东县| 西畴县| 清苑县| 章丘市| 东乌珠穆沁旗| 临海市| 旬阳县| 绵阳市| 桂平市| 阿拉善右旗| 隆回县| 响水县| 屏东县| 西畴县| 金湖县| 剑阁县| 河北省| 上思县| 历史| 惠州市| 鄯善县| 上犹县| 清水县| 磐安县| 建湖县| 宁陵县| 佛山市| 翁源县| 云浮市| 汝南县|