Suppose you have a class and a subclass in Java:
public abstract class Car {
public static Car getCar() {
Car car = makeCar();
return car;
}
private static Car makeCar() {
//bunch of code that makes the car
return car;
}
}
public class Ferrari extends Car {
private static makeCar() {
//bunch of code that makes a Ferrari! Yeah!
awesomeRide = new Car();
return awesomeRide;
}
}
Then in another class you call:
Ferrari.getCar();
Ferrari's super-class's getCar() and makeCar() methods will be called. Ferrari cannot @Override getCar() because in Java, static methods cannot be overridden.
So in the Car's getCar() method, how can I tell whether the method call was sent to the class Ferrari, as opposed to the class, Car? Since it's a static method, I cannot do if(this instanceOf Car)
obviously.
EDIT: The correct answer (below) showed me that indeed I can't tell from within Car if getCar() is being run due to someone calling Car.getCar() or Ferrari.getCar().
But what I didn't know was that according to Java's documentation, while a static method cannot be overridden in Java, it can be hidden.
The key difference between hiding and overriding is that with hiding, static methods call other static methods on the same class, not the subclass they got routed in from.
What that means is that with overriding, if these were not static methods, Ferrari's makeCar() would always get called from Car's getCar() method anytime the caller called myFerrariInstance.getCar(). However with hiding, Ferrari's makeCar() will never get called from Car's getCar() method, because makeCar() is also a static method on the same class.
So in the Car's getCar() method, how can I tell whether the method call was sent to the class Ferrari, as opposed to the class, Car
You can't. (I thought javac
used to generate the same bytecode for both calls - it now doesn't, but I don't believe there's any way to detect which call is made at execution-time, and I wouldn't be surprised if it still lost that information during JITting.)
If you feel you need to do that, you should change the design - either significantly, or just passing in the relevant class as an argument to the method.
You could give each of your subclasses a static method with the same signature. This wouldn't be overriding, but it would work - you'd end up calling the right method, which could then do what you wanted. But if you created a new subclass and forgot to add the method, it would just silently call the superclass one...
See more on this question at Stackoverflow