[英]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);
}
這段代碼適用於未知類型A
和B
以及Map
的未知參數化,因為唯一的約束是方法Map.get
接受它的A
實例,因為它接受任何東西並返回它做任何類型的B
實例? extends B
? extends B
將可分配給B
現在,如果你的調用者有一個任意子類型的Function
, X
,例如
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.