gpt4 book ai didi

java - 引用类型中的有界通配符

转载 作者:塔克拉玛干 更新时间:2023-11-01 22:19:11 24 4
gpt4 key购买 nike

我无法理解以下有关两个 Predicate 对象的代码。第一个使用下界通配符,第二个使用上限。

Predicate<? super String> p1 = s -> s.startsWith("a"); // why can I call startsWith()?
Predicate<? extends String> p2 = s -> s.startsWith("a");

p1.test("a"); // works
p2.test("a"); // doesn't work (why?)

关于 p1 我不明白的是,为什么可以调用 String 类的方法,例如startsWith()?为什么我只能将 String 对象传递给 p1.test(),我希望能够为 NumberObject 调用它 对象也是如此。

作为 p1 的行为,我认为 p2 会,但事实并非如此。我什至无法将 String 对象传递给 p2.test()。这对我来说没有意义,因为我们期望一个对象继承自 String(包括 String)。

我认为这可能与我们指定引用类型而不是对象本身的类型这一事实有关。但是对象使用什么类型呢?

最佳答案

您调用startsWith是合法的对于 p1 , 即使 p1用下界键入 ? super String ,因为类型参数被推断为 String . lambda 表达式 s -> s.startsWith("a");被推断为 Predicate<String> , 分配给 Predicate<? super String> 类型的变量是合法的.

编译:

Predicate<String> ps = s -> s.startsWith("a");
Predicate<? super String> p1 = ps;

这不是:

// no "startsWith" on Object
Predicate<? super String> p1 = (Object s) -> s.startsWith("a");

JLS 引用在 Section 15.27.3 中, “Lambda 表达式的类型”。

If T is a wildcard-parameterized functional interface type and the lambda expression is implicitly typed, then the ground target type is the non-wildcard parameterization (§9.9) of T.

这里,ground target type 是 lambda 表达式的类型,T是目标类型,这是您的下限变量数据类型。这允许编译器分配 Predicate<String>作为地面目标类型,成为 lambda 表达式的类型。

另请注意,您不能将父类(super class)对象传递给 p1.test ,因为您可以(并且已经)分配了一个 Predicate<String>p1 ,它需要一个 String .

p1.test(new Object()); // Error: can't pass something higher than String

至于为什么不能传一个Stringp2.test , 当你有一个上限通配符时,例如 ? extends String ,这意味着类型参数可以是任何类 String或子类型。 (编译器忽略 String 在这里是 final 并且不能有任何 String 的子类。)谓词 p2可以分配一个 Predicate<SillyString> ,假设 SillyStringString 的子类.但是你不能传递 String到一个可以期待 SillyString 的方法.

关于java - 引用类型中的有界通配符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58294604/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com