1

私はジェネリックスにあまり慣れていないので、この問題をどのように解決するかについて、ここで少し混乱しています。実行時にさまざまなメソッドを呼び出そうとするメソッドを作成しました。ClassCastExceptionしかし、コードは構文的に正しいように見えますが、私は取得しています。

私は次のクラスを持っています(簡潔にするためにいくつかのゲッターとセッターは省略されています):

public interface Transporte extends Serializable {
  private int id;
  private String name;
  public abstract int getId() { return this.id; }
  public abstract String getName() { return this.name; }
}
public class Barco implements Transporte { /* ... */ }
public class Estacao implements Transporte { /* ... */ }
public class Paragem implements Transporte { /* ... */ }

public class Entidade extends Serializable {
  private List<Barco> barcos;
  private List<Estacao> estacoes;
  private List<Paragem> paragens;
  public List<Barco> getBarcos() { return this.barcos; }
  public List<Estacao> getEstacoes() { return this.estacoes; }
  public List<Paragem> getParagens() { return this.paragens; }
}

そして、私が実装しようとしている方法で問題があります:

public <T extends Transporte> List<T> intersectTransportes(Entidade entidade, List<T> transportes) {
  if(entidade==null || transportes==null) return null;

  T typeOfTransport = (T) new Object(); /* <--- HERE'S THE PROBLEM (?) */
  List<T> result = new ArrayList<T>();
  List<Integer> ids = null;

  if(typeOfTransport instanceof Barco) ids = entidade.getIdBarcos(); else
  if(typeOfTransport instanceof Estacao) ids = entidade.getIdEstacoes(); // else ...

  // now do the work
  for(Transporte t : transportes) {
    for(Integer id : ids) {
      if(t.getId()==id) result.add((T) t);
    }
  }

  return result;
}

Javaで許可されていると思ってい<T extends Transporte>たのではなく、を使用していることに注意してください。<T implements Transporte>しかし、後者の構文は無効なので、implements代わりに使用する必要があります...

このメソッドは、次のように呼び出されています。

List<Estacao> allStations;
List<Estacao> myStations = intersectTransportes(entidade, allStations);

ここで私がやろうとしているのは、メソッドを呼び出すときに実行時に使用される実際のタイプを識別することです。この場合、私が使用している特定の実装オブジェクトをinsersectTransportes認識できるはずです。ListTransporte

私は他のものを使うことになっているのではないかと思います

T typeOfTransporte = (T) new Object(); 

明らかに、それがランタイム例外が生成されている行だからです。しかし、これを解決する方法がよくわかりません。解決策(またはこの問題に近づいている特定の参考文献)への兆候はありがたいです。

4

5 に答える 5

2

問題は:

  • a)ジェネリック型はできませんnew-実行時に消去されます
  • b)オブジェクトは拡張されないTransporteため、キャストできませんT
于 2011-06-07T09:43:14.373 に答える
1

クラスをメソッドに渡す必要があります。

public <T extends Transporte> List<T> intersectTransportes(Entidade entidade, List<T> transportes, Class<T> clazz) {

...
T typeOfTransporte = clazz.newInstance();
于 2011-06-07T09:44:16.197 に答える
1
T typeOfTransport = (T) new Object(); /* <--- HERE'S THE PROBLEM (?) */

問題は明らかです。オブジェクトは「トランスポートのタイプ」ではありません (トランスポート インターフェイスを実装または拡張しません)。

この例でも同じエラーが発生します。 String myStr = (String) new Object();

T typeOfTransport = (T) new Barco(); //new Barco() or anything that implements Transport interface

そこで特定のクラスをインスタンス化する必要がありますが、Object のようなクラスはインスタンス化しないでください。クラスは Transport インターフェイスを実装する必要があります。

于 2011-06-07T09:55:05.557 に答える
0

もちろん、(T)new Object()には問題があります。new Object()を呼び出すと、クラスObjectのインスタンスが作成されます。何か便利なものにキャストすることはできません。

次のようにメソッドを記述してみてください。

public <T extends Transporte> List<T> intersectTransportes(Entidade entidade, List<T> transportes, Class<T> clasz)

反射を使用します。

于 2011-06-07T09:44:34.973 に答える
0

Transporteメソッドを使用して (おそらくスイッチを使用して) 、 new の作成を処理する Factory を渡す必要がありcreateNew(Class<? extends T> transporteClass)ます。

Commons-collections または guava ライブラリの使用も検討する必要があります。これらには、探している種類の交差メソッドがあり、このコードを書く手間を省くことができます。

于 2011-06-07T09:49:29.097 に答える