Java:泛型方法和类型识别

时间:2011-06-07 09:39:13

标签: java generics methods runtimeexception

我不习惯仿制药,所以我在这里有点困惑,我应该如何解决这个问题。我编写了一个尝试在运行时调用不同方法的方法。但是我得到了一个ClassCastException,尽管代码在语法上是正确的。

我有以下类(为简洁起见,省略了一些getter和setter):

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;
}

请注意 我正在使用<T extends Transporte>而不是<T implements Transporte>,因为我希望Java允许。但后一种语法无效,所以我必须使用implements代替......

正在调用此方法,如下所示:

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

我在这里要做的是确定在调用方法时在运行时使用的实际类型。在这种情况下,insersectTransportes应该能够识别List的{​​{1}} - 实现我正在使用的对象。

我怀疑我应该使用

以外的东西
Transporte

因为显然是生成运行时异常的行。但是,我不太清楚如何解决这个问题。对解决方案的任何指示(或接近此问题的特定参考书目)都表示赞赏。

5 个答案:

答案 0 :(得分:2)

问题是:

  • a)你不能new你的通用类型 - 它在运行时被删除
  • b)对象未扩展Transporte,因此无法转换为T

答案 1 :(得分:1)

您需要将类传递给您的方法:

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

...
T typeOfTransporte = clazz.newInstance();

答案 2 :(得分: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这样的任何类。该类必须实现传输接口。

答案 3 :(得分:0)

当然(T)new Object()存在问题。当你调用new Object()时,它会创建Object类的实例,就是这样。你不能把它变成有用的东西。

尝试编写这样的方法:

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

并使用反射。

答案 4 :(得分:0)

您应该使用方法(可能使用切换)Transporte来传递处理创建新createNew(Class<? extends T> transporteClass)的工厂。

您还应该考虑使用commons-collections或guava库,它们具有您正在寻找的那种交集方法,从而避免了编写此代码的麻烦。