17

当我编译这样的东西时:

public class MyClass
{
    void myMethod(String name, String options, String query, String comment)
    {
        ...
    }
}

并将其编译为类文件,似乎参数名称丢失了。也就是说,当一些其他 Java 代码引用MyClass并想要调用或覆盖myMethod时,我的 IDE(当前为 Eclipse)似乎从类文件中获取此方法签名:

void myMethod(String arg0, String arg1, String arg2, String arg3);

我知道 Eclipse(也可能还有其他 IDE)允许我提供指向源代码或 javadoc (正如 Bishboosh 指出的那样)的链接,MyClass并且可以利用这一点。但是我很好奇是否有某种方法可以告诉javac将名称包含到类文件中,以便该类的用户即使只有类文件也可以看到参数名称。

班级解决方案

当我用 编译一个类时java -g:vars,参数的名称包含在类文件中。-g:vars似乎相当于 Eclipse -> 项目属性 -> Java 编译器 -> 将变量属性添加到生成的类文件中。

这个解决方案是由几位作者提出的,但尼克的回答最终让我相信了。

在我的机器上,Eclipse 有时使用此信息,有时没有,这可能是我的错或 Eclipse 中的错误,但不是类文件或编译的问题。无论如何,现在我知道信息肯定存在。

但是没有接口的解决方案

虽然这适用于类(有点)好,但它不适用于接口。

对我来说,合乎逻辑的原因似乎是, -g:vars 只提供局部变量的名称,这也是 javac 的文档所指出的。在方法体中,它的参数与局部变量非常相似,因此它们被 -g:vars 覆盖。接口方法没有主体,所以它们不能有局部变量。

我最初的问题只要求上课,因为我不知道可能会有任何区别。

类文件格式

正如gid所指出的,类文件格式不支持存储参数名称。我在类文件规范中找到了一个部分,它描述了一个数据结构,它应该包含方法的参数名称,但这在编译接口时绝对不会使用。

在编译一个类时,我无法判断是否使用了提到的数据结构,或者 Eclipse 是否从方法体内参数的使用情况推断出参数名称。专家可以澄清这一点,但我认为这并不重要。

4

6 回答 6

8

要在类文件中保留名称以进行调试,请尝试项目属性、Java 编译器,然后“将变量属性添加到生成的类文件”(参见Eclipse 帮助)。

编译以下源码:

public class StackOverflowTest {
    public void test(String foo, String bar) {
        // blah
    }
}

被反编译成:

// Compiled from StackOverflowTest.java (version 1.5 : 49.0, super bit)
public class StackOverflowTest {

    // Method descriptor #6 ()V
    // Stack: 1, Locals: 1
    public StackOverflowTest();
        0  aload_0 [this]
        1  invokespecial java.lang.Object() [8]
        4  return
        Line numbers:
            [pc: 0, line: 1]
        Local variable table:
            [pc: 0, pc: 5] local: this index: 0 type: StackOverflowTest

    // Method descriptor #15 (Ljava/lang/String;Ljava/lang/String;)V
    // Stack: 0, Locals: 3
    public void test(java.lang.String foo, java.lang.String bar);
        0  return
        Line numbers:
            [pc: 0, line: 4]
        Local variable table:
            [pc: 0, pc: 1] local: this index: 0 type: StackOverflowTest
            [pc: 0, pc: 1] local: foo index: 1 type: java.lang.String
            [pc: 0, pc: 1] local: bar index: 2 type: java.lang.String
}

请参阅参数名称保留在类文件中。

我建议您查看您的源代码是如何编译的,它是为哪个版本编译的等等。

编辑:

啊,我看到这对于接口来说是不同的——它们似乎没有可用于调试器的这些信息,我认为这是有道理的。我认为没有办法解决这个问题,如果您只想在编辑源代码时查看参数名称,则需要按照 Nagrom_17 的建议走 javadoc 路线(附加源代码)。

于 2009-06-02T13:17:04.067 回答
7

您不需要特别需要源来使 arg 名称出现在 Eclipse 中...如果您指定 Javadoc,Eclipse 将显示 args。

于 2009-06-02T12:17:34.607 回答
5

使用调试支持进行编译可能会有所帮助,它将所有名称存储在 .class 文件中。

虽然我不知道 Eclipse 是否考虑到这一点。

于 2009-06-02T12:26:10.080 回答
2

无论您使用什么 javac 选项,类文件数据结构都不支持将参数名称存储到任何方法。

为了在 IDE 中查看原始名称,您必须为它们提供 javadoc 或源代码。

如果您特别需要在运行时获取它们,则可以为参数添加注释,但您必须创建自己的注释,因为没有可使用的标准集。

抱歉不能再有帮助了

编辑:我完全纠正了......类文件格式确实有命名参数的空间(JLS 4.7

我看不到的是你怎么能用它们来对付他们java.lang.reflect.*

于 2009-06-02T12:45:33.553 回答
1

如果您在类文件中包含调试信息,Eclipse 将获取参数名称:javac -g:vars应该足够了。

于 2009-06-02T12:32:14.607 回答
0

您不需要单独的 Javadoc 文件,您可以在多行注释的第一个斜杠后使用带有两个星号 (*) 的特殊注释在 Eclipse 中创建“内联”javadocs。

示例代码:

   public class MyClass
{
 /**
  * documentation of your method
  * 
  * @param name    a String describing the name
  * @param options used to describe current option
  * @param query
  * @param comment
  * @return void
  */
    void myMethod(String name, String options, String query, String comment)
    {
        ...
    }
}
于 2009-06-02T12:32:52.237 回答