加载java类方法,docs与方法的行为不一致

时间:2015-01-28 10:29:36

标签: java reflection methods

所以我在jdk 7上运行了这两个类:

abstract class Aclass
{
  public void foo()
  {
  }
  public void bar()
  {
  }
}

public class Bclass extends Aclass
{
  public void foo(Integer one)
  {
  }
  public void bar(String two)
  {
  }
}

我的目标是加载Bclass和Bclass ONLY,打印出声明的方法和那些声明的方法的参数。 这是我使用的代码:

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();
    }
  }

运行此代码会产生以下输出:

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

但是在方法[getDeclaredMethods()]的javadoc中,我看到but excludes inherited methods,根据我的测试,这似乎并非如此,该方法显然会在重载时加载继承的方法。 或者我做错了什么?

2 个答案:

答案 0 :(得分:2)

  

我的目标是加载Bclass和Bclass ONLY ......

这是不可能的。

JVM规范(Chapter 5)详细解释了加载类时会发生什么。必须发生的事情之一是解析对直接超类和接口的引用。这需要加载相应的类/接口。

如果(由于某种原因)无法加载超类或接口,则加载子类失败。


  

加载java类方法,文档与方法的行为不一致

getDeclaredMethods()的意外行为是另一个问题。它与类加载无关。

根据此Q&amp; A - Problem in the GetDeclaredMethods (java) - 您正在看到合成&#34;桥接&#34;已添加到Bclass的方法,而不是从Aclass继承的方法。

桥接方法在Java教程here中进行了描述。

您可以使用javap Bclass查看Bclass.class中的代码来确认此问题。请参阅输出中的那些额外桥接方法。

[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();
}

可以通过为每个method.isBridge()对象打印Method来进一步确认(如果需要)。

现在我不明白为什么这个代码需要桥接方法......但这就是它们。


总结:您看到getDeclaredMethods的行为与javadocs一致。您所看到的是最近Java实现的鲜为人知的(但记录!)方面的结果。

答案 1 :(得分:1)

这很奇怪 我认为我没有做错任何事,但我运行你的程序,它只打印Bclass中的方法。我刚刚更改了包,我将AclassBclass放在同一个文件中,因为只有Bclasspublic。输出:

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. 

编译并运行:Sun JDK 1.5.0_22。