如果我写的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()
答案 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
。