鉴于:
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));
}
}
涉及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))
编译器错误可以通过提供显式类型参数
Java8何时需要显式类型参数?也就是说,是否有一种已知的模式打破了类型推断
更新:
还有另一种方法可以解决这个问题。您可以给编译器一个提示,明确指定标识lambda的参数类型:
ImmutableMap<String, Integer> map2 = Stream.of("1", "2", "3")
.collect(Testcase.toImmutableMap((String i) -> i, Integer::valueOf).build());
在Javac 1.8.0_25和ECJ 3.10.2中编译精细。
lambda表达式的目标类型完全根据上下文确定,如Java教程中所述。因此,lambdas不有助于类型参数推断;相反,它们依赖于它。方法引用是紧凑的、易于阅读的lambda表达式,用于已经有名称的方法(OracleJava教程;强调是添加的),所以当涉及到类型分析时,没有区别。
当您将lambda/方法引用分配给变量时,该变量的类型提供了推断类型参数的上下文。然而,当您将它们直接传递给泛型方法时,您需要一些其他机制来推断它们的类型。在某些情况下,该方法的其他参数可能有助于实现这一目的。在您的特定情况下,您可能需要显式类型参数:
ImmutableMap<String, Integer> map2 = Stream.of("1", "2", "3").collect(
Testcase.<String, String, Integer>toImmutableMap(i -> i, Integer::valueOf).build());
使现代化
关于更新后的问题,Java似乎可以在map3
案例中正确推断类型,部分原因是调用MapCollectorBuilder并不复杂。build()
方法。在没有build()
的情况下,map3
的类型提供了确定流的第一个类型参数的上下文。collect()
,它同时给出K
和V
。类型参数T
可以从流的(推断)类型推断出来。
然而,由于涉及到
build()
,我认为Java正在将推断泛型方法toImmutableMap()
的类型参数的问题与调用其返回值的build()
的返回值的类型问题分离开来。换句话说,它希望在考虑通过对值调用方法获得的值的类型之前,先确定toImmutableMap()
返回的对象的类型。
回答你的问题“意思是,有没有已知的模式打破了类型推断?”简而言之:当然,有一种模式,而且对Java编程语言的整个行为有一个巨大的规范。
但是关于类型推断和方法调用类型的章节非常详尽,很难理解。最能说明这一点的是,在发生意外行为的情况下,通常会根据规范对预期行为进行大量讨论。
但对于程序员来说,有一些要点是可以解释和记住的。
有两种方法可以推断类型参数,一种是通过传递给构成表达式的方法或部分的参数,另一种是通过表达式的目标类型,即调用参数的预期类型、分配的变量或返回语句的方法的返回类型。
目标类型可以通过嵌套方法调用传播,如
TargetType x=foo(bar(/*target type can be used*/));
或者是有条件的
TargetType x=condition? foo(/*target type can be used*/): foo(/*target type can be used*/);
但在链式调用的情况下,如
TargetType x=foo(/*target type can NOT be used*/).foo();
现在来看看你们的例子:
ImmutableMap<String, Integer> map1 = Stream.of("1", "2", "3").collect( expression );
这里是流。属于(…)
和。collect(…)
是链接的,因此不能使用目标类型来确定调用的
的流类型,但提供给该方法的参数足以推断
流的类型
>
Testcase。toImmutableMap(键映射器、值映射器)。build()。但是,
toImmutableMap
的参数是具有已知确切类型的局部变量,因此类型推断可以使用它们来推断toImmutableMap
的结果类型,并检查其是否符合的预期。build()
Testcase。toImmutableMap(i)-
Testcase。toImmutableMap2(一)-
问题内容: 鉴于: 涉及并编译的语句很好,但是失败: 可以通过提供显式类型参数来解决编译器错误。 Java 8何时需要显式类型参数?意思是,是否存在一种打破类型推断的已知模式? 能和改变,以避免显式类型参数不失使用生成器的配置的收藏家? 更新 : 为什么涉及工作的陈述?它与所涉及的陈述有何不同? 问题答案: 要回答您的问题“意思是,是否存在一种已知的打破类型推断的模式?” 简短地说:当然,有一种模
问题内容: 我对JAX-WS进行了概述,并注意到了(和)的一些引用。 在什么情况下需要?(我认为JSR 109服务器?!) 问题答案: 是使用SUN的参考实现将Web服务作为标准存档部署在非Java EE5 Servlet容器上时所需的专有部署描述符。 Sun的RI 用作servlet上下文事件的侦听器和调度程序servlet。两者都必须在中声明。然后需要该文件为定义Web服务端点,以使其知道必须
问题内容: 我使用类只有很短的时间,编写方法时,我使所有变量都引用了self,例如self.foo。 但是,我在浏览《 wxPython in Action》 一书时发现,“ self”并没有一直使用。例如: 下面的一个确实使用“自我”。 如果我没记错的话,“自我”是指该类的特定实例,那么什么时候没有必要?有一般的经验法则吗? 问题答案: 您用于引用当前实例的属性。 您用于引用父类的方法。 如果仅
谷歌正在通过电子邮件通知Android位置权限的更改: 我们将于2016年10月15日进行更改,这将影响针对API版本21(Android 5.0、Lollipop)或更高版本的应用程序,这些应用程序使用ACCESS_FINE_LOCATION但没有明确具有“android.hardware.location.gps”用途功能。展望未来,这些应用程序将可安装在没有GPS硬件的设备上。在大多数情况下
如题, 在将包含汉字的数据转json存的时候,什么时候需要转unicode存储,什么时候不需要 如下: {"subject":"\u6395\u7268\u51ef\u86c1"} {"subject":"吃饭了没"}