Java:泛型方法和类型识别
我不太习惯泛型,所以我对如何解决这个问题有点困惑。我编写了一个尝试在运行时调用不同方法的方法。但我收到了 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
问题是:
new
你的泛型类型 - 它在运行时被删除Transporte
,所以它不能被转换为T
The problem is:
new
your generic type - it's erased at runtimeTransporte
, so it cant be cast toT
您需要将类传递给您的方法:
You need to pass the class to your method:
问题相当明显,对象不是“传输类型”(不实现或扩展传输接口)。
在这个例子中你会得到同样的错误:
字符串 myStr = (字符串) 新对象();
您必须在那里实例化一个特定的类,但不能实例化任何像 Object 这样的类。该类必须实现 Transport 接口。
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();
You must instantiate a specific class there, but not any class like Object. The class must implement Transport interface.
当然(T)new Object()有问题。当您调用 new Object() 时,它会创建 Object 类的实例,就是这样。你不能只是把它变成有用的东西。
尝试像这样编写您的方法:
并使用反射。
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:
and use reflection.
您应该传入一个工厂来处理创建新的
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.