簡體   English   中英

在已編譯的 Java 類中保留參數/參數名稱

[英]Preserving parameter/argument names in compiled Java classes

當我編譯這樣的東西時:

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 (正如 Bishboosh 指出的那樣)的鏈接,並且可以利用這一點。 但是我很好奇是否有某種方法可以告訴javac將名稱包含到類文件中,以便該類的用戶即使只有類文件也可以看到參數名稱。

班級解決方案

當我使用java -g:vars編譯一個類時,參數的名稱包含在類文件中。 -g:vars似乎相當於Eclipse -> project properties -> Java compiler -> Add variable attributes to generated class files

這個解決方案是由幾位作者提出的,但尼克的回答最終讓我相信了。

在我的機器上,Eclipse 有時使用此信息,有時沒有,這可能是我的錯或 Eclipse 中的錯誤,但不是類文件或編譯的問題。 無論如何,現在我知道信息肯定存在。

但是沒有接口的解決方案

雖然這適用於類(有點)好,但它不適用於接口。

對我來說,合乎邏輯的原因似乎是, -g:vars只提供局部變量的名稱,這也是 javac 的文檔所指出的。 在方法體中,它的參數與局部變量非常相似,因此它們被-g:vars覆蓋。 接口方法沒有主體,所以它們不能有局部變量。

我最初的問題只要求上課,因為我不知道可能會有任何區別。

類文件格式

正如gid所指出的,類文件格式不支持存儲參數名稱。 在類文件規范中找到了一個部分,它描述了一個數據結構,它應該包含方法的參數名稱,但這在編譯接口時絕對不會使用。

在編譯一個類時,我無法判斷是否使用了提到的數據結構,或者 Eclipse 是否根據方法體內參數的使用來推斷參數名稱。 專家可以澄清這一點,但我認為這並不重要。

要在類文件中保留名稱以進行調試,請嘗試項目屬性、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 路線(附加源代碼)。

您不需要特別需要源來使 arg 名稱出現在 Eclipse 中...如果您指定 Javadoc,Eclipse 將顯示 args。

使用調試支持進行編譯可能會有所幫助,它將所有名稱存儲在 .class 文件中。

雖然我不知道 Eclipse 是否考慮到這一點。

無論您使用什么 javac 選項,類文件數據結構都不支持將參數名稱存儲到任何方法。

為了在 IDE 中查看原始名稱,您必須為它們提供 javadoc 或源代碼。

如果您特別需要在運行時獲取它們,則可以為參數添加注釋,但您必須創建自己的注釋,因為沒有可使用的標准集。

抱歉不能再有幫助了

編輯:我完全糾正了......類文件格式確實有命名參數的空間( JLS 4.7

我看不到的是你怎么能用java.lang.reflect.*

如果您在類文件中包含調試信息,Eclipse 將獲取參數的名稱: javac -g:vars應該足夠了。

您不需要單獨的 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)
    {
        ...
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM