Groovy def l = [1,2,3]作为BlockingQueue

时间:2016-10-22 18:14:46

标签: groovy

如果我写的def l = [1, 2, 3] as Socket之类的东西显然是胡说八道,我就明白了:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '[1, 2, 3]' with class 'java.util.ArrayList' to class 'java.net.Socket' 

这是有道理的。

现在我尝试一些不那么冒险的事情:

import java.util.concurrent.BlockingQueue

def l = [1, 2, 3] as BlockingQueue
println l.class
println l

这不会抛出异常,并打印以下内容:

class ArrayList1_groovyProxy
[1, 2, 3]

那么ArrayList1_groovyProxy是什么,为什么我能够在没有错误的情况下将列表转换为BlockingQueue,尽管它失败了(l并未结束成为BlockingQueue实例)?

编辑:

  • 首先,我想指出def l = [1, 2, 3] as List效果很好,并生成ArrayList的regualr实例,尽管List和{{1}是接口。
  • 其次,在Dónal's回答后,我尝试了以下内容:

    BlockingQueue

    这打印了以下行,没有抛出断言异常

    def l = [1, 2, 3] as BlockingQueue
    assert l instanceof BlockingQueue
    println l.class
    println l
    

    但是,这一行确实抛出class ArrayList1_groovyProxy [1, 2, 3]

    MissingMethodException

    因此断言以某种方式成功,但尝试使用l.offer(5) 作为BlockingQueue会引发异常。

  • 第三,如果我尝试l,也会发生同样的情况 这段代码:

    def l = [1, 2, 3] as Map

    不会产生错误并打印出来:

    def l = [1, 2, 3] as Map
    assert l instanceof Map
    println l
    println l.getClass()
    

3 个答案:

答案 0 :(得分:1)

只是Groovy很可爱。它能够看到您正在尝试创建一个集合,但它无法弄清楚如何构建一个BlockingQueue。它回落到代理的ArrayList。如果您在左侧使用类型声明而不是" def,"它会爆炸。再一次,因为你正在使用def,它变得可爱。烦人,不是吗? :)

答案 1 :(得分:1)

使用x as y 投射,它是强制(见Section 8.7 of the Groovy Manual)。

施放时,强制不会检查类型安全性。

此外,BlockingQueue是一个界面。我不确定你为什么要把一个对象作为一个接口。

尝试运行:

import java.util.concurrent.LinkedBlockingQueue 
LinkedBlockingQueue l = [1, 2, 3] as LinkedBlockingQueue
println(l instanceof LinkedBlockingQueue)
println(l.class)
println(l.metaClass.methods*.name.sort().unique())
​

你得到:

true
class java.util.concurrent.LinkedBlockingQueue
[add, addAll, clear, contains, containsAll, drainTo, element, equals, getClass, hashCode, isEmpty, iterator, notify, notifyAll, offer, peek, poll, put, remainingCapacity, remove, removeAll, retainAll, size, take, toArray, toString, wait]

你不能拥有一个界面实例,所以它不知道你要求它做什么。例如,尝试运行new BlockingQueue(),你不能,因为你不能拥有一个接口的实例。这就是您无法将Object转换为接口的原因。

答案 2 :(得分:0)

  

为什么我能够在没有错误的情况下将列表转换为BlockingQueue,尽管它失败了(我不会最终成为BlockingQueue实例)?

为什么您确定l不是BlockingQueue个实例?以下(您可以在Groovy控制台中运行)表明 BlockingQueue实例:

import java.util.concurrent.BlockingQueue

// this assignment would be impossible if l is not a BlockingQueue
BlockingQueue l = [1, 2, 3] as BlockingQueue

// this assertion would throw an exception if l is not a BlockingQueue
assert l instanceof BlockingQueue

仅供参考,您可以通过定义变量的类型来消除类型的大量不确定性,而不是使用def