1

私は質問への答えを読んでいます:

Javaでジェネリック型のインスタンスを作成しますか?

Lars Bohl によって提案されたアプローチを実装しました。私は彼のコードを次のように適応させました:

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class ParameterizedTypeEg<E> {
    public Class<E> getTypeParameterClass() {
        Type type = getClass().getGenericSuperclass();
        ParameterizedType paramType = (ParameterizedType) type;
        return (Class<E>) paramType.getActualTypeArguments()[0];
    }
    private static class StringHome extends ParameterizedTypeEg<String> {
        private String _string;
        StringHome (String string) {
            _string = string;
        }
    }
    public static void main(String[] args)
        throws InstantiationException, IllegalAccessException {
        String str = new StringHome("my string").getTypeParameterClass().newInstance();
        String str2 = new ParameterizedTypeEg<String>().getTypeParameterClass().newInstance();
    }
}

このアプローチは、str 変数に対してうまく機能します。次に、str2 は、私には同じタイプに見えるもので作成されます (ParameterizedTypeEg < String >、これは基本的に StringHome と同じものです)。ただし、このアプローチは str2 では機能せず、(ParameterizedType) 型をキャストしようとすると ClassCastException がスローされます。

str2 の場合、ParameterizedTypeEg を String でパラメーター化しましたが、getGenericSuperclass() は str とは非常に異なるものを返します。また、メソッド内で str2 は「this」を ParameterizedTypeEg として示しますが、str の場合、「this」は ParameterizedTypeEg$StringHome です。それが問題の根源だと思います。str2 のジェネリック型が決定されていることを Java が認識しないのはなぜですか?

パラメータ化された型が階層の複数のレベルを通過するときに、同じ問題のように見えるものがありますか? つまり、クラス B< T > には A< T > が含まれており、B をインスタンス化します。A 内では、上記のアプローチを使用して A のパラメーター化された型を決定することによって String オブジェクトを作成することはできません。このアプローチでは、包含階層の場合にも例外が発生します。そして、これは私に問題を引き起こします。これは、パラメーター化された型を複数のレベルの包含および/または継承を介して渡し、同じアプローチですべての場合にジェネリック型のインスタンスを生成できるようにしたいためです。

ありがとう、ジョン

4

4 に答える 4

1

次の変更により、コードが機能します。

から

  String str2 = new ParameterizedTypeEg<String>().getTypeParameterClass().newInstance();

   String str2 = new ParameterizedTypeEg<String>(){}.getTypeParameterClass().newInstance();

これにより、ParameterizedTypeEg の匿名サブクラスが作成されます。電話すると

getClass().getGenericSuperclass();

StringHome では、必要な ParameterizedTypeEg < java.lang.String> を取得します。行ったように str2 を作成すると、その呼び出しは単純に Object を返すため、パラメーター化された型にキャストしようとすると失敗します。

スレッド「メイン」の例外 java.lang.ClassCastException: java.lang.Class は java.lang.reflect.ParameterizedType にキャストできません

匿名サブクラスを作成すると、これは ParameterizedTypeEg < java.lang.String> を返します

これは、Google Guice Guave ライブラリのType Tokenクラスで使用されているのと同じトリックです。たとえば、次のように書きます。

new TypeToken<List<String>>() {}

そしてそうではない

 new TypeToken<List<String>>()  
于 2013-09-01T05:12:58.487 に答える
0

しかし、このアプローチは str2 に対しては機能せず、(ParameterizedType) 型をキャストしようとすると ClassCastException がスローされます
..... なぜ Java は str2 に対してもジェネリック型が決定されていることを認識しないのですか? ?

ParameterizedTypeのOracleドキュメントで指定されているとおり:

ParameterizedType は、次のようなパラメータ化された型を表します Collection<String>

しかし、 のスーパー クラスParameterizedTypeEgは Object であり、Generic Type ではありません。したがって、Type 返される bygetClass().getGenericSuperclass();ClassObject 自体のものです。そして、パラメータ化されていない型の への型キャストは、forParameterizedTypeを提供します。ClassCastExceptionstr

于 2013-09-01T05:14:17.487 に答える
0

getClass().getGenericSuperclass();スーパークラスの詳細を提供します。したがって、パラメータ化されたスーパークラスをサブクラス化する場合にのみ機能します。型パラメーターを指定してパラメーター化されたスーパー クラスをインスタンス化する場合は機能しません。

于 2013-09-01T04:54:37.613 に答える