当前位置: 首页 > 面试题库 >

Java什么时候需要显式类型参数?

苍和裕
2023-03-14
问题内容

鉴于:

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));
    }
}

涉及map1map3编译的语句很好,但是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))

可以通过提供显式类型参数来解决编译器错误<String, String, Integer>

  1. Java 8何时需要显式类型参数?意思是,是否存在一种打破类型推断的已知模式?
  2. toImmutableMap()MapCollectorBuilder改变,以避免显式类型参数不失使用生成器的配置的收藏家?

更新

  1. 为什么涉及map3工作的陈述?它与所涉及的陈述map2有何不同?

问题答案:

要回答您的问题“意思是,是否存在一种已知的打破类型推断的模式?”
简短地说:当然,有一种模式,而且对于Java编程语言的整个行为都有一个巨大的规范。

但是有关类型推断和方法调用类型的章节确实详尽且难以理解。这可以通过以下事实得到最好的说明:在发生意外行为的情况下,经常会根据规范对预期行为进行大量讨论。

但是对于程序员来说,有些地方是可以解释和记住的。

有两种方法可以通过传递给组成表达式的方法或部分的参数或表达式的 目标类型
(即调用参数的预期类型)来推断类型参数。如果有return语句,则分配该值或方法的返回类型。

目标类型可以通过嵌套方法调用传播,例如

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 );

在这里,Stream.of(…).collect(…)链接在一起的
,因此不能使用目标类型来确定of调用的流类型,但是提供给该方法的参数足以推断类型Stream<String>。该collect方法提供分配给结果的结果map1,因此流类型Stream<String>
目标类型ImmutableMap<String, Integer>都是已知的,并且可用于 表达式 的类型推断。在表达式上:

  • Testcase.toImmutableMap(keyMapper, valueMapper).build()这是一个链式调用,因此目标类型是已知的,build()但不是toImmutableMap。但是,to的参数toImmutableMap是具有已知确切类型的局部变量,因此类型推断可以使用它们来推断的结果类型,toImmutableMap并检查其是否符合预期。.build()

  • Testcase.toImmutableMap(i -> i, Integer::valueOf).build()这又是一个链式调用,但是现在参数i - > i具有不完整的类型,并且缺少目标类型。在i -> i不了解目标类型的情况下猜测类型的尝试失败。

  • Testcase.toImmutableMap2(i -> i, Integer::valueOf)不是 链式调用,因此目标类型可用于该toImmutableMap2调用(就该collect调用而言,它是一个嵌套调用)。因此,的目标类型toImmutableMap2允许推断参数的目标类型,从而推断i -> ilambdahtml" target="_blank">表达式。使用正确的目标类型,可以推断出正确的功能签名。



 类似资料:
  • 鉴于: 涉及和的语句编译良好,但失败,原因如下: 编译器错误可以通过提供显式类型参数

  • 问题内容: 我对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":"吃饭了没"}