2017-06-01 32 views
0

出現此錯誤的(方法addUpdatedListener()BaseActivity):爲什麼方法引用不能應用於子類?

Caused by: java.lang.IllegalAccessError: Method 'void com.example.base.activities.BaseActivity.addOnAccountsUpdatedListener()' is inaccessible to class 'com.example.ui.activities.LoginActivity$$Lambda$1' (declaration of 'com.example.ui.activities.LoginActivity$$Lambda$1' appears in /data/app/com.example-1/base.apk:classes9.dex) 

這工作得很好:

public class LoginActivity extends BaseActivity { 
    ... 
Observable.interval(UPDATE_INTERVAL, TimeUnit.SECONDS).onBackpressureDrop() 
       .take(3) 
       .doOnCompleted(new Action0() { 
        @Override 
        public void call() { 
         LoginActivity.this.addUpdatedListener(); 
        } 
       }) 
    ... 
} 

但如果我寫這樣的話,會出現錯誤:

Observable.interval(UPDATE_INTERVAL, TimeUnit.SECONDS).onBackpressureDrop() 
       .take(3) 
       .doOnCompleted(this::addUpdatedListener); 

和像這樣也會發生錯誤:

Observable.interval(UPDATE_INTERVAL, TimeUnit.SECONDS).onBackpressureDrop() 
       .take(3) 
       .doOnCompleted(LoginActivity.this::addUpdatedListener); 

BaseActivity.class

public abstract class BaseActivityextends AppCompatActivity{ 
    protected void addUpdatedListener(){ 
    ... 
    } 
} 
+0

你可以在你的類上運行'javap'嗎?我的猜測是,編譯器在第一種情況下生成額外的代碼,因爲它知道該方法不可訪問,但在第二種情況下不能訪問。 – ngreen

回答

0

我沒有一個Android項目設置,所以我試圖模仿你只用普通的Java代碼做什麼。在第一個例子中,編譯器會生成一個電話,看起來有點像這樣:

INVOKEVIRTUAL LoginActivity.addUpdatedListener()V 

這是非常簡單的,正常通話。編譯器將確保您有權限完成此調用,因此它可能會生成一些額外的代碼以確保一切正常。

在第二種情況下,會發生什麼,但是,是要傳遞的方法引用到INVOKEDYNAMIC呼叫,以及該呼叫裏面發生了什麼部分如下:

// handle kind 0x5 : INVOKEVIRTUAL 
    BaseActivity.addUpdatedListener()V, 
()V 

這裏的問題開始變得更清楚:執行動態指令的代碼無法訪問此方法,因爲它是protected。編譯器無法解決權限問題,因爲它無法知道方法引用何時被調用的完整上下文。如果您要覆蓋受保護的方法並將其公開,應該可以解決您的問題。你也可以公開基礎方法。除此之外,我不確定你將如何使它工作。

相關問題