I have analyzed the issue and here is the results. I have simplified a bit the example from the question.
This answer handles the first question of OP
Why getTest() generate a bridge method if BaseClass is default?
For second question regarding the inconsistency appearing with generics you can read Denis answer
Example 1
class BaseClass {
public String getTest(){
return "one";
}
public String getTest2(){
return "two";
}
public String getTest3(){
return "three";
}
}
public class OverrideClass extends BaseClass{}
public class Application {
public static void main(String[] args) throws Exception {
Class<OverrideClass> overrideClass1 = OverrideClass.class;
Method[] declaredMethods1 = overrideClass1.getDeclaredMethods();
System.out.println(Arrays.toString(declaredMethods1));
}
}
The execution of this either with JDK 8 or with JDK 17 has always the same result
[public java.lang.String OverrideClass.getTest(), public java.lang.String OverrideClass.getTest2(), public java.lang.String OverrideClass.getTest3()]
Example 2
Just modify the above example into
public class BaseClass {
public String getTest(){
return "one";
}
public String getTest2(){
return "two";
}
public String getTest3(){
return "three";
}
}
Note that the change is in the access modifier on Base class which now is public!
The execution of this produces the expected behavior of []
This however is not a bug of JDK. It is intended to be this way.
Explanation
The reason that in the example1 the getDeclaredMethods() has returned the same methods of the parent class is not because those methods are printed as inherited. It is because those are bridge methods that actually belong to that child class (OverrideClass).
This functionality has been added long ago and the explanation as you can see here from developers of oracle was
The proposal is to add bridge methods in these very rare cases to fix
a problem in reflection with no other forseen fix or workaround.
Specifically, we would generate a bridge method when a public method
is inherited from a nonpublic class into a public class.
And as you can also see here, the most recent comment from oracle developers was
The bridge methods are added in a case like this where a public class
public methods from a non-public superclass to allow for the
possibility of reflective access of the subclasses methods
JDK-6342411).
Closing this issue as not a bug.
So this is happening only in non public parent classes because in this case the public methods that are inherited need to be added as bridge methods in that children class.
In the example 2 where bridge methods do not exist, if you try to print out the disassembled code using javap -c OverrideClass you will see the following
public class OverrideClass extends BaseClass {
public OverrideClass();
Code:
0: aload_0
1: invokespecial #1 // Method BaseClass."<init>":()V
4: return
}
In the example 1 with bridge methods existing, if you try to print out the disassembled code using javap -c OverrideClass you will see the following
public class OverrideClass extends BaseClass {
public OverrideClass();
Code:
0: aload_0
1: invokespecial #1 // Method BaseClass."<init>":()V
4: return
public java.lang.String getTest3();
Code:
0: aload_0
1: invokespecial #7 // Method BaseClass.getTest3:()Ljava/lang/String;
4: areturn
public java.lang.String getTest2();
Code:
0: aload_0
1: invokespecial #11 // Method BaseClass.getTest2:()Ljava/lang/String;
4: areturn
public java.lang.String getTest();
Code:
0: aload_0
1: invokespecial #14 // Method BaseClass.getTest:()Ljava/lang/String;
4: areturn
}