I've been going over Generic classes and methods in Java and came across this question in a past paper
I tried implementing the interface and classes proposed in the question, including the refuel method, and found no problem with passing the Car argument as a parameter
Motorized interface
public interface Motorized {
public int getFuel();
}
Vehicle class
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;
}
}
Car class
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.");
}
}
test method
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));
}
}
Can somebody explain to me what the problem should be with this question and why my implementation of it doesn't reflect this problem?
The problem lies with the return value of the method:
public static Motorized refuel(Motorized v)
You said you had no problems passing in a Car
and that is a completly valid statement. But you have not tried to get the value back from the refuel
method:
Car car = ...
Car refueled = refuel(car); // compiler error: Motorized is not assignable to Car!
The return type is Motorized
although Car extends Motorized
, you can't be sure that the Motorized
instance that is returned will always be a Car
. See this simplified example:
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();
}
Now you maybe expect a Car
but you get a Motorbike
, so even a cast fails:
Car refueled = (Car) refuel(car); // ClassCastException, Motorbike is not a Car
You can do this with generics though:
public static <M extends Motorized> M refuel(M m) {
// refuel the motorized vehicle
return m;
}
Though if the gas station explodes again, then the method has a problem. It doesn't know what M
actually is. So this can be a lifesaver for headaches to you.