Java Polymorphism and Method Invocation in Smali: Why Subclass Methods are Called Even Without Overriding
As per the given code, we can see that both parent and sub classes have a method called 'printInfo()'. The 'SubClass' extends the 'ParentClass', which means it inherits the methods and properties of the parent class.
When we create an object of the 'SubClass' and call 'printInfo()' on it, it will call the method defined in the 'SubClass'.
But when we create an object of the 'SubClass' and assign it to a reference variable of the 'ParentClass' type and call 'printInfo()' on it, it will still call the method defined in the 'SubClass'. This is because we have used polymorphism here, which allows us to assign an object of a subclass to a reference variable of the parent class type.
Now, coming to the smali code, the 'invoke-virtual' instruction is used to call the 'printInfo()' method. When we create an object of the 'SubClass' and assign it to a reference variable of the 'ParentClass' type and call 'printInfo()' on it, the smali code generated will contain the instruction 'invoke-virtual {v0}, LParentClass;->printInfo()V'. This is because the reference variable is of the 'ParentClass' type, and the compiler assumes that the method being called is the one defined in the 'ParentClass'.
However, when we create an object of the 'SubClass' and call 'printInfo()' on it, the smali code generated will contain the instruction 'invoke-virtual {v0}, LSubClass;->printInfo()V'. This is because the method being called is the one defined in the 'SubClass', which is the actual type of the object.
Therefore, even if we do not override the method in the 'SubClass', the smali code will still call the method defined in the 'SubClass' when we create an object of the 'SubClass' and call 'printInfo()' on it. This is due to the principle of dynamic dispatch or runtime polymorphism in Java. During execution, the JVM determines the appropriate method to call based on the actual object type, not just the reference type.
In the smali code, the 'invoke-virtual' instruction is used to invoke methods that can be overridden, and the JVM performs dynamic dispatch to determine the actual method to call at runtime. This means that the JVM will use the implementation of 'printInfo()' defined in the 'SubClass' even without explicitly overriding it in the 'SubClass'.
Here's a breakdown of how the code works with smali instructions:
new-instance v0, LSubClass;
invoke-direct {v0}, LSubClass;-><init>()V
invoke-virtual {v0}, LParentClass;->printInfo()V // Calls the printInfo() method from SubClass, even though the reference type is ParentClass
new-instance v0, LSubClass;
invoke-direct {v0}, LSubClass;-><init>()V
invoke-virtual {v0}, LSubClass;->printInfo()V // Calls the printInfo() method from SubClass, as expected
This demonstrates how Java's polymorphism and the JVM's runtime behavior work together to ensure that the correct method is called based on the actual object type, regardless of the reference type used.
原文地址: https://www.cveoy.top/t/topic/m9ve 著作权归作者所有。请勿转载和采集!