簡體   English   中英

泛型,類型擦除和靜態織物方法

[英]Generics, type erasure and static fabric method

例如,我有SimpleCallback類

public class SimpleCallback<T> implements Callback<T> {

    private SuccessListener<T> successListener;
    private ErrorListener errorListener;

    protected SimpleCallback() {

    }

    public static <C> SimpleCallback<C> success(SuccessListener<C> listener) {
        SimpleCallback<C> callback = new SimpleCallback<>();
        callback.successListener = listener;
        return callback;
    }

    public SimpleCallback<T> error(ErrorListener errorListener) {
        this.errorListener = errorListener;
        return this;
    }

    @Override
    public void onComplete(T result) {
        notifySuccess(result);
    }

    @Override
    public void onError() {
        notifyError();
    }

    public interface SuccessListener<T> {

        void onSuccess(T result);
    }

    public interface ErrorListener {

        void onError();
    }

}

現在我想使用這個回調讓get cats異步:

SimpleCallback<List<Cat>> callback = SimpleCallback
            .success(cats -> cats.forEach(Cat::meow));

現在沒關系,但是當我想添加錯誤監聽器時,我的貓會成為原始對象

SimpleCallback<List<Cat>> callback = SimpleCallback
            .success(cats -> cats.forEach(Cat::meow)) <-- Here cats become objects
            .error(() -> System.out.println("Cats error"));

解決方案之一使用顯式泛型類型:

SimpleCallback<List<Cat>> callback = SimpleCallback.<List<Cat>>
            .success(cats -> cats.forEach(Cat::meow))
            .error(() -> System.out.println("Cats error"));

但它看起來有點難看。 那么在沒有顯式泛型類型的情況下創建回調的方法是什么?

UPD:我認為@Jesper提供了很好的解決方案

另一個解決方案是顯式提供lambda表達式的參數類型:

.success((List<Cat> cats) -> cats.forEach(Cat::meow))

顯然,擦除泛型類型變量的策略隨上下文而變化。 當然必須有規則如何運作,但我不知道他們,對不起。

從實際的角度來看,Jesper提出的解決方案,即在成功方法中提供類型信息似乎完全可以接受。

.success((List<Cat> cats) -> cats.forEach(Cat::meow))

否則,可以在一個方法中傳遞兩個Listeners:

public static <C> SimpleCallback<C> create(
    SuccessListener<C> successListener, ErrorListener errorListener) {
    SimpleCallback<C> callback = new SimpleCallback<>();
    callback.successListener = successListener;
    callback.errorListener = errorListener;

    return callback;
}

並在一個步驟中創建回調:

Callback<List<Cat>> callback = SimpleCallback
        .create(
            cats -> cats.forEach(Cat::meow),
            () -> System.out.println("Cats error")
         );

簡而言之,沒有。 這個關於菱形運算符如何在Java 1.8中起作用的答案 ,任何鏈式方法調用都存在類型推斷問題。 你的例子很相似,因為

SimpleCallback<List<Cat>> callback = SimpleCallback
        .success(cats -> cats.forEach(Cat::meow));

success的論證中推斷出C型。

因此,您的選擇是:

  • 明確聲明泛型類型
  • 在使用鏈式調用之前獲取命名引用(使用顯式聲明的泛型類型)

對於您的示例,我更願意使用以下范例:

公共類SimpleCallback實現Callback {

private SuccessListener<T> successListener;
private ErrorListener errorListener;

protected SimpleCallback() {

}

public static <C> SimpleCallback<C> create() {
    return new SimpleCallback<>();
}

public SimpleCallback<T> withSuccessListener(SuccessListener<T> listener) {
    this.successListener = listener;
    return this;
}

public SimpleCallback<T> withErrorListener(ErrorListener errorListener) {
    this.errorListener = errorListener;
    return this;
}

@Override
public void onComplete(T result) {
    notifySuccess(result);
}

@Override
public void onError() {
    notifyError();
}

public interface SuccessListener<T> {

    void onSuccess(T result);
}

public interface ErrorListener {

    void onError();
}

}

然后創建一行,添加並鏈接下一行。

SimpleCallback<List<Cat>> callback = SimpleCallback.create();
callback = callback.success(cats -> cats.forEach(Cat::meow))
                   .error(() -> System.out.println("Cats error"));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM