Java接口回調(diào)的本質(zhì)詳解
本質(zhì)是JVM指令invokevirtual它涉及到了多態(tài)的特性,使用 virtual dispatch 做方法調(diào)用
virtual dispatch 機制會首先從 receiver(被調(diào)用方法的對象的實際類型)的類的實現(xiàn)中查找對應的方法,如果沒找到,則去父類查找,直到找到函數(shù)并實現(xiàn)調(diào)用,而不是依賴于引用的類型。
我們知道了接口回調(diào)的本質(zhì)是多態(tài),多態(tài)的本質(zhì)是JVM的invokevirtual指令,那么我們就不用拘泥于接口和抽象類或者繼承關系這種概念了,我們直接寫一個用普通類實現(xiàn)的回調(diào)然后再分析它:
public class TestA{
public void A(){
System.out.println("A");
}
}
public class TestC {
public void C(TestA A){
System.out.println("ccc1");
A.A();
System.out.println("ccc2");
}
}
public class JavaTest {
public static void main(String[] args) {
TestC testC = new TestC();
testC.C(new TestA(){
@Override
public void A() {
System.out.println("fsf");
}
});
}
}執(zhí)行結(jié)果:

如果是invokespecial指令:
public class TestA {
private void A(){
System.out.println("A");
}
}
public class TestC {
public void C(TestA A){
System.out.println("ccc1");
//注意這里不能用 A.getClass,getClass方法也是用invokevirtual指令調(diào)用的
Class aClass = TestA.class;
try {
Method method = aClass.getDeclaredMethod("A");
method.setAccessible(true);
method.invoke(A);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("ccc2");
}
}
public class Test{
public static void main(String[] args) {
TestC testC = new TestC();
testC.C(new TestA(){
private void A() {
System.out.println("fsf");
}
});
}
}JVM在調(diào)用private方法的時候使用的是invokespecial指令,但是我們不能直接在外部調(diào)用私有方法所以就寫了個反射來調(diào)用,執(zhí)行結(jié)果:

如果有因為是不是因為反射導致的,我們排除一下反射:
public class TestA{
public void A() {
System.out.println("A");
}
}
public class TestC {
public void C(TestA A){
System.out.println("ccc1");
Class aClass = TestA.class;
try {
Method method = aClass.getDeclaredMethod("A");
method.setAccessible(true);
method.invoke(A);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("ccc2");
}
}
public class Test{
public static void main(String[] args) {
TestC testC = new TestC();
testC.C(new TestA(){
public void A() {
System.out.println("fsf");
}
});
}
}執(zhí)行結(jié)果:

使用反射和不使用反射的結(jié)果一致可以排除反射的干擾
到此這篇關于Java接口回調(diào)的本質(zhì)詳解的文章就介紹到這了,更多相關Java接口回調(diào)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java?Api實現(xiàn)Elasticsearch的滾動查詢功能
這篇文章主要介紹了Java?Api實現(xiàn)Elasticsearch的滾動查詢,解決ES每次只能查詢一萬條數(shù)據(jù)的問題,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2023-08-08
手寫redis@Cacheable注解?支持過期時間設置方式
這篇文章主要介紹了手寫redis@Cacheable注解?支持過期時間設置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01
SpringBoot整合SpringSecurityOauth2實現(xiàn)鑒權(quán)動態(tài)權(quán)限問題
這篇文章主要介紹了SpringBoot整合SpringSecurityOauth2實現(xiàn)鑒權(quán)-動態(tài)權(quán)限,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-06-06
Java靜態(tài)方法不能調(diào)用非靜態(tài)成員的原因分析
在Java中,靜態(tài)方法是屬于類的方法,而不是屬于對象的方法,它可以通過類名直接調(diào)用,無需創(chuàng)建對象實例,非靜態(tài)成員指的是類的實例變量和實例方法,它們需要通過對象實例才能訪問和調(diào)用,本文小編將和大家一起探討Java靜態(tài)方法為什么不能調(diào)用非靜態(tài)成員2023-10-10

