如何使用方法引用作为将来的回调?

时间:2019-01-17 05:49:11

标签: java generics netty

当我尝试使用类似的东西

class Example {
    ...

    private Future<String> asyncMethod() {
        ...
        return somePromise;
    }

    private static void callback(Future<String> future) {
        System.out.println(future.getNow());
    }

    public static void main(String[] args) {
        asyncMethod().addListener(Example::callback);
    }
}

我遇到错误

Example.java:[17,34] incompatible types: invalid method reference
   incompatible types: io.netty.util.concurrent.Future<capture#1 of ? super java.lang.String>
   cannot be converted to io.netty.util.concurrent.Future<java.lang.String>

使用匿名类作为侦听器没有错误

asyncMethod().addListener(new GenericFutureListener<Future<String>>() {
    @Override
    public void operationComplete(Future<String> future) throws Exception {
        System.out.println(future.getNow());
    }
});

但这很丑陋和冗长:(我该怎么做才能以最优雅的方式解决这个问题?

2 个答案:

答案 0 :(得分:1)

您可以转换方法参考

asyncMethod().addListener((GenericFutureListener<Future<String>>) Example::callback);

它不那么冗长,但仍然不够完美。为了稍微改善此解决方案,您可以将长类型定义移至功能接口

class Example {
    @FunctionalInterface
    private interface Callback extends GenericFutureListener<Future<String>> {
        void operationComplete(Future<String> future) throws Exception;
    }

    private static void callback(Future<String> future) {
        System.out.println(future.getNow());
    }

    public static void main(String[] args) {
        asyncMethod().addListener((Callback) Example::callback);
    }
}

或者您可以使用键入的参数将回调包装到lambda

asyncMethod().addListener((Future<String> f) -> callback(f));

IDK,也许可以做得更好。

答案 1 :(得分:0)

您可以选择以下选项之一:

  1. 使用lambda (比完整的匿名类短,但仍不是最佳选择):

final StorageReference storRef = storageReference.child("profilePicture/"+ UUID.randomUUID().toString()); storRef.putFile(userProfileUri) .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { storRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() { @Override public void onSuccess(Uri uri) { //Log.d(TAG,"user profile url is: "+uri.toString()); saveEmailToFirebase(uri.toString()); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Log.d(TAG,"on download porfileuri failed"+e.getMessage()); Toast.makeText(LoginActivity.this, "profile picture uploading failed "+e.getMessage(), Toast.LENGTH_SHORT).show(); } }); } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Toast.makeText(LoginActivity.this, "profile picture uploading failed "+e.getMessage(), Toast.LENGTH_SHORT).show(); } }) .addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() { @Override public void onProgress(UploadTask.TaskSnapshot taskSnapshot) { double progress = (100.0*taskSnapshot.getBytesTransferred()/taskSnapshot .getTotalByteCount()); Log.d(TAG,"File uploading "+(int)progress+"%"); } }); }else { Toast.makeText(LoginActivity.this,"Please select Profile picture",Toast.LENGTH_SHORT).show(); }

  1. 将回调参数固定为:

asyncMethod().addListener((GenericFutureListener<Future<String>>) future -> Application.callback(future))

从简单的private static void callback(Future<? super String> future) {开始,您也可以通过这种方式使用回调。

注意:如果您对Future<String> future泛型问题感到困惑,出于同样的原因,我在this SO post上加了书签。