Invoking super class method without its instance u

2019-07-03 15:39发布

问题:

Please consider the below code demonstrating inheritance and reflection :

    /*Parent class*/

    package basics;

    public class Vehicle {

        private void parentPrivateMethod() {
            System.out.println("This is the child private method");
        }

        public void print() {
            System.out.println("This is a Vehicle method");
        }

        public void overrideThisMethod() {
            System.out.println("Parent method");
        }

    }


    /*Child class*/

    package basics;

    public class Car extends Vehicle {

        private void childPrivateMethod() {
            System.out.println("This is the child private method");
        }

        public String returnCarName() {
            return "Manza";
        }

        @Override
        public void overrideThisMethod() {
            //super.overrideThisMethod();/*NOTE THIS*/
            System.out.println("Child method");
        }

    }


    /*Tester class*/
    package basics;

    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;

    public class NewTester {

        /**
         * @param args
         * @throws NoSuchMethodException
         * @throws SecurityException
         * @throws InvocationTargetException
         * @throws IllegalAccessException
         * @throws IllegalArgumentException
         * @throws InstantiationException
         */
        public static void main(String[] args) throws SecurityException,
                NoSuchMethodException, IllegalArgumentException,
                IllegalAccessException, InvocationTargetException, InstantiationException {
            // TODO Auto-generated method stub

            Car carInstance = new Car();

            /* Normal method invocation */
            carInstance.overrideThisMethod();

            /* Reflection method invocation */
            Method whichMethod = Car.class.getSuperclass().getMethod(
                    "overrideThisMethod", null);
            whichMethod.invoke(carInstance, null);

            /* Work-around to call the superclass method */
            Method superClassMethod = Car.class.getSuperclass().getMethod(
                    "overrideThisMethod", null);
            superClassMethod.invoke(Car.class.getSuperclass().newInstance(), null);
        }

    }

The output(with 'NOTE THIS' part commented) is :

        Child method
        Child method
        Parent method

In case, the 'NOTE THIS' part is un-commented, the superclass method will be invoked, giving an output :

        Parent method
        Child method
        Parent method
        Child method
        Parent method

When an instance of Car is created, the constructor of Vehicle runs first. Hence, I believe, that an instance of Vehicle is created,too, whose reference the Car instance holds via 'super'.

Question : How can I invoke the superclass version of 'overrideThisMethod' without using the /* Work-around to call the superclass method */ ?

Am I overlooking something here/making wrong assumptions here?

回答1:

When an instance of Car is created, the constructor of Vehicle runs first. Hence, I believe, that an instance of Vehicle is created,too, whose reference the Car instance holds via 'super'.

This is not quite correct; only one object is created. The constructor of Vehicle runs because it is an instance of Vehicle as well as of Car. There is no separate Vehicle object, and super is not an object reference but a keyword. For example you can't pass super to methods as an argument.

The super keyword allows you to tell the compiler that you want to call a method from the super class without checking if the method is overridden in subclasses. In order to do this the compiler generates the method call with the invokespecial JVM instruction. Normally the compiler would emit an invokevirtual instruction.



回答2:

If you need to run the superclass public method, call it from an instance of the superclass. If you wanted to call the parent method from the child, then it shouldn't have gotten overridden in the first place.

Vehicle v = new Vehicle();
v.overrideThisMethod();