一、问题核心解析
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>() { @Override public 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 的父类