我一直在研究Java中的泛型类和方法,并在上一篇论文中遇到了这个问题
我尝试实现问题中提出的接口和类,包括加油方法,但发现将Car参数作为参数传递没有问题
电动界面
public interface Motorized {
public int getFuel();
}
车辆类
public abstract class Vehicle{
private int fuel;
public Vehicle(int fuel) {
this.fuel = fuel;
}
public String toString(){
return("Fuel is: " + getFuel());
}
public int getFuel() {
return fuel;
}
}
汽车课
public class Car extends Vehicle implements Motorized {
int seats;
public Car(int fuel, int seats) {
super(fuel);
this.seats = seats;
}
public int getSeats() {
return seats;
}
@Override
public String toString(){
return("Fuel is: " + getFuel() + "and the car has" + getSeats() + "seats.");
}
}
测试方法
public class VehicleTest {
public static Motorized refuel(Motorized v) {
return v;
}
public static void main(String[] args) {
Car car = new Car(15, 5);
System.out.println(refuel(car));
}
}
有人可以向我解释这个问题应该是什么问题,为什么我的实现不能反映这个问题?
答案 0 :(得分:2)
问题在于方法的返回值:
public static Motorized refuel(Motorized v)
您说在传递Car
时没有问题,这是一个完全有效的语句。但是您尚未尝试通过refuel
方法取回值:
Car car = ...
Car refueled = refuel(car); // compiler error: Motorized is not assignable to Car!
尽管Motorized
的返回类型为Car extends Motorized
,但您不能确定返回的Motorized
实例是否总是{em> }}。请参阅以下简化示例:
Car
现在,您可能会期望得到public static Motorized refuel(Motorized v) {
// try to refuel
// uh oh... the gas station exploded
// you have to change to a motorbike which just stands around
return new Motorbike();
}
,但您会得到Car
,因此即使强制转换也会失败:
Motorbike
您可以使用泛型来做到这一点:
Car refueled = (Car) refuel(car); // ClassCastException, Motorbike is not a Car
尽管如果加油站再次爆炸,则该方法将存在问题。它不知道public static <M extends Motorized> M refuel(M m) {
// refuel the motorized vehicle
return m;
}
实际上是什么。因此,这可能是您头痛的救星。
答案 1 :(得分:1)
代替
System.out.println(refuel(car));
尝试
Car refueledCar = refuel(car);
您会发现它无法编译,因为从refuel
方法获得的变量不是Car
的实例,而是某种对象(但编译器不知道实现Motorized
的哪种对象。您可以使用
Car
Car refueledCar = (Car) refuel(car);
但这很笨拙,并且使您的代码更容易出现错误。幸运的是,有更好的方法可以解决此问题。具体来说,通过使用泛型。如果将refuel
的方法签名更改为此:
public static <T extends Motorized> T refuel(T t)
您会发现返回的类型与您传递的类型相同,并且编译器对以前无法编译的那一行非常满意。
通过解释的方式,新方法签名的基本含义是“存在一个未知类型T
,它扩展了Motorized
。该方法接受类型为T
的变量,并且具有相同类型的返回值。”
答案 2 :(得分:0)
您可以为此使用generic method。
这是一个极其简化的层次结构(此处Vehicle
被忽略)。
interface Motorized {
void refuel();
}
class Car implements Motorized {
@Override
public void refuel() {
// TODO
}
}
现在这是您的测试班:
class VehicleTest {
// | generic method type parameter bound up to any `Motorized`
// | | returns same type...
// | | | ... as given type
// | | |
static <T extends Motorized> T refuel(T t) {
t.refuel();
return t;
}
// and here's some usage
public static void main(String[] args) {
Car car = new Car();
Car refueled = refuel(car);
}
}