So i have those 2 classes running on jdk 7:
abstract class Aclass
{
public void foo()
{
}
public void bar()
{
}
}
And:
public class Bclass extends Aclass
{
public void foo(Integer one)
{
}
public void bar(String two)
{
}
}
My goal is to load Bclass, and Bclass ONLY, print out its declared methods and parameters of those declared methods. Here is the code i use:
public static void main(String[] args)
{
try
{
Class<?> clazz = Tester.class.getClassLoader().loadClass("full_path.Bclass");
for (Method method : clazz.getDeclaredMethods())
{
System.out.println("Method name: " + method.getName() + " From class: " + method.getDeclaringClass().getCanonicalName() + " with declared methods:");// test
for (Class<?> param : method.getParameterTypes())
{
System.out.println(param.getCanonicalName());
}
}
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
Running this code it produces the following output:
Method name: foo From class: complete_path.Bclass with declared methods:
Method name: foo From class: complete_path.Bclass with declared methods:
java.lang.Integer
Method name: bar From class: complete_path.Bclass with declared methods:
Method name: bar From class: complete_path.Bclass with declared methods:
java.lang.String
But in the javadoc's of the method [getDeclaredMethods()] i see but excludes inherited methods , this seems not to be the case according to my tests, the method apparently does load inherited methods when they are overloaded.
Or am i doing something wrong?
My goal is to load Bclass, and Bclass ONLY ...
It is not possible.
The JVM specification (Chapter 5) explains in great detail what has to happen when a class is loaded. One of the things that must happen is that the references to direct superclasses, and interfaces are resolved. That entails loading the respective classes / interfaces.
If (for some reason) the superclasses or interfaces cannot be loaded, then loading of the child class fails.
Loading java class methods, docs not consistent with method's behavior
The unexpected behavior of getDeclaredMethods() is a different issue. It is nothing to do with class loading.
According to this Q&A - Problem in the GetDeclaredMethods (java) - you are seeing synthetic "bridge" methods that have been added to Bclass rather than methods inherited from Aclass.
Bridge methods are described in the Java Tutorial here.
You can confirm this by using javap Bclass to look at the code in Bclass.class. See those extra bridge methods in the output.
[steve@newbox tmp]$ javap Bclass
Compiled from "Bclass.java"
public class Bclass extends Aclass {
public Bclass();
public void foo(java.lang.Integer);
public void bar(java.lang.String);
public void bar();
public void foo();
}
Further confirmation (if you need it) can be had by printing method.isBridge() for each Method object.
Now I don't understand why this code needs bridge methods ... but this is what they are.
In summary: the behavior of getDeclaredMethods that you are seeing is consistent with the javadocs. What you are seeing is a consequence of a little known (but documented!) aspect of recent Java implementations.
It's weird
I think I did nothing wrong, but I run your program and it only prints methods in Bclass. I just changed package and I put Aclass and Bclass in same file, since only Bclass is public. Output:
Method name: foo From class: test2.Bclass with declared methods:
java.lang.Integer
Method name: bar From class: test2.Bclass with declared methods:
java.lang.String
test2.Bclass
test2.Aclass
// Also added at the end
// System.out.println(clazz.getCanonicalName());
// System.out.println(clazz.getSuperclass().getCanonicalName());
// to see if I typed something wrong.
Compiled and run using: Sun JDK 1.5.0_22.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With