Java Lambda 类型推断详解:filter() 方法与 Predicate<? super T>

一、问题核心解析

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> 的含义

  • 下界通配符 :表示接受 TT 的父类型

  • 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 的父类
相关推荐
Beyond_System|系统之外29 分钟前
【学编程】Python基础编程题100道(21-60)
开发语言·python·算法
景熙55231 小时前
15.Java 8 Stream 流入门到实战
java·开发语言·数据结构
wno7041 小时前
Spring Security权限控制
java·python·spring
杨运交2 小时前
[071][验证码模块]基于Spring拦截器的验证码认证设计思想
java·后端·spring
Geek-Chow2 小时前
CountDownLatch in Java
java
SL_staff3 小时前
从RBAC到场景化授权:《无忧·企业文档》三级权限模型的技术实践解析
java·开源·产品
传奇开心果编程3 小时前
【springboot基础语法学与练】第 1 课:从零开始
java·spring boot·后端·学习
SL_staff3 小时前
财务系统慎用低代码?从数据模型闭环看合规落地的技术实践
java·低代码·全栈
Bruce_Liuxiaowei4 小时前
Python 实例赋值遮蔽类属性:一个从不报错的静默陷阱
开发语言·python·语法糖
滕州市燕猫虎计算机科技工作室个体工商户4 小时前
IDEA:Command line is too long
java·ide·intellij-idea