gpt4 book ai didi

java - Consumer 和 Consumer 似乎不完全等价 - 与任何 Consuming 功能接口(interface)相同

转载 作者:行者123 更新时间:2023-12-01 11:10:13 29 4
gpt4 key购买 nike

我有一个我不理解的 java 编译器错误。看来消费者 和 Consumer< T >(带有 T 扩展对象)在方法签名参数中不等效。请查看以下代码:

import java.util.function.Consumer;

public class MyClass {

public void joker(Consumer<?> fct) {}
public <T> void generic(Consumer<T> fct) {}
public void myConsumer(String s) {}

public void doesNotCompile()
{
joker(this::myConsumer); // COMPILE ERROR : (In Eclipse : ) The type MyClass does not define myConsumer(Object) that is applicable here
generic(this::myConsumer); // Works fine : how come are "T" and "?" not equivalent here ?

// The following also works fine as usual :
Consumer<String> cs = this::myConsumer;
joker(cs);

joker((String s) -> myConsumer(s));
}

}

当我通过命令行而不是在 Eclipse 中编译代码时,错误有点不同:
D:\>javac -Xdiags:verbose MyClass.java
MyClass.java:11: error: method joker in class MyClass cannot be applied to given types;
joker(this::myConsumer);
^
required: Consumer<?>
found: this::myConsumer
reason: argument mismatch; invalid method reference
method myConsumer in class MyClass cannot be applied to given types
required: String
found: Object
reason: argument mismatch; Object cannot be converted to String
1 error

它稍微清楚一点,但我仍然不明白这一点。请注意,java.util.function.Function 会出现模拟错误,而 java.util.function.Supplier 则不会。因此,我相信任何接受参数的功能接口(interface)都会发生错误。

这是编译器错误还是我在这里遗漏了什么?如果是后者(很可能),有人能说出这种行为设计的原因吗?

我觉得类型推断出了点问题。我也几乎不知道 JVM 以不同的方式处理 lambda 和方法引用(AFAIK 通过 MethodHandler)。但老实说,我只是感到困惑。

帮助? ¯\(ツ)/¯

最佳答案

TL;DR; The compiler effectively forbids to pass any value other than null into a Consumer<?>. And thus the usage of Consumer<?> is literally none.



在您的 joker 中试试这个方法:
fct.accept(new Object());

你会看到它不会编译,因为编译器无法确保传递的 Consumer真的可以接受 Object s。但是使用 null有效,因为它是所有 Object 的唯一有效值年代:
fct.accept(null);

您可以通过使用未经检查的强制转换来克服此限制,但它们是 真的气馁,因为你会喜欢遇到 ClassCastException .

请记住 Consumer<Object>不等于 Consumer<?> .先验允许任何 Object传递给它,而后者不接受任何东西! (当然 null 除外)

你的另一个“很好”的例子:
joker((String s) -> myConsumer(s));

但在引擎盖下,你也在使用未经检查的类型转换。您正在隐式转换 s来自 ObjectString .它几乎等同于编写:
joker(s -> myConsumer((String) s));

甚至这个(因为 s 只知道是 Object ):
joker((Object s) -> myConsumer((String) s));

对于您的其他问题,为什么 T?不一样。 T是泛型类型,编译器会尝试将其缩小到最具体的类型。在 generic(this::myConsumer) 的情况下, T将是 String ,如果编译器无法推断类型,它将简单地使用 Object所以它类似于 Consumer<Object> , 但是 不是 Consumer<?>
总而言之,使用 Consumer<?>可能永远不会有一个真正的用例,因为没有任何讨厌的黑客你只能通过 null进去。那有什么用呢?

关于java - Consumer<?> 和 Consumer<T> 似乎不完全等价 - 与任何 Consuming 功能接口(interface)相同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62464841/

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