2010-08-24 24 views
2

我發現以下問題: $0 (Program Name) in Java? Discover main class? 但接受的答案在這種情況下失敗:

public class Derived extends Base { } 

class Base { 
    public static void main(String[] args){ 
     System.out.println(getTheClassName()); 
    } 

    static String getTheClassName(){ 
     StackTraceElement[] stack = Thread.currentThread().getStackTrace(); 
     StackTraceElement main = stack[stack.length - 1]; 
     return main.getClassName(); 
    } 
} 

當調用:

java Derived 

輸出不幸BaseDerived預期。

是否有可能獲得real的主名? (順便說一句,jps工具正確檢測主類,但要獲得正確的名稱,我需要知道當前VM的ID,這也是一個問題)

此致敬意。

編輯:準確地說:我需要知道作爲傳遞給JVM的命令行參數傳遞的類的名稱是什麼。 jps工具以我想要的方式進行,但由於其他問題(如未知的VMid),我無法使用此工具。

EDIT2:全球答覆托爾比約恩的回答:

爲了您的工作方式,你需要有一個非靜態方法來代替。讓它 非靜態,有一個main()的派生做一個新的衍生()。getTheClassName()

我想知道我能得到的名稱無須在派生類主要方法。

解決方案:我將提供兩種(Thorbjørn's和erickson's)初始化類的機制;-)所有的答案都非常有幫助。我接受Thorbjørn的回答,因爲他早於erickson發佈了他的答案。謝謝。

回答

5

靜態方法屬於它們定義的類,而不是類的實例(與靜態/非靜態方法相同)。因此,當你在getTheClassName中時,你處於Base類中定義的靜態方法中。

對於您的工作方法,您需要改爲使用非靜態方法。使其成爲非靜態的,在Derived中有一個main()做一個新的Derived()。getTheClassName()

+0

我知道你已經發布的解決方法,但我想知道,如果不在'Derived'類中實現'main'方法,我可以得到名稱。 – 2010-08-24 20:30:57

+0

據我所知,這在純Java中是不可能的。不過,您可以通過JMX或JVM特定的方法向HotSpot詢問此問題,但這可能是供應商特定的解決方案。你爲什麼需要這個? – 2010-08-24 20:34:05

+0

我需要這樣的某種應用程序框架:我將提供主要方法的實現;框架的用戶只能從'Base'類派生,並且能夠使用我的* boostted *'main'運行他/她的類。 – 2010-08-24 20:42:02

3

main入口點位於Base時,您爲什麼期望Derived?聲明爲static的成員屬於其,並且不會繼承。當按原樣運行程序時,將不會加載類Derived,因爲它從未被引用。


考慮將派生類的名稱作爲Base類的參數。除了使目標類明確外,它可能是實現其他功能的便利之處。

class Base { 
    public static void main(String... argv) throws Exception { 
    Class<?> clz = Class.forName(argv[0]); 
    Method mth = clz.getMethod("main", String[].class); 
    String[] sub = new String[argv.length - 1]; 
    System.arraycopy(argv, 1, sub, 0, sub.length); 
    mth.invoke(null, sub); 
    } 
} 
+0

我期待'Derived',因爲正如我說,'jps'工具輸出'Derived'到'stdout'。確切地說:我需要知道,什麼類(或類文件)最初作爲命令行參數傳遞給'java'命令。 – 2010-08-24 20:27:23

+0

哇,我很驚訝發射器接受'Derived'作爲類名,因爲它不包含'main'方法。 'jps'實用程序必須訪問傳遞給本地C'main'方法的'argv [0]'信息。 – erickson 2010-08-24 20:32:16

+0

我已經看了一下實現 - 它使用'MonitoredHost'和'MonitoredVm'類。 – 2010-08-24 20:36:35

1

試試這個:

for(final Map.Entry<String, String> entry : System.getenv().entrySet()){ 
    if(entry.getKey().startsWith("JAVA_MAIN_CLASS")) 
     return entry.getValue(); 
} 

不過還是你應該看看別人的答案。即使這樣做,這是一個非常糟糕的做法。