Java如何调用父类的父类的中的方法

1.可以用反射实现

2.可以用虚拟机级别的invokeddynamic实现(基于java1.7版本以及以上才可以)

代码如下:


/**
 * @(#)Text4.java
 *
 *
 * @author 
 * @version 1.00 2016/12/6
 */
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import static java.lang.invoke.MethodHandles.lookup;

public class Text4 {

    class GrandFather{
    	void thinking(){
    		System.out.println("i am grandfather");
    	}
    }
    
    class Father extends GrandFather{
    	void thinking(){
    		System.out.println("i am father");
    	}
    }
    
    class son extends Father{
    	void thinking(){
    		try{
    			MethodType mt = MethodType.methodType(void.class);
    			MethodHandle mh = lookup().findSpecial(GrandFather.class,
    				"thinking", mt, getClass());
    				mh.invoke(this);
    		}catch(Throwable e){
    			
    		}
    	}
    }
    
    public static void main(String[] args){
    	(new Text4().new son()).thinking();
    }
    
    
}


对上述代码使用生成class字节码:


Classfile /E:/JAVAprojects/noMain/bin/noMain/son.class
  Last modified 2016-12-6; size 1386 bytes
  Compiled from "son.java"
public class noMain.son extends noMain.Father
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Class              #2             // noMain/son
   #2 = Utf8               noMain/son
   #3 = Class              #4             // noMain/Father
   #4 = Utf8               noMain/Father
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Methodref          #3.#9          // noMain/Father."<init>":()V
   #9 = NameAndType        #5:#6          // "<init>":()V
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               LnoMain/son;
  #14 = Utf8               thinking
  #15 = Methodref          #16.#18        // java/lang/Object.getClass:()Ljava/lang/Class;
  #16 = Class              #17            // java/lang/Object
  #17 = Utf8               java/lang/Object
  #18 = NameAndType        #19:#20        // getClass:()Ljava/lang/Class;
  #19 = Utf8               getClass
  #20 = Utf8               ()Ljava/lang/Class;
  #21 = Fieldref           #22.#24        // java/lang/Void.TYPE:Ljava/lang/Class;
  #22 = Class              #23            // java/lang/Void
  #23 = Utf8               java/lang/Void
  #24 = NameAndType        #25:#26        // TYPE:Ljava/lang/Class;
  #25 = Utf8               TYPE
  #26 = Utf8               Ljava/lang/Class;
  #27 = Methodref          #28.#30        // java/lang/invoke/MethodType.methodType:(Ljava/lang/Class;)Ljava/lang/invoke/MethodType;
  #28 = Class              #29            // java/lang/invoke/MethodType
  #29 = Utf8               java/lang/invoke/MethodType
  #30 = NameAndType        #31:#32        // methodType:(Ljava/lang/Class;)Ljava/lang/invoke/MethodType;
  #31 = Utf8               methodType
  #32 = Utf8               (Ljava/lang/Class;)Ljava/lang/invoke/MethodType;
  #33 = Methodref          #34.#36        // java/lang/invoke/MethodHandles.lookup:()Ljava/lang/invoke/MethodHandles$Lookup;
  #34 = Class              #35            // java/lang/invoke/MethodHandles
  #35 = Utf8               java/lang/invoke/MethodHandles
  #36 = NameAndType        #37:#38        // lookup:()Ljava/lang/invoke/MethodHandles$Lookup;
  #37 = Utf8               lookup
  #38 = Utf8               ()Ljava/lang/invoke/MethodHandles$Lookup;
  #39 = Class              #40            // noMain/GrandFather
  #40 = Utf8               noMain/GrandFather
  #41 = String             #14            // thinking
  #42 = Methodref          #43.#45        // java/lang/invoke/MethodHandles$Lookup.findSpecial:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle;
  #43 = Class              #44            // java/lang/invoke/MethodHandles$Lookup
  #44 = Utf8               java/lang/invoke/MethodHandles$Lookup
  #45 = NameAndType        #46:#47        // findSpecial:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle;
  #46 = Utf8               findSpecial
  #47 = Utf8               (Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle;
  #48 = Methodref          #49.#51        // java/lang/invoke/MethodHandle.invoke:(LnoMain/son;)V
  #49 = Class              #50            // java/lang/invoke/MethodHandle
  #50 = Utf8               java/lang/invoke/MethodHandle
  #51 = NameAndType        #52:#53        // invoke:(LnoMain/son;)V
  #52 = Utf8               invoke
  #53 = Utf8               (LnoMain/son;)V
  #54 = Class              #55            // java/lang/Throwable
  #55 = Utf8               java/lang/Throwable
  #56 = Utf8               a
  #57 = Utf8               mt
  #58 = Utf8               Ljava/lang/invoke/MethodType;
  #59 = Utf8               mh
  #60 = Utf8               Ljava/lang/invoke/MethodHandle;
  #61 = Utf8               StackMapTable
  #62 = Class              #63            // java/lang/Class
  #63 = Utf8               java/lang/Class
  #64 = Utf8               main
  #65 = Utf8               ([Ljava/lang/String;)V
  #66 = Methodref          #1.#9          // noMain/son."<init>":()V
  #67 = Methodref          #1.#68         // noMain/son.thinking:()V
  #68 = NameAndType        #14:#6         // thinking:()V
  #69 = Utf8               args
  #70 = Utf8               [Ljava/lang/String;
  #71 = Utf8               SourceFile
  #72 = Utf8               son.java
  #73 = Utf8               InnerClasses
  #74 = Utf8               Lookup
{
  public noMain.son();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #8                  // Method noMain/Father."<init>":()V
         4: return
      LineNumberTable:
        line 32: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LnoMain/son;

  void thinking();
    descriptor: ()V
    flags:
    Code:
      stack=5, locals=4, args_size=1
         0: aload_0
         1: invokevirtual #15                 // Method java/lang/Object.getClass:()Ljava/lang/Class;
         4: astore_1
         5: getstatic     #21                 // Field java/lang/Void.TYPE:Ljava/lang/Class;
         8: invokestatic  #27                 // Method java/lang/invoke/MethodType.methodType:(Ljava/lang/Class;)Ljava/lang/invoke/MethodType;
        11: astore_2
        12: invokestatic  #33                 // Method java/lang/invoke/MethodHandles.lookup:()Ljava/lang/invoke/MethodHandles$Lookup;
        15: ldc           #39                 // class noMain/GrandFather
        17: ldc           #41                 // String thinking
        19: aload_2
        20: aload_1
        21: invokevirtual #42                 // Method java/lang/invoke/MethodHandles$Lookup.findSpecial:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle;
        24: astore_3
        25: aload_3
        26: aload_0
        27: invokevirtual #48                 // Method java/lang/invoke/MethodHandle.invoke:(LnoMain/son;)V
        30: goto          34
        33: astore_2
        34: return
      Exception table:
         from    to  target type
             5    30    33   Class java/lang/Throwable
      LineNumberTable:
        line 36: 0
        line 38: 5
        line 39: 12
        line 40: 15
        line 41: 17
        line 40: 21
        line 39: 24
        line 43: 25
        line 44: 30
        line 47: 34
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      35     0  this   LnoMain/son;
            5      30     1     a   Ljava/lang/Class;
           12      18     2    mt   Ljava/lang/invoke/MethodType;
           25       5     3    mh   Ljava/lang/invoke/MethodHandle;
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 33
          locals = [ class noMain/son, class java/lang/Class ]
          stack = [ class java/lang/Throwable ]
        frame_type = 0 /* same */

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: new           #1                  // class noMain/son
         3: dup
         4: invokespecial #66                 // Method "<init>":()V
         7: invokevirtual #67                 // Method thinking:()V
        10: return
      LineNumberTable:
        line 53: 0
        line 55: 10
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      11     0  args   [Ljava/lang/String;
}
SourceFile: "son.java"
InnerClasses:
     public static final #74= #43 of #34; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles


没有生成invokedynamic调用,应该是我的jvm配置出错,使得jvm栈帧的模式值调用了出栈的第一个实例使得输出答案为 i am father


虚拟机级别动态分配调用方法代码:


/**
 * @(#)StaticDispatch.java
 *
 *
 * @author 
 * @version 1.00 2016/12/6
 */


import java.lang.invoke.*;
import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import static java.lang.invoke.MethodHandles.lookup;

public class StaticDispatch {

 	static class ClassA{
 		public void println(String s){
 			System.out.println(s);
 		}
 	}
    
    
	private static MethodHandle getPrintlnMH(Object recevier) throws Throwable{
		MethodType mt = MethodType.methodType(void.class,String.class);
		return lookup().findVirtual(recevier.getClass(),"println",mt).bindTo(recevier);
	}

    
    public static void main(String[] args) throws Throwable{
		Object ob = System.currentTimeMillis() % 2 == 0 ? System.out : new ClassA();
		
		getPrintlnMH(ob).invokeExact("invoke println"); 
    }
    
}


  • 11
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值