【问题标题】:Java 7 Diamond Operation in method call方法调用中的 Java 7 钻石操作
【发布时间】:2011-12-26 16:46:14
【问题描述】:

这是讨论的后续问题:

Why doesn't the diamond operator work within a addAll() call in Java 7?

来自 Java 教程,

http://docs.oracle.com/javase/tutorial/java/generics/gentypeinference.html

请注意,菱形通常在方法调用中起作用;但是,为了更清楚起见,建议您主要使用菱形来初始化声明它的变量

所以,我对第一行有点困惑。什么时候菱形在方法调用中起作用?

更多关于钻石运算符如何工作的解释可以在这里找到:

http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#What%20is%20type%20argument%20inference%20for%20constructors?

从此,我尝试了以下方法,效果很好:

假设我有:

private static class Box<T>{
    public Box(T t){}
}
static void f(Box<Integer> box){}

类似以下的调用编译良好:

f(new Box<>(new Integer(10)));

上面f()的方法调用中调用构造函数的类型参数是从构造函数的参数推断出来的(即Integer)。

这就是教程所说的意思

请注意,菱形通常在方法调用中起作用

如果没有,谁能提供一个例子,钻石在方法调用中工作

【问题讨论】:

  • @gurung 这是一个错字。剪切和粘贴的坏情况:(

标签: java java-7 diamond-operator


【解决方案1】:

这就是教程所说的意思

我认为是的,尽管在 &lt;&gt; 运算符方面存在一些问题。

在您的情况下,Box 实例化不是问题,因为可以使用构造函数参数轻松推断类型。尝试将构造函数更改为“不”接收 IntegerT 并查看调用如何失败。

class BadBox<T> {

    private T t;

    public BadBox(){}    

    public void setT(T t) {
        this.t = t;
    }

    static void f(BadBox<Integer> box){}

    public static void main(final String[] args) {
        f(new BadBox<>());  //fails, should have worked ideally
    }    
}

同样,看看这个类:

class Testi<R> {    
    public void doIt(Set<? extends R> sets) {
    }

    public static void main(final String[] args) {
            // works since type inference is now possible
        new Testi<CharSequence>().doIt(new HashSet<>(Arrays.asList("a")));

            // fails; nothing which can help with type inference
        new Testi<CharSequence>().doIt(new HashSet<>();
    }       
}

同样,您的链接问题(关于addAll)中的问题可以通过如下帮助编译器来简单地解决:

List<String> list = new ArrayList<>();
list.add("A");

// works now! use only if you love diamond operator ;)
list.addAll(new ArrayList<>(Arrays.asList(new String[0])));
// or the old-school way
list.addAll(new ArrayList<String>()));

在实现匿名类时,菱形运算符似乎也出现了问题,如下所示:

final String[] strings = { "a", "b", "c" };
Arrays.sort(strings, new Comparator<>() {
    @Override
    public int compare(String o1, String o2) {
        return 0;
    }
});

幸运的是,在这种情况下,编译器非常明确地提到 &lt;&gt; 不能/不会与匿名类一起使用。

【讨论】:

    【解决方案2】:

    我认为不值得考虑什么时候有效,什么时候无效。编译器会告诉你,因此你必须重写不工作的部分。

    这背后没有真正的理由;更像是开发人员将实际编译器在特定时间实现的当前限制放入规范中,并告诉我们:必须如此。

    Java 8 解除了很多这些限制,而不会死机。例如

    Arrays.asList("foo", "bar").addAll(new ArrayList<>());
    

    使用 Java 8 编译没有任何错误。而且,为什么不呢?

    【讨论】:

      【解决方案3】:

      这与方法调用无关。独立声明

      new Box<>(new Integer(10));
      

      也可以编译。有足够的信息来推断TBox(即从整数参数)

      另一方面,这不会编译

      new ArrayList<>();
      

      没有办法知道需要什么样的列表。

      Collection<String> strings = new ArrayList<>();
      

      这是有效的,因为目标类型 Collection&lt;String&gt; 有助于推理

      【讨论】:

      • new ArrayList&lt;&gt;(); 作为独立语句确实编译。
      猜你喜欢
      • 2011-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-15
      • 1970-01-01
      • 1970-01-01
      • 2016-02-03
      相关资源
      最近更新 更多