筆記

          way

          JAVA調(diào)用重寫的祖父方法

          本打算繼承一個API中的Parent類(Parent繼承自GrandParent類),重寫其中的service方法,copy了Parent的service方法。不過發(fā)現(xiàn)Parent的service中也有super.service方法。當(dāng)時考慮直接調(diào)用GrandParent的service方法。。。未遂(包括反射也不行)。正好看到老外寫的一篇文章,翻譯:
          在Son類里面寫一個test方法:
          public void test() {
           
          super.test();
           
          this.test();
          }
          反編譯之后:
          public void test()
              {
              
          //    0    0:aload_0         
              
          //    1    1:invokespecial   #2   <Method void Parent.test()>
              
          //    2    4:aload_0         
              
          //    3    5:invokevirtual   #3   <Method void test()>
              
          //    4    8:return          
              }
          使用ASM可以完成對GrandParent方法的調(diào)用
          public class GrandParent {
              
          public void test() {
                      System.out.println(
          "test of GrandParent");
              }
          }

          public class Parent extends GrandParent{
              
          public void test() {
                  System.out.println(
          "test of Parent");
              }
          }

          public class Son extends Parent{
              
          public void test() {
                  System.out.println(
          "test of Son");
              }
          }
          調(diào)用Son實(shí)例的test方法只會執(zhí)行Son的test方法。而ASM可以修改class,先寫一個Example類繼承Son,重寫test方法

           1 import java.io.FileOutputStream;
           2  
           3 import org.objectweb.asm.ClassWriter;
           4 import org.objectweb.asm.MethodVisitor;
           5 import org.objectweb.asm.Opcodes;
           6  
           7 public class ASMByteCodeManipulation extends ClassLoader implements Opcodes {
           8  
           9  public static void main(String args[]) throws Exception {
          10   ClassWriter cw = new ClassWriter(0);
          11   cw.visit(V1_1, ACC_PUBLIC, "Example"null"Son"null);
          12  
          13   // creates a MethodWriter for the (implicit) constructor
          14   MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>""()V"null,null);
          15   mw.visitVarInsn(ALOAD, 0);
          16   mw.visitMethodInsn(INVOKESPECIAL, "Son""<init>""()V");
          17   mw.visitInsn(RETURN);
          18   mw.visitMaxs(11);
          19   mw.visitEnd();
          20  
          21   // creates a MethodWriter for the 'test' method
          22   mw = cw.visitMethod(ACC_PUBLIC, "test""()V"nullnull);
          23   mw.visitFieldInsn(GETSTATIC, "java/lang/System""out","Ljava/io/PrintStream;");
          24   mw.visitLdcInsn("test of AI3");
          25   mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream""println",
          26     "(Ljava/lang/String;)V");
          27   //Call test() of GrandParent
          28   mw.visitVarInsn(ALOAD, 0);
          29   mw.visitMethodInsn(INVOKESPECIAL, "GrandParent""test""()V");
          30   //Call test() of GrandParent
          31   mw.visitVarInsn(ALOAD, 0);
          32   mw.visitMethodInsn(INVOKESPECIAL, "Parent""test""()V");
          33   //Call test() of GrandParent
          34   mw.visitVarInsn(ALOAD, 0);
          35   mw.visitMethodInsn(INVOKESPECIAL, "Son""test""()V");
          36   mw.visitInsn(RETURN);
          37   mw.visitMaxs(21);
          38   mw.visitEnd();
          39  
          40   byte[] code = cw.toByteArray();
          41   FileOutputStream fos = new FileOutputStream("Example.class");
          42   fos.write(code);
          43   fos.close();
          44  
          45   ASMByteCodeManipulation loader = new ASMByteCodeManipulation();
          46   Class<?> exampleClass = loader.defineClass("Example", code, 0,
          47     code.length);
          48   Object obj = exampleClass.newInstance();
          49   exampleClass.getMethod("test"null).invoke(obj, null);
          50  
          51  }
          52 }
          輸出:
          test of AI3
          test of GrandParent
          test of Parent
          test of Son
          看看怎樣實(shí)現(xiàn)的,11行定義一個新的類Example繼承Son。22行,Example重寫test方法,先打印“test of AI3”,再分別在29、32、35行調(diào)用GrandParent、Parent、Son的test方法。
           main方法中,45行創(chuàng)建Example的實(shí)例,再用反射調(diào)他的test方法。
          使用invokespecial這種方式也有局限,只能從子類調(diào)用。否則報錯:
          Exception in thread "main" java.lang.VerifyError: (class: Example, method: test1 signature: (LAI2;)V) Illegal use of nonvirtual function call

          posted on 2012-05-31 11:23 yuxh 閱讀(2057) 評論(0)  編輯  收藏 所屬分類: jdkwork

          導(dǎo)航

          <2012年5月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          統(tǒng)計

          常用鏈接

          留言簿

          隨筆分類

          隨筆檔案

          收藏夾

          博客

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 隆化县| 延津县| 广元市| 香港 | 即墨市| 揭阳市| 家居| 中山市| 双柏县| 绥棱县| 衡东县| 楚雄市| 宽城| 彰武县| 锡林浩特市| 宾阳县| 隆昌县| 扶风县| 石家庄市| 海门市| 睢宁县| 密云县| 喀喇沁旗| 肇源县| 泗阳县| 都安| 布拖县| 崇明县| 黄陵县| 平原县| 盐山县| 南岸区| 涿鹿县| 雅安市| 广灵县| 响水县| 永川市| 德令哈市| 宜黄县| 邵阳市| 榕江县|