2011-11-07 5 views
10

Tをクラス型パラメータと仮定すると、なぜT.classを使用できないのですか?javaの型パラメータのクラス名は?

私はページをダウンロードし、渡されたクラスに従って解析する関数を書いていました。 は、解析のために、私は、その署名である別の関数を使用する:ParseObject::parse(Class<T> classname)

<T> void downloadParse(){ 
    ParseObject obj; 
    obj.parse(T.class); //<--- why compiler error here?? (whereas something like Integer.class is allowed) 
} 
+2

短い答え: '型消去'。 Googleは残りの部分を行うことができます:) – laher

答えて

15

のJavaジェネリックは、type erasureを介して実装されています。コンパイル時間のチェックにのみ使用できます。コンパイル後、オブジェクトは最も低い共通オブジェクトに変更されます。 (この場合はObject.class)。

コンパイルされたバイトコードは、Tが何であるか分かりません。

あなたがクラスにアクセスしたい場合は、あなたが方法を変更する必要があります。

<T> void downloadParse(Class<T> cls){ 
    ParserObject obj; 
    obj.parse(cls); 
} 
+0

TOO QUICK !!ありがとう!!あなたはGoogleの人を打つ:)答え100%を理解していない、Googleより多くなります。私は提案したのと同じことをしました。私はいくつかの関数の周りに 'cls'パラメータを渡し、私の実際のプログラムのクラス変数に格納する必要がありました。 (それを行う上で変だと感じました) –

+1

それは奇妙なことですが、それがそれを行う唯一の方法です。 Javaが一般化されたジェネリックを手に入れることができれば、はるかに簡単に人生を変えることができます。 –

+4

これはあまり意味がありません。同じ効果のために 'Class 'を使うだけです。タイプを強制する必要がある場合にのみ意味があります。 '> void dp(クラス cls)'です。ジェネリック医薬品のための優れたルール:可能な限り避けるようにしてください;) – sfussenegger

2

Erasureはここに悪役です。 Javaのチュートリアルから: - 生型は任意の型引数 なしジェネリッククラスまたはインタフェース名です。例えば

、ボックスは 生型と呼ばれるボックスを入力して翻訳されています。これは、実行時にジェネリッククラスが使用しているオブジェクトの種類を見つけることができないことを意味します。次の操作 ができません: コンパイラはコンパイル時に(typeパラメータEによって表される)は、実際の型引数 に関するすべての情報が削除されるため

public class MyClass<E> { 
    public static void myMethod(Object item) { 
     if (item instanceof E) { //Compiler error 
      ... 
     } 
     E item2 = new E();  //Compiler error 
     E[] iArray = new E[10]; //Compiler error 
     E obj = (E)new Object(); //Unchecked cast warning 
    } 
} 

太字で示した動作は、実行時に無意味です。消去して

、型情報が削除され、すべてがちょうどオブジェクトです:ジェネリック型がインスタンス化されると

、コンパイラは型消去と呼ばれる技術により、これらの 型を変換 - プロセス コンパイラは、型パラメータに関連するすべての情報を削除し、クラスまたはメソッド内に 引数を入力します。タイプ消去により、Java ジェネリックを使用するアプリケーションは、 ジェネリックより前に作成されたJavaライブラリーおよびアプリケーションとのバイナリー互換性を維持します。

次に、コンパイラは、クラス「T」をキャストとして必要な場所に再導入します。 Tはジェネリックの中に「存在しない」ため、クラスTのオブジェクトを作成することはできません。ジェネリックの呼び出しとジェネレータからの呼び出しでは、コンパイラはオブジェクトを「T」クラスにキャストします。

Googleの「java erasure」では、この仕組みの詳細についてはこちらをご覧ください。ウィキペディアはsome examplesを提供します。

2

他の人が言ったように、それは不可能です。しかし、それは議論のない方法であり、voidを返すので、あなたはTと何を期待しますか?

あなたがたまに発生する可能性のある何かが、このさ:

<T> T foo(Class<T> cls) { 
    Object o = ...; 
    return cls.cast(o); 
} 

// usage - perfectly type safe 
String s = foo(String.class); 

さらに、それは例えば、ジェネリック型引数を取得できる場合がありますここに:

class Foo implements Iterable<String> { 
    // snip 
} 

ParameterizedType pt = (ParameterizedType) Foo.class.getGenericInterfaces()[0]; 
System.out.println(pt); // prints java.lang.Iterable<java.lang.String> 

Class<?> at = (Class<?>) pt.getActualTypeArguments()[0]; 
System.out.println(at.getName()); // prints java.lang.String 

しかし、それはまた別の話だ;)

関連する問題