2016-10-22 14 views
0

如果我喜歡寫東西def l = [1, 2, 3] as Socket這顯然是無稽之談,我得到這個:Groovy的高清L = [1,2,3]的BlockingQueue

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效果很好,儘管事實上,這兩個ListBlockingQueue是接口產生的ArrayList一個regualr實例。
  • 二,後Dónal's的答案,我試過如下:

    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) 
    

    所以斷言不知何故成功,但嘗試使用l作爲BlockingQueue引發異常。

  • 第三,同樣的情況,如果我嘗試def l = [1, 2, 3] as Map 此代碼:

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

    不產生錯誤和打印:

    [1, 2, 3] 
    class ArrayList1_groovyProxy 
    

回答

1

這只是Groovy的是可愛。它能夠看到你正在嘗試創建一個集合,但它無法弄清楚如何構建一個BlockingQueue。它正在回落到一個代理ArrayList。如果你在左邊輸入了一個類型聲明而不是「def」,它就會被炸燬。再一次,它變得可愛,因爲你正在使用def。討厭,不是嗎? :)

+0

這種「可愛」有多常見?安靜地失敗會導致骯髒,難以發現錯誤。 – Malt

0

爲什麼我能夠將列表轉換爲BlockingQueue而不出錯,儘管它失敗(l最終不是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

+1

甚至更​​多通過使用'@ TypeChecked'或'@ CompileStatic'' – cjstehno

+0

'l'不是一個阻塞隊列,因爲A)類名是'ArrayList1_groovyProxy' B)'l.offer(5)'拋出'Groovy。 lang.MissingMethodException:'。斷言不會失敗的事實只會使這種行爲變得陌生。另外,我欣賞靜態打字技巧。 – Malt

+0

它_definitely_是一個'BlockingQueue',如果不是,那麼斷言和對'BlockingQueue'類型變量的賦值將會失敗。 –

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(),你不能,因爲你不能有一個接口的實例。這就是爲什麼你不能將一個對象作爲接口的原因。

+0

'List ='雖然'List'也是一個接口,但是'def l = [1,2,3]'正常工作。我得到'class java.util.ArrayList'和'[1,2,3]' – Malt

+0

@Malt I ...我不知道你的意思是「正常工作」。這仍然是無效的,你不能實例化接口,嘗試'新的List()'或'新的BlockingQueue()'。你不能,作爲一個接口定義*合約*。您不能在最初不受合同約束的預先存在的實體上履行新合同。 –

+0

我很清楚具體類和接口之間的區別。然而,儘管'List'是一個接口,'def l = [1,2,3]'作爲List'的語句產生了一個工作的'ArrayList',沒有錯誤。當我嘗試'def l = [1,2,3]作爲BlockingQueue'時,我期望得到一個'LinkedBlockingQueue'或其他實現的實例。相反,我有些奇怪。 – Malt