How does a JVM execute the Inheritance tree structure?
class Vehicle {
public int wheels;
public int lights;
}
class Car extends Vehicle {
public int wheels =4;
public int lights =2;
public void lights_on( int lights) {
//Code to onlights
}
}
class BMWCar extends Car {
public int wheels = 4;
public int lights = 4;
}
public class TestCar {
public static void main(String args[]) {
//Creating a new instance of BMWCAR by calling the default
// constructor provided by the constructor
bmwCar = new BMWCAR();
bmwCar.lights_on();
}
}
In the above example, when I run the TestCar.java
file, The JVM's开发者_运维技巧 class loader loads the TestCar
file into the method area, and it executes the main method. When a bmwCar
instance is created, it calls the default constructor of the BMWCar
class and executes the super constructor, which is the Car
class's default constructor. I would like to know why when the bmwCar.lights_on();
method is called the JVM looks for the lights_on
method and in the bmwCar
object it initalizes the value of instance variables wheels and lights i.e. 4
and 4
.
When the lights_on();
method is executed in the Car
class, does the JVM reintialize the value? How is the reference passed from bmwCar.lights_on
to the Car
class lights_on
method? I am looking for a detailed answer about the workflow.
You are declaring member variables wheels
and lights
in class Vehicle
, and then you're declaring member variables with the same name in subclasses Car
and BMWCar
.
Note that member variables are not overridden like methods; the member variables in your subclasses hide the variables in the superclasses.
So, there is not one set of member variables - there are three! You see one of those three depending in which class your method is. The member variables of the superclasses are not somehow reinitialized. Inside the method lights_on
in class Car
, you'll see the variables wheels
and lights
of class Car
, with the values 4 and 2.
Using member variables with the same name as in a superclass should be avoided, as it's confusing, and it's not doing what you might think it does.
Don't redeclare the member variables put do it like this
public class Vehicle {
public int wheels = -1;
public int lights = -1;
}
class Car extends Vehicle {
{
wheels = 4; //set inherited member variable
lights = 2; //set inherited member variable
}
public void lights_on(int lights){
System.out.println("Parameter to lights_on: "+lights);
System.out.println("Wheels: "+wheels);
System.out.println("Lights: "+this.lights);
}
}
class BMWCar extends Car {
{
wheels = 4;
lights = 4;
}
}
public class TestCar {
public static void main(String args[]){
//Creating a New Instance of BMWCAR by calling the default Constructor provided by the constructor
Car car = new BMWCar();
car.lights_on(1);
car = new Car();
car.lights_on(1);
}
}
Conceptually, the JVM refers to and looks up the field by its name, type and class. See the GETFIELD opcode in the JVM spec.
In practice, the JIT compiler (at least in Hotspot) compiles to native code which simply access memory at a given offset of the object's data (i.e. the JIT compiler pre-computes the field offset). (Sorry, I don't have a reference for this, but if you get the debug version of the JVM you can ask it to output its assembler code and see that that's what it does.)
精彩评论