2016-06-28 2 views
1

私はオブジェクトにマップをキャストしようとしたところでコードを書いていました。GroovyのList to MapでClassCastExceptionがスローされたり、ArrayList1_groovyProxyはスローされません。

Map a = object as Map 

私が代わりに

Map a = (Map) object 

を使用することができますし、オブジェクトの型がリストであるが、前者を使用することによって、私は面白いことに遭遇した場合、これはClassCastExceptionをスローとして全体の問題は無関係になります。 オブジェクトがListの場合、つまり、object = []の場合、groovy型の強制変換は、期待したものとは異なる動作をします。

私の期待はClassCastExceptionでしたが、結果として得られるオブジェクトが見つかりました。しかし、このオブジェクトは奇妙に見えます。これはListのインスタンスであり、Mapのインスタンスです。.toString()を使用すると、Map([a,b])ではなくListが出力されます。また、a['c'] = 'c'でマップに値を設定することはできません。これはjava.lang.IllegalArgumentException: argument type mismatchになります。次の出力で

Map a = ['a', 'b'] as Map 

println(a) 
println(a instanceof List) 
println(a instanceof Map) 
println(a.getClass()) 

結果:

[a, b] 
true 
true 
class ArrayList1_groovyProxy 

私はこれArrayList1_groovyProxyが何であるかを見つけるためにGoogleを試みたが、何かを見つけることができませんでした。

私には意味がありません。強制的には、明らかに実際にはそうでないオブジェクトが返され、ちょうどClassCastExceptionを投げるのではなく、壊れているように見えます。

例外をスローしてArrayList1_groovyProxyの使用方法を説明するのではなく、その動作の背後にある理由を誰にも説明できますか?それとも、グルーヴィーのバグですか?

+0

'['a'、 'b']'は 'リスト'です。マップが必要な場合は、 'def map = ['1': 'one'、 '2': 'two']'を定義します。今度は '' map instanceof Map'をアサートしようとしてください。 – Rao

+0

'['a'、 'b']'がリストであることは知っています。それはポイントではなかった。その質問は、 '' ''、 'b' 'としてMap'が '(Map)[' a '、' b ']'のようにClassCastExceptionをスローしない理由でした。結果として生じるオブジェクトはかなり使用できないように思われるからです。 – alexanderfranke

+0

わかりませんが、定義中に 'as Map'と言って強制しています。あなたは 'Map a = ['a'、 'b']' – Rao

答えて

2

asoperatorは、メソッドへの引数として提供されるタイプでasTypeメソッドを呼び出します。

asTypeのデフォルト実装はDefaultGroovyMethodsです。

Mapはインターフェイスなので、最終的にはProxyGenerator.INSTANCE.instantiateDelegate(interfaces, obj)が呼び出され、Mapを実装する動的プロキシが返されます。

/** 
* Converts a given object to a type. This method is used through 
* the "as" operator and is overloadable as any other operator. 
* 
* @param obj the object to convert 
* @param type the goal type 
* @return the resulting object 
* @since 1.0 
*/ 
@SuppressWarnings("unchecked") 
public static <T> T asType(Object obj, Class<T> type) { 
    if (String.class == type) { 
     return (T) InvokerHelper.toString(obj); 
    } 

    // fall back to cast 
    try { 
     return (T) DefaultTypeTransformation.castToType(obj, type); 
    } 
    catch (GroovyCastException e) { 
     MetaClass mc = InvokerHelper.getMetaClass(obj); 
     if (mc instanceof ExpandoMetaClass) { 
      ExpandoMetaClass emc = (ExpandoMetaClass) mc; 
      Object mixedIn = emc.castToMixedType(obj, type); 
      if (mixedIn != null) 
       return (T) mixedIn; 
     } 
     if (type.isInterface()) { 
      try { 
       List<Class> interfaces = new ArrayList<Class>(); 
       interfaces.add(type); 
       return (T) ProxyGenerator.INSTANCE.instantiateDelegate(interfaces, obj); 
      } catch (GroovyRuntimeException cause) { 
       // ignore 
      } 
     } 
     throw e; 
    } 

なぜGroovyがタイプを強要するのかについては、基本的にGroovyの性質です.Javaコーディングがより簡単になります。オブジェクトはpassing a Map to its constructor、さらにはcoerce a Map instance to a particular typeで構築できます。だから、なぜすべてのオブジェクトを演算子を介してMapに強制的に戻さないようにしますか?

+0

ありがとうございました。プロキシクラスについて説明します。それはその後、通常の地図操作をサポートしていない場合はそれも、それを返しますなぜ はまだ説明していません。私はマップがすべてを作成するためにコンストラクタで使用することができるならば、戻ってマップにすべてを強制しても大丈夫であることを同意するだろうが、期待はその後、ちょうどobject.propertiesのようなものを返すことではないでしょうか? – alexanderfranke

関連する問題