简体   繁体   中英

Why method reference can't be applied for child class?

This error occurs (method addUpdatedListener() is at 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)

This works fine:

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

But if I write like this, then error occurs:

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

and like this also error occurs:

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

BaseActivity.class :

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

I don't have an Android project set up, so I tried to simulate what you're doing with just normal Java code. In the first example, the compiler will generate a call that looks sort of like this:

INVOKEVIRTUAL LoginActivity.addUpdatedListener ()V

This is pretty straightforward, a normal call. The compiler will ensure that you have permissions to complete this call, so it will probably generate some extra code to make sure everything works.

What happens in the second case, however, is you are passing a method reference to an INVOKEDYNAMIC call, and part of what happens inside that call is as follows:

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

Here the problem starts to become more clear: the code executing the dynamic instruction doesn't have access to this method, because it's protected . The compiler can't work around the permissions problems because it can't know the full context of when the method reference will be invoked. If you were to override the protected method and make it public, that should solve your problem. You could also just make the base method public. Other than that, I'm not sure how you would make it work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM