I have this test code example:
public class Test {
private static class Test3 {
private void print1() {
System.out.println("1");
}
}
private static class Test4 extends Test3 {
private void print1() {
System.out.println("2");
}
}
public static void main(String[] args) {
System.out.println("Overriden call to private method ----------------");
OuterTest.Test1 test1 = new OuterTest.Test1();
OuterTest.Test2 test2 = new OuterTest.Test2();
OuterTest.Test1 test12 = new OuterTest.Test2();
test1.invokeOverriden();
test2.invokeOverriden();
test12.invokeOverriden();
System.out.println("Call to private method from parent class ----------------");
test1.invokeNotOverriden();
test2.invokeNotOverriden();
test12.invokeNotOverriden();
System.out.println(" Some magic ----------------");
Test3 test3 = new Test3();
Test4 test4 = new Test4();
Test3 test34 = new Test4();
test3.print1();
test4.print1();
test34.print1();
}
}
class OuterTest {
public static class Test1 {
public void invokeOverriden() {
print1();
}
public void invokeNotOverriden() {
print1();
}
private void print1() {
System.out.println("1");
}
}
public static class Test2 extends Test1 {
@Override
public void invokeOverriden() {
print1();
}
private void print1() {
System.out.println("2");
}
}
}
First, all works as I think it should:
Overriden call to private method ----------------
1
2
2
Then, inherited class's private method dissapears, if I called non-implemented parent method. It could be explained as "All private methods are final and hidden from derived classes", so invokeNotOverriden()
doesn't know anything about methods in Test2 class:
Call to private method from parent class ----------------
1
1
1
Finally, in static class some magic suddenly appears when I call non-static private method:
Some magic ----------------
1
2
1
I expected 1 2 2
here. Why am I wrong?
Answer
You've got 1 2 1
in some magic
section, because private methods are resolved w/o polymorphism, compiler creates call to method contained in type variable declared with, in your case Test3
. Declare print1
as non-private in Test3
(and, consequently, in Test4
as it's prohibited to tighten access modifiers of methods) and see polymorphism in action, so you'll get expected 1 2 2
.
Consider shorter example:
class Test {
private static class Test3 {
private void print1() {
System.out.println("non-polymorphic 1");
}
void polymorphic() {
System.out.println("polymorphic 1");
}
}
private static class Test4 extends Test3 {
private void print1() {
System.out.println("non-polymorphic 2");
}
void polymorphic() {
System.out.println("polymorphic 2");
}
}
public static void main(String[] args) {
Test4 t4 = new Test4();
t4.print1();
t4.polymorphic();
System.out.println("======");
Test3 t34 = new Test4();
t34.print1();
t34.polymorphic();
}
}
CLARIFICATION ... to my comment to this answer: polymorphism isn't effective for access to data fields, only for methods. Consider:
private static class Test3 {
int i = 1;
}
private static class Test4 extends Test3 {
int i = 2;
}
public static void main(String[] args) {
Test4 t4 = new Test4();
System.out.println(t4.i);
System.out.println("======");
Test3 t34 = new Test4();
System.out.println(t34.i);
}
Despite i
declared non-private, t34.i
value is 1
.
No comments:
Post a Comment