0

マークされた行がコンパイルされないため、次のコードは機能しません。

MyClass {
    //singleton stuff
    private static MyClass instance;
    private MyClass () {}
    public static MyClass getInstance() {
        if(instance==null) {
            instance = new MyClass ();
        }
        return instance;
    }

    // method creating problems
    public NonGenericSuperClassOfGenericClass create(Class<?> c1, Class<?> c2) {
        return new GenericClass<c1,c2>; // DOES NOT COMPILE!!!
    }
}

MyClass をジェネリックにしたくありません。なんで?メソッド create の実際の実装は次のようになるためです。

    // method creating problems
    public NonGenericSuperClassOfGenericClass create(Class<?>... classes) {
        if(someCondition)
             return new GenericClass<classes[0],classes[1]>;
        else
             return new OtherGenericClass<classes[0]>;
}

したがって、MyClass を特定のジェネリックに結合することはできません。渡されたパラメーターを使用して GenericClass をインスタンス化する方法はありますか? どのように?

ありがとう


回答ありがとうございます。私はあなたにすべての話をします。

私はSpringを使用しており、 MongoDBを使用する予定です。

クラス GenericClass は次のようなものです。

 GenericClass<PersistetType1, Long> 

また

 GenericClass<PersistentType2, Long>

ここで、PersistentType1/2 は最終的に DB に格納する必要があるクラスであり、GenericClass は Mongo API にアクセスするための一種のプロキシです。実際には、次のようになります。

  public MongoTemplate getTemplate();
  public void save(T toInsert);
  public List<T> select(Query selectionQuery);
  public T selectById(ID id);
  public WriteResult update(Query selectionQuery, Update updatedAttributes);
  public void delete(T toRemove);
  public void delete(Query selectionQuery);

それで?コントローラ (またはうるさい場合はエンティティ) から、リポジトリをインスタンス化し、任意のメソッドを呼び出す必要があります。これにより、コントローラーは MongoDB と結合されます。つまり、コントローラーは、実際には MongoRepository と呼ばれ、Mongo に厳密に依存する GenericClass を明示的にインスタンス化する必要があります (実際、これは正確に 2 つの「自由度」を持つジェネリックです)。

そこで、コントローラーを分離する別のプロキシである MyClass を作成することにしました。このようにして、Controller は MyClass の単一のインスタンスを取得し、適切なリポジトリの新しいインスタンスを作成できるようにします。特に、「somecondition」が true の場合は、MongoRepository を使用することを意味します (false の場合、Hibernate プロキシ、つまり HibernateRepository をインスタンス化する必要がある可能性があります)。ただし、MongoRepository は汎用であるため、パラメーターとして渡すことを望んでいたインスタンス化の何らかの形式が必要です。

残念ながら、ジェネリックはコンパイル時に解決されるため、私には機能しないと思います。

どうすれば修正できますか?

4

5 に答える 5

6

特にJavaでは意味がありません。

ジェネリックの要点は、コンパイル時に型が何であるかを指定することです。

実行時まで型がわからない場合、Java ジェネリックは型消去のために役に立たなくなります。(C# では、リフレクションが必要になります)

于 2012-06-29T03:01:57.673 に答える
2

Type Erasureにより、最初の実装では rawtypes 実装のみを考慮することができます。

// Similar to original method
@SuppressWarnings("rawtypes")
public Map<?, ?> create(Class<?> c1, Class<?> c2) {
    return new HashMap();
}

よりクリーンな代替手段は次のとおりです。

// A more generic alternative
public <S, T> Map<S, T> create2(Class<? extends S> c1, Class<? extends T> c2) {
    return new HashMap<S, T>();
}

どちらの実装も、実行時にまったく同じことを行います。署名は引数に依存するため、2 番目の方が優れています ( create は a を返しますがMap<?, ?>、2 番目はa を返す場合がありますMap<String, Integer>) 。

于 2012-06-29T11:56:52.693 に答える
1

実行時に Class オブジェクトを渡す必要はありません。ジェネリックは純粋にコンパイル時です。あなたは非ジェネリック型を返しているように見えるので、とにかくジェネリックパラメーターを捨てています(なぜこれを行うのかわかりませんが、そうなので、それで行きます)。パラメータとして何を使用してもかまいません。型チェッカーを通過する任意の型パラメーターで十分です。

public NonGenericSuperClassOfGenericClass create() {
    if(someCondition)
         return new GenericClass<Object,Object>();
    else
         return new OtherGenericClass<Object>();
}
于 2012-06-29T17:48:23.930 に答える
1

頭に浮かぶのは、次のようなものです。

public NonGenericSuperClassOfGenericClass create(Class<?>... classes) {
    if(someCondition)
         return new helper1(classes[0],classes[1]);
    else
         return new helper2(classes[0]);
}

public <R,T> GenericClass<R,T> helper1( Class<R> a, Class<T> b ){
    return new GenericClass<R,T>();
}

public <T> OtherGenericClass<T> helper2( Class<T> a ){
    return new OtherGenericClass<T>();
}
于 2012-06-30T05:47:43.230 に答える