一、問題核心解析
1. 代碼示例分析
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()) .collect(Collectors.toList());
2. Lambda 表達式為什么能傳入
函數式接口本質:Lambda 表達式是函數式接口的實例化簡寫
Predicate<T>
?是函數式接口,只有一個抽象方法:@FunctionalInterface public interface Predicate<T> {boolean test(T t); // 唯一的抽象方法// 其他默認方法... }
Lambda 表達式?
string -> !string.isEmpty()
?等價于:new Predicate<String>() {@Overridepublic boolean test(String string) {return !string.isEmpty();} }
3.?<? super T>
?的含義
下界通配符:表示接受?
T
?或?T
?的父類型在?
filter(Predicate<? super T> predicate)
?中:T
?是流元素的類型(本例中是?String
)? super T
?表示可以接受處理?String
?或其父類(如?Object
,?CharSequence
)的?Predicate
二、類型推斷全流程
1. 類型推斷步驟
2. 詳細推斷過程
步驟 1:流類型確定
strings.stream() // 返回 Stream<String>
編譯器從?
strings
?的類型?List<String>
?推斷出?stream()
?返回?Stream<String>
此時?
T = String
步驟 2:filter 方法簽名匹配
Stream<T> filter(Predicate<? super T> predicate);
// 代入 T=String →
Stream<String> filter(Predicate<? super String> predicate);
步驟 3:Lambda 表達式類型解析
.filter(string -> !string.isEmpty())
目標類型:
Predicate<? super String>
參數類型推斷:
根據目標類型,
string
?必須是?String
?或其父類Lambda 體中使用?
string.isEmpty()
?方法isEmpty()
?是?String
?類的方法(在?CharSequence
?中不存在)因此編譯器推斷?
string
?必須是?String
?類型
步驟 4:返回值類型推斷
Lambda 體?
!string.isEmpty()
?返回?boolean
匹配?
Predicate.test()
?要求的?boolean
?返回類型
步驟 5:完整匹配驗證
// 等效實現
Predicate<String> p = (String s) -> {return !s.isEmpty();
};
filter(p); // 符合 Predicate<? super String>
三、<? super T>
?的設計意義
1. 提高 API 靈活性
// 通用謂詞:處理任何對象
Predicate<Object> nonNull = obj -> obj != null;// 可用于不同類型的流
List<String> strings = ...;
strings.stream().filter(nonNull); // 允許:Object 是 String 的父類List<Integer> numbers = ...;
numbers.stream().filter(nonNull); // 允許:Object 是 Integer 的父類