【问题标题】:Java: generics method and type identificationJava:泛型方法和类型识别
【发布时间】:2011-06-07 09:39:13
【问题描述】:

我不太习惯泛型,所以在这里我有点困惑我应该如何解决这个问题。我编写了一个尝试在运行时调用不同方法的方法。但是我得到了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;
}

请注意,我使用的是 &lt;T extends Transporte&gt; 而不是 &lt;T implements Transporte&gt;,因为我希望 Java 允许。但是后一种语法无效,所以我必须改用implements...

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

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

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

我怀疑我应该使用除

之外的其他东西
T typeOfTransporte = (T) new Object(); 

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

【问题讨论】:

    标签: java generics methods runtimeexception


    【解决方案1】:

    问题是:

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

    【讨论】:

      【解决方案2】:

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

      public <T extends Transporte> List<T> intersectTransportes(Entidade entidade, List<T> transportes, Class<T> clazz) {
      
      ...
      T typeOfTransporte = clazz.newInstance();
      

      【讨论】:

      • 我试图避免在方法中添加额外的参数(以使其简短而甜蜜),但看起来这样可以避免额外的工作量。
      【解决方案3】:
      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 接口。

      【讨论】:

        【解决方案4】:

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

        试着像这样写你的方法:

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

        并使用反射。

        【讨论】:

          【解决方案5】:

          您应该传入一个处理创建新Transporte 的工厂,并带有一个方法(可能使用开关)createNew(Class&lt;? extends T&gt; transporteClass)

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-11-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多