簡體   English   中英

將泛型類型參數標記為Java 8中的功能接口

[英]Mark generic type parameter as functional interface in Java 8

我想將函數的類型參數限制為功能接口。

像這樣的東西:

public static <@FunctionalInterface T extends Function<A, B>> T foo () {
    return a -> bar;
}

這里不允許使用@FunctionalInterface

目的是使得可以返回具有類型參數類型的lambda。 由於T可以是普通類,因此不允許返回lambda。

是否有可能將類型參數限制為功能接口?

正如您在其他問題上已經討論過的那樣,這是不可能的 不僅要注釋類型參數,還要特別是通過lambda表達式實現未知接口。

編譯方法時

public static <@FunctionalInterface T extends Function<A, B>> T foo() {
    return a -> bar;
}

編譯器必須生成能夠返回適當類型的實例的代碼,但它不知道T將是什么,因為這取決於foo()的調用者,但編譯foo()和編譯foo()的調用者之間沒有任何聯系foo() 后者可能在幾年之后發生在我們這個星球的另一邊。

也許你不知道Type Erasure 您的方法foo()只有一個編譯版本,但它必須滿足返回適當類型實例的通用協定。 不知道 T 什么

這在返回現有實例時有效,例如返回集合的元素或作為參數傳遞的值之一。 但是泛型方法無法返回類型參數的新實例。 不使用new ,也不使用lambda表達式。


請注意,如果讓知道類型的調用者執行“up-level”操作,仍然可以使用所需函數的子接口實現。 假設你有一個Generic工廠方法,如:

public static <A,B> Function<A,B> getter(Map<?, ? extends B> map) {
    return a->map.get(a);
}

這段代碼適用於未知類型AB以及Map的未知參數化,因為唯一的約束是方法Map.get接受它的A實例,因為它接受任何東西並返回它做任何類型的B實例? extends B ? extends B將可分配給B

現在,如果你的調用者有一個任意子類型的FunctionX ,例如

interface X extends Function<String, Integer> {}

它可以使用你的工廠方法來生成一個裝飾函數的X實例,如:

Map<String, Integer> map=new HashMap<>();
X x=getter(map)::apply;
x.apply("foo");

這里,在調用者站點上檢查對作為功能接口的 X的約束。

我的仿制葯很弱,但我認為這將是:

public static <T, R> Function<T, R> foo() {
    // ...
}

但是我認為你不能實例化 R ,你必須能夠從T獲得它。 您的代碼不知道R的運行時類型,因此new R()超出范圍。

但是,例如,如果T可以給你R ,就像Map

public static <K, R, T extends Map<K,R>> Function<T, R> makeGetter(K key) {
    return a -> a.get(key);
}

返回一個getter,當使用給定的map調用時,將返回帶有用於創建getter的鍵的條目:

import java.util.function.Function;
import java.util.*;
public class Example {

    public static final void main(String[] args) {
        Map<String,Character> mapLower = new HashMap<String,Character>();
        mapLower.put("alpha", 'a');
        mapLower.put("beta",  'b');

        Map<String,Character> mapUpper = new HashMap<String,Character>();
        mapUpper.put("alpha", 'A');
        mapUpper.put("beta",  'B');

        Function<Map<String, Character>, Character> getAlpha = makeGetter("alpha");

        System.out.println("Lower: " + getAlpha.apply(mapLower));
        System.out.println("Upper: " + getAlpha.apply(mapUpper));
    }

    public static <K, R, T extends Map<K,R>> Function<T, R> makeGetter(K key) {
        return a -> a.get(key);
    }
}

輸出:

Lower: a
Upper: A

我認為類型擦除不會讓你比這更接近,除非使用實例方法和參數化你的包含類。

暫無
暫無

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

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