java - 为什么要对 lambda 输入参数执行强制转换?

标签 java generics lambda

我接受由于下限通配符,这个谓词不应该接受 String 的父类(super class)。没有明确的强制转换。[ 1 , 2 ] 这个问题与 lambda 参数列表中的类型安全强制有关。鉴于第二个块编译失败,为什么第一个块可以在没有警告的情况下编译?似乎在第一种情况下,尽管有 lambda 的参数声明,CharSequence正在转换到 String满足谓词的边界约束。

    Predicate<? super String> predicate1 = (CharSequence c)
       -> c.toString().length() > 2 ;
    System.out.println(predicate1.test("foo"));                 // compiles

    Predicate<? super String> predicate2 = (CharSequence c)
       -> c.toString().length() > 2 ;
    System.out.println(predicate2.test((CharSequence)"foo"));  // capture error

error: method test in interface Predicate<T> cannot be applied to given types;
    out.println(predicate2.test((CharSequence)"foo")); 
                          ^
  required: CAP#1
  found: CharSequence
  reason: argument mismatch; CharSequence cannot be converted to CAP#1
  where T is a type-variable:
    T extends Object declared in interface Predicate
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Object super: String from capture of ? super String

感谢您在这方面所做的工作。问题似乎是假设 lambda 和通用进程将强制使用 CharSequence .但是,现在很清楚 String可以在没有编译器错误的情况下提交给 lambda,所以在第一种情况下会发生什么和 String正在提交给两个进程。泛型过程忽略 lambda 的内容也就不足为奇了。

最佳答案

Predicate<? super String> predicate2 = (CharSequence c)
   -> c.toString().length() > 2 ;
System.out.println(predicate2.test((CharSequence)"foo"));  // capture error
问题是predicate2说它会接受 String ;你正试图传递一个 CharSequence .
如果将变量的声明更改为
Predicate<? super CharSequence> predicate2
那么它的工作原理。
这不起作用的原因是您可能正在传递 MyCharSequence implements CharSequence谓词:
System.out.println(predicate2.test((CharSequence)new MyCharSequence()));
这不应该被接受,因为 predicate2 的类型变量表示它应该只期望得到一个 String 的实例。 .编译器只看到实参的类型为CharSequence ,所以它无法区分“这是一个 String”(应该没问题)和“这是一个 MyCharSequence”(应该没问题)。

关于java - 为什么要对 lambda 输入参数执行强制转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62562462/

相关文章:

java - 我的 toString() 仅返回一个对象乘以总对象数

generics - 什么时候在 Swift 中使用类型约束?

java - 转换到 List<SomeType> 发出未经检查的转换警告,而转换到 SomeType 则不会

Java 获取不带扩展的泛型类型

java - 检测lambda是否是方法引用

c++ - 在范围内存在不可复制的局部变量时按值捕获

java - Hibernate级联删除不起作用

java - 如何使用 "Get-wmiObject"监视 Windows Java 进程

java - 使用 HashMap 中的复合键优化许多 LinearGradient 着色器的 onDraw

javascript - 使用 jmespath 通过两个参数查找最小值和最大值