正在加载 java class 方法,文档与方法的行为不一致

Loading java class methods, docs not consistent with method's behavior

所以我有 2 类 运行 在 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,打印出其声明的方法和那些声明的方法的参数。 这是我使用的代码:

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 ,根据我的测试,情况似乎并非如此,该方法显然会在重载时加载继承的方法。 还是我做错了什么?

My goal is to load Bclass, and Bclass ONLY ...

不可能。

JVM 规范 (Chapter 5) 非常详细地解释了加载 class 时必须发生的情况。必须发生的事情之一是对直接 superclasses 和接口的引用被解析。这需要加载相应的 classes / 接口。

如果(出于某种原因)无法加载超级classes 或接口,则加载子 class 失败。


Loading java class methods, docs not consistent with method's behavior

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

根据此问答 - Problem in the GetDeclaredMethods (java) - 您看到合成 "bridge" 方法已添加到 Bclass 而不是从 Aclass.[=24 继承的方法=]

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 对象打印 method.isBridge() 来进一步确认(如果需要)。

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


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

很奇怪
我想我没有做错,但我 运行 你的程序,它只打印 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。