javamethodsoverridingfinalmethod-hiding

Java - Hiding Overriding and the modifier final


I couldn't find a question like mine, so I hope it's not a duplicate one.

Again it's about overriding and hiding. I think - but I might be wrong - I understood both.

The following code behaves as expected, both methods have been hidden. method1 because it is a private method and private methods can't be overridden only hidden, method2 because it's static and static methods can't be overridden, they can only be hidden.

public class Child extends Parent { 
    public void method1(){System.out.println("child");}     
    public static void method2(){ System.out.println("static child");}  
}

class Parent{
    private void method1(){ System.out.println("parent");}      
    public static void method2(){ System.out.println("static parent");}

    public static void main(String[] args){
            Parent p = new Child();
            p.method1(); //prints out "parent"
            p.method2(); //prints out "static parent"
    }
}

If I read the specs it says:

http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.3.3

A method can be declared final to prevent subclasses from overriding or hiding it.

If I change method1 in the Parent class to "final"

private final void method1(){ System.out.println("parent");}

Everything works fine. edit start: I expected an compiler error saying that final methods can't be hidden, but that didn't happen. :edit end

Question no 1: does that mean only static methods can be hidden? In the book I'm reading (OCA study guide, Jeanne Boyarsky and Scott Selikoff page 252) they clearly say that a private method was hidden.

Then I changed method2 in the Parent class to

public final static void method2(){ System.out.println("static parent");}

Now the compiler does complain, the error says "Child cannot override method2()" which is pretty confusing because I thought I tried to hide a method.

Question no 2: Shouldn't it be "Child cannot hide method2()"?

edit start: I am well aware that no overriding happens here, but as the mentioned specs point out: the modifier final prevents methods to be overridden or hidden, that's why I put it in the title. :edit end


Solution

  • Question 1

    Question no 1: does that mean only static methods can be hidden?

    Parent.method1() was not visible in nor inherited by Child simply by virtue of being private. So Child.method1() didn't override or hide Parent.method1(), it merely created a new method in Child that had the same name, parameters and return type.

    See http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.8.3:

    Note that a private method cannot be hidden or overridden in the technical sense of those terms. This means that a subclass can declare a method with the same signature as a private method in one of its superclasses, and there is no requirement that the return type or throws clause of such a method bear any relationship to those of the private method in the superclass.

    Question 2

    Question no 2: Shouldn't it be "Child cannot hide method2()"?

    Yes, you are correct. It should be "hide". Per the JLS (http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.8.2),

    If a class C declares or inherits a static method m, then m is said to hide any method m', where the signature of m is a subsignature (§8.4.2) of the signature of m', in the superclasses and superinterfaces of C that would otherwise be accessible to code in C.

    "Hiding" is what static methods do to static methods. "Overriding" is what instance methods do to instance methods. The two can't be mixed: a static method can't override or hide an instance method, and an instance method can't override or hide a static method.

    BTW, my Eclipse compiler gives a similar error message: "Cannot override the final method from Parent"