Inheritance at package visibility in Java

TFuto :

I am looking for an explanation for the following behavior:

  • I have 6 classes, {a.A,b.B,c.C,a.D,b.E,c.F}, each having a package visible m() method that writes out the class name.
  • I have an a.Main class with a main method that does some testing of these classes.
  • The output seems to not follow proper inheritance rules.

Here are the classes:

package a;

public class A {
    void m() { System.out.println("A"); }
}

// ------ 

package b;

import a.A;

public class B extends A {
    void m() { System.out.println("B"); }
}

// ------ 

package c;

import b.B;

public class C extends B {
    void m() { System.out.println("C"); }
}

// ------ 

package a;

import c.C;

public class D extends C {
    void m() { System.out.println("D"); }
}

// ------ 

package b;

import a.D;

public class E extends D {
    void m() { System.out.println("E"); }
}

// ------ 

package c;

import b.E;

public class F extends E {
    void m() { System.out.println("F"); }
}

The Main class is in package a:

package a;

import b.B;
import b.E;
import c.C;
import c.F;

public class Main {

    public static void main(String[] args) {
        A a = new A();
        B b = new B();
        C c = new C();
        D d = new D();
        E e = new E();
        F f = new F();

        System.out.println("((A)a).m();"); ((A)a).m();
        System.out.println("((A)b).m();"); ((A)b).m();
        System.out.println("((A)c).m();"); ((A)c).m();
        System.out.println("((A)d).m();"); ((A)d).m();
        System.out.println("((A)e).m();"); ((A)e).m();
        System.out.println("((A)f).m();"); ((A)f).m();

        System.out.println("((D)d).m();"); ((D)d).m();
        System.out.println("((D)e).m();"); ((D)e).m();
        System.out.println("((D)f).m();"); ((D)f).m();
    }
}

And here is the output:

((A)a).m();
A
((A)b).m();
A
((A)c).m();
A
((A)d).m();
D
((A)e).m();
E
((A)f).m();
F
((D)d).m();
D
((D)e).m();
D
((D)f).m();
D

And here are my questions:

1) I understand that D.m() hides A.m(), but a cast to A should expose the hidden m() method, is that true? Or is D.m() overrides A.m() in spite of the fact that B.m() and C.m() breaks the inheritance chain?

((A)d).m();
D

2) Even worse, the following code shows overriding in effect, why?

((A)e).m();
E
((A)f).m();
F

And why not in this part:

((A)a).m();
A
((A)b).m();
A
((A)c).m();
A

and this one?

((D)d).m();
D
((D)e).m();
D
((D)f).m();
D

I am using OpenJDK javac 11.0.2.


EDIT: The first question is answered by How to override a method with default (package) visibility scope?

An instance method mD declared in or inherited by class D, overrides from D another method mA declared in class A, iff all of the following are true:

  • A is a superclass of D.
  • D does not inherit mA (because crossing package boundaries)
  • The signature of mD is a subsignature (§8.4.2) of the signature of mA.
  • One of the following is true: [...]
    • mA is declared with package access in the same package as D (this case), and either D declares mD or mA is a member of the direct superclass of D. [...]

BUT: the second question is still unresolved.

TFuto :

I reported this issue and it was confirmed a bug for several Java versions.

Bug report.

I mark this answer as the solution, but would like to thank everyone for all the answers and messages, I learned a lot. :-)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=304315&siteId=1