Java通用以避免ClassCastException [英] Java generic to avoid ClassCastException
问题描述
这是我正在处理的一段代码。我有一个回调对象,可以返回指定的超类型。 车辆
就是这里的一个类。这些类在这里用作其他类的超类型,如 Car
和 Train
。
interface CompletionCallBack< Result> {
void onCompletion(结果结果);
}
class车辆{
Map< String,Object>属性;
}
class Car延伸车辆{
public String getMake(){
return attributes.get(make)。toString();
class train {
public String getMake(){
return attributes.get(size)。toString() ;
public class Main {
static void execute(CompletionCallBack< Vehicle> callBack){
callBack.onCompletion(new Vehicle()) ;
}
public static void main(String [] args){
execute(new CompletionCallBack< Vehicle>(){
@Override
public void onCompletion(Vehicle result){
Car car =(Car)result; // Exception
}
});
execute(new CompletionCallBack< Vehicle>(){
@Override
public void onCompletion(Vehicle result){
Train train =(Train)result; // Exception
}
});
$ b这里我得到了ClassCastException,因为Vehicule不能直接转换为汽车或火车。我想调用 execute
给它一个像 Car
或 Train <
$ b $ $ $ $ $
$静态无效executeGeneric(CompletionCallBack< ?extend Vehicle> callBack){
callBack.onCompletion(new Vehicle()); //编译错误
}
public static void main(String [] args){
executeGeneric(new CompletionCallBack< Car>(){
@Override
public void onCompletion(Car car){
//我在这里收到一辆车
}
});
}
}
我正在尝试这样做,因为在我的情况下,车辆
包含一个属性映射和一个 Car
车辆,该车辆在该列表中具有一些键值对。火车有其他人。我的 Car
和 Train
对象提供了简单的getter,它知道从 Map
。
我能做到这一点的唯一方法是移除父子关系并围绕<$ c构建一个装饰器$ c> Vehicle 为我的 Train
和 Car
类。
问题在于你有一个适用于任何车辆的机制,无需区分汽车和火车 - 但是你希望汽车和火车有不同的行为。
因此有以下几种解决方案:
1)拆分机制让你拥有不同的类型, 2)使用多态 - 在Vehicle中提供的方法可以在Car和Train中以不同的方式进行调用,并在回调中调用这些方法。
$ b $ 3)如果一切都失败了,使用 instanceof
来检测对象的实际类型,然后将其转换为汽车或火车。
Here is a piece of code I'm working on. I have a Callback object that can return a specified super type. Vehicle
is one of these classes here. These classes are used as supertype for other classes like Car
and Train
here.
interface CompletionCallBack<Result> {
void onCompletion(Result result);
}
class Vehicle {
Map<String, Object> attributes;
}
class Car extends Vehicle {
public String getMake(){
return attributes.get("make").toString();
}
}
class Train extends Vehicle {
public String getMake(){
return attributes.get("size").toString();
}
}
public class Main {
static void execute(CompletionCallBack<Vehicle> callBack) {
callBack.onCompletion(new Vehicle());
}
public static void main(String[] args) {
execute(new CompletionCallBack<Vehicle>() {
@Override
public void onCompletion(Vehicle result) {
Car car = (Car) result; //Exception
}
});
execute(new CompletionCallBack<Vehicle>() {
@Override
public void onCompletion(Vehicle result) {
Train train = (Train) result; //Exception
}
});
}
}
Here I get ClassCastException as Vehicule cannot be directly casted to Car or Train. I would like to either call the execute
giving it a type like Car
or Train
like so :
public class Main {
static void executeGeneric(CompletionCallBack<? extends Vehicle> callBack) {
callBack.onCompletion(new Vehicle()); //compilation error
}
public static void main(String[] args) {
executeGeneric(new CompletionCallBack<Car>() {
@Override
public void onCompletion(Car car) {
//I receive a car here
}
});
}
}
I'm trying to do this because in my case, Vehicle
contains a map of attribute and a Car
a vehicle that has some key-value pair in that list. Train has others. My Car
and Train
object provides easy getter that knows the specific keys to retrieve data from the Map
.
The only way I was able to do it was to remove the parent-child relation and build a decorator around a Vehicle
for my Train
and Car
classes.
The problem is that you have a mechanism that should work for any Vehicle, without distinguishng between Car and Train - yet you want different behaviour for Car and Train.
So there are several solutions:
1) Split up the mechanism so you have different, typed, callbacks for Car and Train
2) Use polymorphism - provide method(s) in Vehicle that you over-ride differently in Car and Train, and call these in the callbacks.
3) If all else fails, use instanceof
to detect the actual type of the object before casting it to Car or Train.
这篇关于Java通用以避免ClassCastException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!