Tuesday 5 February 2019

java - Overriding private methods in (non-)static classes



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

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...