【问题标题】:Why can't I use the Java 7 diamond syntax with a guava ImmutableSortedMap.Builder为什么我不能将 Java 7 菱形语法与番石榴 ImmutableSortedMap.Builder 一起使用
【发布时间】:2014-12-18 22:14:15
【问题描述】:

我使用的是 java 7,这个 sn-p 不能编译

ImmutableSortedMap<Integer, String> INT_TO_WORD =
       new ImmutableSortedMap.Builder<>(Ordering.natural())
           .put(1, "one")
           .put(2, "two")
           .put(3, "three")
           .build();

而这个是

ImmutableSortedMap<Integer, String> INT_TO_WORD =
       new ImmutableSortedMap.Builder<Integer, String>(Ordering.natural())
           .put(1, "one")
           .put(2, "two")
           .put(3, "three")
           .build();

我在lhs 上指定了类型,为什么还要在rhs 上指定类型? &lt;&gt; 操作符有什么比眼睛看到的更多的东西吗?

【问题讨论】:

  • Java 的类型推断是有限的。它在 Java 8 中有所改进,但仍有一些烦人的怪癖。
  • @JeffreyBosboom 这可以在 Java 8 中使用吗?
  • @nikhil 不。 Java 8 也有同样的问题。

标签: java java-7 guava diamond-operator


【解决方案1】:

这与举例不同

ArrayList<String> l = new ArrayList<>();

这里右侧的 new 正在有效地创建 ArrayList。

在您的示例中,new 正在创建一个完全不同的类型,即Builder,并且只有最后ImmutableSortedMap 是由build() 方法创建的。 编译器无法知道 Builder 与您的 ImmutableSortedMap 有任何关系。

或者用一个愚蠢的例子,这可能是完全有效的:

ArrayList<String> l = new SomethingSilly<Boolean>().getArrayListOfStrings();

【讨论】:

  • 理论上,可以设计 java 来解释 build() 返回的泛型参数与Builder()&lt;A, B&gt; 的泛型参数绑定。如果 Java 可以建立这种联系,那么“愚蠢的例子”将无法编译。但是,Java 没有建立这种联系。
  • 我认为我不同意。该示例的线索是,SomethingSilly 的布尔类型与 getArrayListOfStrings 返回 ArrayList 的事实之间没有任何联系。我可以在这个类中有几个方法,每个方法都返回一个不同的类型列表,它们都不是布尔值。然而该类的类型参数是布尔值。因此,Java 无法推断出SomethingSilly 类的&lt;&gt; 之间的内容。
  • 理论上,如果它被编码为public class SomethingSilly&lt;T&gt; {...public getArrayList() { return new ArrayList()&lt;T&gt; } ... },那么Java 可以被设计成能够进行这种推断。但是我发现我没有足够仔细地查看您的“SomethingSilly”示例,所以是的,您是对的,它仍然可以编译,因为您的 getArrayListOfStrings() 没有绑定到 SomethingSilly 类的通用参数。但是@nikhil 的 Builder.build() 示例与类的通用参数相关联,因此“SomethingSilly”示例不直接类似。
  • 但是由于 Java 目前并没有真正建立这种推理连接,所以我的观点只是理论上的。
【解决方案2】:

正如 Jeffrey 所指出的,Java 的类型推断有一些怪癖。只有在调用要为其分配变量的 Object 类型的构造函数时,才能使用菱形语法代替完整类型语法。

您不能以您尝试的方式使用菱形语法的原因是因为您将它与 builder 对象 的构造函数一起使用,而不是 实际最终对象 strong> 您将变量分配给。

换句话说,这是可行的:

// Assigning directly to new object
ObjectInterface<Integer, String> object = new ObjectImplementation<>()

这不是:

// Assigning to the result of a method off of a different object;
// will fail without generic arguments
ObjectInterface<Integer, String> object = new ObjectInterface.Builder<>().build();

Java 的菱形语法和泛型推理不够健壮,无法确定您在使用构建器做什么,可能是因为这种健壮性难以实现,因为 Java 的泛型推理必须以某种方式知道您的“构建”方法与构建器的通用参数相关联。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-07
    • 1970-01-01
    • 1970-01-01
    • 2016-03-15
    • 2020-04-25
    • 2012-01-15
    • 1970-01-01
    • 2013-11-18
    相关资源
    最近更新 更多