鉴于:
import com.google.common.collect.ImmutableMap;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Stream;
public class Testcase
{
public static <T, K, V> MapCollectorBuilder<T, K, V>
toImmutableMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends V> valueMapper)
{
return null;
}
public static final class MapCollectorBuilder<T, K, V>
{
public Collector<T, ?, ImmutableMap<K, V>> build()
{
return null;
}
}
public static <T, K, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableMap2(
Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends V> valueMapper)
{
return null;
}
public void main(String[] args)
{
Function<String, String> keyMapper = i -> i;
Function<String, Integer> valueMapper = Integer::valueOf;
ImmutableMap<String, Integer> map1 = Stream.of("1", "2", "3")
.collect(Testcase.toImmutableMap(keyMapper, valueMapper).build());
ImmutableMap<String, Integer> map2 = Stream.of("1", "2", "3")
.collect(Testcase.toImmutableMap(i -> i, Integer::valueOf).build());
ImmutableMap<String, Integer> map3 = Stream.of("1", "2", "3")
.collect(Testcase.toImmutableMap2(i -> i, Integer::valueOf));
}
}
Run Code Online (Sandbox Code Playgroud)
涉及map1和map3编译的语句很好,但map2失败了:
Testcase.java:[41,57] incompatible types: cannot infer type-variable(s) T,K,V
(argument mismatch; invalid method reference
no suitable method found for valueOf(java.lang.Object)
method java.lang.Integer.valueOf(java.lang.String) is not applicable
(argument mismatch; java.lang.Object cannot be converted to java.lang.String)
method java.lang.Integer.valueOf(int) is not applicable
(argument mismatch; java.lang.Object cannot be converted to int))
Run Code Online (Sandbox Code Playgroud)
可以通过提供显式类型参数来解决编译器错误<String, String, Integer>.
toImmutableMap()和MapCollectorBuilder改变,以避免显式类型参数不失使用生成器的配置的收藏家?更新:
map3工作?它与涉及的声明map2有何不同?回答你的问题 \xe2\x80\x9c 的意思是,是否有一个已知的模式可以破坏类型推断?\xe2\x80\x9d 很快:当然,有一个模式,而且对于 Java 的整个行为有一个巨大的规范编程语言。
\n\n但是关于类型推断和方法调用类型的章节确实非常详尽且难以理解。最好的说明是,在发生意外行为的情况下,通常会根据规范进行有关预期行为的大量讨论。
\n\n但有一些要点对于程序员来说是可以解释和记住的。
\n\n有两种方法可以推断类型参数:通过传递给组成表达式的方法或部分的参数,或者通过表达式的目标类型,即调用参数的预期类型、变量在 return 语句的情况下,它被分配或方法的返回类型。
\n\n目标类型可以通过嵌套方法调用进行传播,例如
\n\nTargetType x=foo(bar(/*target type can be used*/));\nRun Code Online (Sandbox Code Playgroud)\n\n或者有条件的
\n\nTargetType x=condition? foo(/*target type can be used*/): foo(/*target type can be used*/);\nRun Code Online (Sandbox Code Playgroud)\n\n但在链式调用的情况下则不然
\n\nTargetType x=foo(/*target type can NOT be used*/).foo();\nRun Code Online (Sandbox Code Playgroud)\n\n现在来看你的例子:
\n\nImmutableMap<String, Integer> map1 = Stream.of("1", "2", "3").collect( expression );\nRun Code Online (Sandbox Code Playgroud)\n\n这里,Stream.of(\xe2\x80\xa6)和.collect(\xe2\x80\xa6)是链接的,因此目标类型不能用于确定调用的流类型of,但提供给该方法的参数足以推断类型Stream<String>。该collect方法提供分配给 的结果map1,因此流类型Stream<String>和目标类型ImmutableMap<String, Integer>都是已知的,并且可以用于表达式 的类型推断。到表达式:
Testcase.toImmutableMap(keyMapper, valueMapper).build()这是一个链式调用,因此目标类型已知,build()但不知道toImmutableMap。但是, 的参数是toImmutableMap具有已知确切类型的局部变量,因此类型推断可以使用它们来推断 的结果类型toImmutableMap并检查它是否符合预期.build()
Testcase.toImmutableMap(i -> i, Integer::valueOf).build()这又是一个链式调用,但现在参数的i - > i类型不完整,并且由于缺少目标类型而受到影响。i -> i在不了解目标类型的情况下尝试猜测类型会失败。
Testcase.toImmutableMap2(i -> i, Integer::valueOf)这不是链式调用,因此目标类型可用于调用toImmutableMap2(就collect调用而言,它\xe2\x80\x99是嵌套调用)。因此, 的目标类型toImmutableMap2允许推断参数的目标类型,从而推断i -> ilambda 表达式的目标类型。通过正确的目标类型,可以推断出正确的功能签名。
| 归档时间: |
|
| 查看次数: |
891 次 |
| 最近记录: |