對於子類調用父類的方法我們用super.Method()即可,但是倘若我們想調用其祖先類,並且在不改變其繼承關係以及祖先和父類的代碼的時候,該怎麼辦呢,代碼樣列如下:給大家三個類,可以先去了解再來熟悉下面的代碼
- MethodHandle 它是可對直接執行的方法或者字段或者構造方法的類型的引用,或者說他是一個有能力安全調用方法的對象。
- MethodHandles 它是僅操作或返回方法句柄的靜態方法的類。
- MethodType 他是表示方法簽名類型的不可變對象。每個MethodHandle都有一個MethodType實例,用來指明返回類型和參數類型。
package vip.wulang.test;
/**
* @author coolerwu on 2018/8/13.
* @version 1.0
* @time 20:58
*/
public class ParentTest {
class GrandFather {
public void thinking() {
System.out.println("i am grandfather.");
}
}
class Father extends GrandFather {
@Override
public void thinking() {
System.out.println("i am father.");
}
}
class Son extends Father {
@Override
public void thinking() {
//如何調用GrandFather
}
}
public static void main(String[] args) {
new ParentTest().new Son().thinking();
}
}
第一種方法
package vip.wulang.test;
/**
* @author coolerwu on 2018/8/13.
* @version 1.0
* @time 20:58
*/
public class ParentTest {
class GrandFather {
public void thinking() {
System.out.println("i am grandfather.");
}
}
class Father extends GrandFather {
@Override
public void thinking() {
System.out.println("i am father.");
}
}
class Son extends Father {
@Override
public void thinking() {
GrandFather grandFather = new GrandFather();
grandFather.thinking();
}
}
public static void main(String[] args) {
new ParentTest().new Son().thinking();
}
}
//輸出結果
//i am grandfather.
第二種方法也就是今天我要講的這種,其他的反射之類的各位自行去解決
package vip.wulang.test;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
/**
* @author coolerwu on 2018/8/13.
* @version 1.0
* @time 20:58
*/
public class ParentTest {
class GrandFather {
public void thinking() {
System.out.println("i am grandfather.");
}
}
class Father extends GrandFather {
@Override
public void thinking() {
System.out.println("i am father.");
}
}
class Son extends Father {
@Override
public void thinking() {
MethodType methodType = MethodType.methodType(void.class);
try {
Constructor<MethodHandles.Lookup> constructor =
MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);
constructor.setAccessible(true);
MethodHandles.Lookup instance = constructor.newInstance(GrandFather.class, -1);
MethodHandle methodHandle =
instance.findSpecial(
GrandFather.class, "thinking", methodType, GrandFather.class);
methodHandle.invoke(this);
} catch (Exception e) {
e.printStackTrace();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
public static void main(String[] args) {
new ParentTest().new Son().thinking();
}
}
//輸出結果
//i am grandfather.
是不是很神奇
其中MethodType.methodType();第一個參數是返回類型,後面的爲參數類型。MethodHandles.Lookup中的構造方法我需要
的是private Lookup(Class<?> lookupClass, int allowedModes)所以我利用了反射來獲取到實例,也可以通過反射
獲取這個static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED);都是一樣的,主要是因爲在
Lookup類中TRUSTED代表可信任的,可以訪問任何方法,TRUSTED值爲-1,而instance.findSpecial意思就是去這個類尋
找帶有thinking名字的並且參數類型以及方法類型一樣的,最後invoke
這種方法模式使用了invokedynamic指令,使其具有動態語言的特性,用空可以去看看《深入理解Java虛擬機》這本書,可以參悟很多!!!