从类名获取Java源代码

3

有没有一种方法可以通过类名获取Java源代码?

例如,如果我可以访问具有类java.io.File的库,我想要它的源代码。

我正在开发一种解析器,并且需要在执行时获取源代码。 我还需要递归搜索它。

假设上述类具有此方法:

int method (User user) {...}

我需要获取User的源代码,以及它内部类的相关内容。


@ZoogieZork:在你使用IDE浏览源代码之前,你需要先有真实的源代码。 - Dolph
1
我想在执行过程中操作代码。 - Federico Lenzi
8个回答

9

有没有一种方法可以从类名中获取Java源代码?例如:...

您可能需要几种可能的解决方案。如果不知道您真正想要使用信息做什么,我们无法对我们的建议非常精确,但我会建议您尽可能远离源代码。 JSE源代码 可以在线获得,许多开源库也可以,但这并不总是情况。此外,当您想要找到它时,您需要将其全部组织起来,就像一个类路径一样,而Class对象则更容易获取和操作,而无需再次解析文本。

反射

如果您只需要在运行时了解类的信息,请使用Java反射API。借助它,给定一个Class对象,您可以例如获取特定字段的类型、列出所有字段并遍历它们等等:

Class clazz = User.class;
Field field = clazz.getDeclaredField("var");
System.out.println(field.getType().getName());

反射对于发现程序中的类信息非常有用,你可以遍历整个树而不必查找源代码或解析任何内容。
记住,只要在运行时类路径上,你就可以使用 Class.forName("MyClass") 查找一个类对象,并反射其结果。
字节码操作
如果你需要更多的信息,并且真正想要操作这些类,你需要字节码操作。一些人尝试生成源代码、编译成字节码并加载到他们的程序中,但相信我——使用可靠的字节码操作 API 要简单得多。我推荐使用 ASM
使用它,你不仅可以获取关于类的信息,还可以添加新字段、新方法、创建新类……甚至可以加载多个变体的类,如果你感觉自己受虐。使用 ASM 的示例可以在这里找到
反编译
如果你真的、真的需要源代码,而没有可用的源代码,则可以使用各种反编译器从类对象中反编译。它们使用与以上两种相同的信息和技术,但会进一步尝试生成源代码。请注意,它并不总是有效。我推荐使用 Jode,但你可以在网上找到一个不错的列表和比较其他工具。
文件查找
如果你有源代码,只是想查找一下,也许你只需要将 .java 文件放在一个大树型结构中,并根据需要基于包名称检索。
Class clazz = User.class;
String path = clazz.getPackage().getName().replaceAll("\\.","/");
File sourceFile = new File(path, clazz.getName() + ".java")

您需要增加更多的逻辑来检查类类型,因为显然原始类型没有类定义,并且您需要以不同的方式处理数组类型。

您可以使用Class.forName("MyClass")按名称查找类(如果.class文件在您的类路径上)。


谢谢,我是新来的,问题有点不完整。我采用了文件查找的方式,因为我需要方法和字段的javadoc和注释,所以反射不是最好的选择。 - Federico Lenzi

3
最好且最简单的方法可能是使用javap。请参见javap
hello.java。
public class hello
{
    public static void main(String[] args)
    {
    System.out.println("hello world!");
    world();
    }

    static public void world()
    {
    System.out.println("I am second method");
    }
}

执行javap hello命令,您将得到以下结果:

Compiled from "hello.java"
public class hello extends java.lang.Object{
    public hello();
    public static void main(java.lang.String[]);
    public static void world();
}

它只是反汇编一个类文件。你说的“它可以使用Javadocs”是什么意思? - zengr
我想从源代码中获取javadoc。 - Federico Lenzi
1
您还可以使用 javap -c hello 来获取更详细的结果。 - Searene

3

您可以使用您选择的JAVA反编译器从类文件中获得源代码的良好近似值。但是,如果您真的想获取java.io.File的源代码,则可以下载它。


2

是的,如果您下载源代码。它可以在官方下载页面上公开下载。

如果您正在使用Eclipse,并且每当您使用该类时,您可以右键单击>查看源代码(或简单地单击类> F3),它将打开一个带有源代码的新选项卡。


源代码是JDK的一部分,可以在Java主目录(由JAVA_HOME指向)中查找src.zip。 - Steve Kuo
我该如何在程序中获取它? - Federico Lenzi

2
你可以使用以下代码打印出加载类的资源路径:
URL sourceURL=obj.getClass().getProtectionDomain().getCodeSource().getLocation();

它将是一个 .class 文件、.jar、.zip,或其他形式。


0

所以你想要做的是在执行时获取Java类。为此,你需要Java反射


0
如果您的目标是获取有关类中内容的信息,您可能会发现Java反射API是一种更简单的方法。您可以使用反射在运行时查找类的字段、方法、构造函数、继承层次结构等,而无需拥有该类的源代码。

0
有没有办法通过类名获取Java源代码?
答案比较复杂,主要是因为你的问题不够明确。(举个例子)
  • 通常情况下,无法获取类的真实、实际的Java源代码。

  • 如果您有(例如)包含类源代码的ZIP或JAR文件,则可以根据类的完全限定名称提取相关源文件。但是,首先必须从某个地方获取这些ZIP/JAR文件。

  • 如果您只对方法签名、属性名称和类型等感兴趣,则大部分信息可在运行时使用Java反射API获得。但是,它取决于类是否使用调试信息编译(请参见javac编译器的-g选项),将有多少信息可用。而且这与您可以从真正的源代码中获得的信息远远不同。

  • 反编译器可能能够从字节码文件生成可编译的类源代码。但是,反编译的代码看起来与原始源代码完全不同。

  • 我猜,如果您有一个填充了类javadoc的网站的URL,您可以从类名、方法名或公共属性名转到相应的javadoc URL。您甚至可以从javadoc中“屏幕截取”描述。但是再次强调,这不是真正的源代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接