Java:泛型方法和类型识别

发布于 2024-11-14 09:07:14 字数 2295 浏览 3 评论 0原文

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

请注意,我使用 而不是 正如我期望 Java 允许的那样。但后一种语法无效,因此我必须使用 implements 来代替...

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

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

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

我怀疑我应该使用除此之外的其他东西

T typeOfTransporte = (T) new Object(); 

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

I'm not very used to generics, so I'm a little confused here about how I'm supposed to solve this problem. I've written a method that tries to call different methods at runtime. But I'm getting a ClassCastException although the code seems syntactically correct.

I have the following classes (some getters and setters were omitted for brevity):

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

And the method I'm trying to implement and have difficulties with:

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

Please notice that I'm using <T extends Transporte> instead of <T implements Transporte> as I'd expect Java to allow. But that latter syntax is invalid, so I have to use implements instead...

The method is being invoked as illustrated here:

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

What I'm trying to do here is to identify the actual type used at runtime when invoking the method. In this case, insersectTransportes should be able to recognize the particular List of Transporte-implementing objects I'm using.

I suspect that I'm supposed to use something other than

T typeOfTransporte = (T) new Object(); 

since obviously that's the line where the runtime exception is being produced. However, I'm not quite sure how to solve this. Any indications to the solution (or specific bibliography approaching this problem) is appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

丢了幸福的猪 2024-11-21 09:07:14

问题是:

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

The problem is:

  • a) you can't new your generic type - it's erased at runtime
  • b) Object does not extend Transporte, so it cant be cast to T
菩提树下叶撕阳。 2024-11-21 09:07:14

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

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

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

You need to pass the class to your method:

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

...
T typeOfTransporte = clazz.newInstance();
旧伤慢歌 2024-11-21 09:07:14
T typeOfTransport = (T) new Object(); /* <--- HERE'S THE PROBLEM (?) */

问题相当明显,对象不是“传输类型”(不实现或扩展传输接口)。

在这个例子中你会得到同样的错误:
字符串 myStr = (字符串) 新对象();

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

您必须在那里实例化一个特定的类,但不能实例化任何像 Object 这样的类。该类必须实现 Transport 接口。

T typeOfTransport = (T) new Object(); /* <--- HERE'S THE PROBLEM (?) */

The problem is rather obvious, an object is not a "Type of Transport" (does not implement or extends the Transport interface).

You will get the same error with this example:
String myStr = (String) new Object();

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

You must instantiate a specific class there, but not any class like Object. The class must implement Transport interface.

痴情 2024-11-21 09:07:14

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

尝试像这样编写您的方法:

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

并使用反射。

Of course there is a problem with (T) new Object(). When you call new Object() it creates instance of class Object, thats it. You cant just cast it to something useful.

Try writing your method like this:

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

and use reflection.

女皇必胜 2024-11-21 09:07:14

您应该传入一个工厂来处理创建新的 Transporte,并使用一个方法(可能使用开关)createNew(Class transporteClass)

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

You should pass in a Factory that deals with creating the new Transporte, with a method (probably using a switch) createNew(Class<? extends T> transporteClass).

You should also look into using either commons-collections or the guava libraries, which have the kind of intersection methods you're looking for, saving you the trouble of writing this code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文