保留已编译的java类中的参数/参数名称

时间:2009-06-02 12:14:29

标签: java eclipse compilation javac

当我编译这样的东西时:

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)允许我提供指向源代码的链接或者MyClass的javadoc (如Bishiboosh所指出的)并且可以利用这个。但我很好奇是否有某种方法告诉javac将名称包含在类文件中,以便该类的用户可以看到参数名称,即使它们只有类文件。

班级解决方案

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

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

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

但没有接口解决方案

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

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

我的第一个问题只是要求上课,因为我不知道可能有任何不同。

班级档案格式

正如 gid 所指出的,类文件格式不支持参数名称的存储。我发现了一个section in the class file spec,它描述了一个数据结构,它应该保留方法的参数名称,但在编译接口时绝对不会使用它。

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

6 个答案:

答案 0 :(得分:8)

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

编译以下来源:

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路径(附上源代码)。

答案 1 :(得分:6)

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

答案 2 :(得分:5)

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

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

答案 3 :(得分:2)

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

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

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

抱歉无法提供更多帮助

修改: 我完全更正了......类文件格式显然有空间用于命名参数(JLS 4.7

我看不到你是如何使用java.lang.reflect.*

来获取他们的

答案 4 :(得分:1)

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

答案 5 :(得分:0)

您不需要单独的Javadoc文件,您可以在Eclipse中使用带有两个星号(*)的特殊注释在多行注释的第一个斜杠后创建'inline'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)
    {
        ...
    }
}