Mar*_*cca 8 java generics type-inference
有没有办法告诉 Java 不要尝试从使用原始类型的方法引用推断类型?
这是我写的一个方法,这个原因现在无关紧要:
public static <F, T> Predicate<F> isEquals(
Function<F, T> aInMapFunction, T aInExpectedValue)
{
return aInActual -> Objects.equals(
aInMapFunction.apply(aInActual), aInExpectedValue);
}
Run Code Online (Sandbox Code Playgroud)
现在,如果您将方法引用传递给返回原始类型的“isEquals”会怎样?
Predicate<String> lLengthIs20 = isEquals(String::length, 20);
Run Code Online (Sandbox Code Playgroud)
这一切都很好,只是 Java 也会接受这种奇怪的用法:
Predicate<String> lLengthIs20 = isEquals(String::length, "what the heck?!?!?");
Run Code Online (Sandbox Code Playgroud)
这是因为编译器会将类型参数 T 推断为“ Serializable & Comparable<? extends Serializable & Comparable<?>>”,它将接受 Integer 和 String 类型。
在我的情况下,这是不可取的,因为我想要一个编译错误而不是 Java 找出一些疯狂的类型参数。就我而言,我还可以显式覆盖方法“isEquals”以采用特定的原始类型。例如:
public static <F> Predicate<F> isEquals(
ToIntFunction<F> aInMapFunction, int aInExpectedValue)
{
return aInActual ->
aInMapFunction.applyAsInt(aInActual) == aInExpectedValue;
}
Run Code Online (Sandbox Code Playgroud)
这工作正常,当我传入一个返回原始 int 的方法时,将调用此方法而不是 Object 方法。问题是我仍然需要 Object 方法,我无法删除它,这仍然会导致编译器接受我上面列出的奇怪调用。
所以问题是:当方法引用返回原始类型时,有没有办法告诉 Java 不要使用 isEquals 的对象版本?我找不到任何东西,我觉得我在这方面运气不佳。
(注意: isEquals 的对象版本的实际实现工作正常并且应该是安全的。这是因为 Object.equals 和 Object s .equals 接受 Object 参数,并且 String 对象永远不会等于 Integer 对象。然而,在语义上,这看起来很奇怪)
编辑:在“paranoidAndroid”发表评论之后,我的一个想法是按以下方式包装方法引用:
public static <T> Function<T, Integer> wrap(ToIntFunction<T> aInFunction)
{
return aInFunction::applyAsInt;
}
Run Code Online (Sandbox Code Playgroud)
现在,
Predicate<String> lLengthIs20 = isEquals(wrap(String::length), "what the heck?!?!?");
Run Code Online (Sandbox Code Playgroud)
... 产生编译错误。仍然不是很好,也许有更好的方法。至少这比显式传递类型要好,后者优于目的。
编辑 2:我现在在 Java 8 中。Java 11 在这里可能会有不同的表现,我没有测试。
编辑 3:我认为我们在这里无能为力,这只是对 Java 中类型推断如何工作的暗示。这是另一个例子:
public static <T> boolean isEquals(T t1, T t2) {
return Objects.equals(t1, t2);
}
Run Code Online (Sandbox Code Playgroud)
使用此方法,以下表达式完全有效:
System.out.println(isEquals(10, "20"));
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为 Java 将尝试根据公共上限来解析 T 的类型。碰巧 Integer 和 String 共享相同的上限Serializable & Comparable<? extends Serializable & Comparable<?>>
\n\n\xe2\x80\x9e \xe2\x80\xa6有没有办法让我告诉Java不要使用对象版本\xe2\x80\xa6 \xe2\x80\x9c
\n
是的。泛型 \xe2\x80\x94中用于告诉 Java 不要使用的术语 \xe2\x80\x94Object称为: \xe2\x80\ x9e\xe2\x80\x9c。
我的实验证实,调用以下方法isEquals(String::hashCode, "What the theoretical fuck!&?*!?@!")将产生error: no suitable method found for isEquals(String::hashCode,String)......
public static <F extends String, T extends Number> Predicate<F> isEquals(Function<F, T> aFunction, T aValue)\n{\n return input -> Objects.equals(aFunction.apply(input), aValue);\n} \nRun Code Online (Sandbox Code Playgroud)\n如果您在同一个类中同时拥有上述方法和以下方法,则调用此版本isEquals(String::length, 20)...
public static <F> Predicate<F> isEquals(ToIntFunction<F> aFunction, int aValue)\n{\n return input -> aFunction.applyAsInt(input) == aValue;\n}\nRun Code Online (Sandbox Code Playgroud)\n...但是需要第一个isEquals(String::length, Integer.valueOf(42))。
单击此演示中的蓝色“执行”按钮以查看其工作情况。
\n| 归档时间: |
|
| 查看次数: |
304 次 |
| 最近记录: |