gpt4 book ai didi

java - 使用通用供应商和 lambda 进行类型检查

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:12:08 25 4
gpt4 key购买 nike

我有两个通用方法,旨在强制调用者提供与类型匹配的参数:

private <T> void compareValues(Supplier<T> supplier, T value) {
System.out.println(supplier.get() == value);
}

private <T> void setValue(Consumer<T> consumer, T value) {
consumer.accept(value);
}

但是,在调用它们时,编译器对允许作为参数传递的内容有不同的推理:

compareValues(this::getString, "Foo"); // Valid, as expected
compareValues(this::getInt, "Foo"); // Valid, but compiler should raise error
compareValues(this::getString, 1); // Valid, but compiler should raise error

setValue(this::setString, "Foo"); // Valid, as expected
setValue(this::setInt, "Foo"); // Type mismatch, as expected
setValue(this::setString, 1); // Type mismatch, as expected


private String getString() {
return "Foo";
}

private int getInt() {
return 1;
}

private void setString(String string) {
}

private void setInt(int integer) {
}

怎么会?编译器是不是太笨拙了,无法正确地推断出这里的类型,或者这是类型系统的一个特性?如果是这样,导致这种行为的规则是什么?此外,如果可能的话,我将如何在不添加人工参数的情况下创建“类型安全”版本的 compareValues?

请注意,提供的方法仅包含虚拟实现,并不反射(reflect)我实际代码库中的代码。此处的重点仅在于方法调用。

最佳答案

其他人已经提到了为什么会发生这种情况,所以这里有一个解决问题的解决方案。

如果您创建一个泛型类,将供应商的传递与参数的传递分开,您就没有给编译器选择交集类型的机会:

public class Comparer<T>
{
private final Supplier<T> supplier;

Comparer(final Supplier<T> supplier)
{
this.supplier = supplier;
}

void compare(T value)
{
System.out.println(supplier.get() == value);
}
}

new Comparer<>(this::getString).compare("Foo"); // Valid, as expected
new Comparer<>(this::getInt).compare("Foo"); // Invalid, compiler error
new Comparer<>(this::getString).compare(1); // Invalid, compiler error

通过分离此行为,您还允许 Comparer 执行可能有用的操作,例如缓存 Supplier.get() 的结果。

关于java - 使用通用供应商和 lambda 进行类型检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50150961/

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