2011-04-20 39 views
24

在靜態環境中,你怎麼不能調用getClass()的靜態版本(而不是使用my.package.name.MyClassName.class)?爲什麼getClass()不能用作靜態方法?

編譯器是否足夠聰明以確定何時使用對象方法+何時使用靜態方法?


注意爲清楚起見:

我不是說一個static getClass()應使用代替非靜態方法getClass()(這是一種明顯的 - 如果SpecialFooFoo一個子類,那麼FoogetClass()可能會返回Foo.classSpecialFoo.class或別的東西,它必須在運行時確定)。

我是說,我不知道爲什麼沒有2個版本getClass(),一個是隻適用於靜態上下文靜態方法,並定期非靜態方法getClass()。如果這是不可能的,那麼這是不可能的,這就是答案。如果可能但尚未完成,那麼這是一個歷史選擇,也許這是一個很好的理由。這就是我想知道的。

這將是巨大的申報

final static Logger logger = LoggerFactory.getLogger(getClass()); 

,而不是

final static Logger logger = LoggerFactory.getLogger(my.package.name.MyClass.class); 

其中前者可以逐字從一個類被複制到下一個,而後者會要求您複製類名在每個文件中。

+0

好問題。 Groovy允許'this'在靜態上下文中引用* current類;-) – 2011-04-20 16:17:58

+0

可能是因爲在運行時靜態方法沒有任何類上下文。 – halfdan 2011-04-20 16:19:39

+0

權,但是從編譯器的角度來看,當你調用一個靜態方法'FOO()',它知道'FOO()'指的是靜態方法。我想我問的是爲什麼沒有返回內建靜態'.class'字段的'getClass()'靜態方法。 – 2011-04-20 16:21:57

回答

3

如果不出意外,因爲這是不合法的既有static和非static版本的方法(可能是因爲它是合法的,如果氣餒,調用static方法在非static上下文)。

我也覺得像這樣的方法,而在定義記錄器或任何的上下文中,可能是在其他情況下,如從實例方法調用時造成混淆。

7

每個對象都是Java類中的一個類的實例,並且任何類都不能成爲另一個類的實例!這就是爲什麼getClass()不是靜態的,因爲它只在一個對象的上下文中才有意義:你正試圖爲一個對象尋找它是哪個類的實例。 如果它是一個靜態的功能,它可以被稱爲一個對象外 - 但它沒有意義的寫

String.getClass() 

,因爲你已經知道你是「問」 String類!

+0

沒錯 - 我知道在寫我的問題的時候。查看編輯。 – 2011-04-20 16:32:39

+1

它沒有增加使用類*的值,但是它增加了在類內使用*的值。 – 2011-04-20 16:34:46

2

因爲如果getClass()是靜態的,它的代碼將不得不在一個類中定義 - 可能是Object。在那裏,您無法確定調用者類,並且沒有調用它的對象實例。

編輯:

這不是關於名稱;它可能會很好getClass2()。我在說,如果你定義了一個靜態方法,你不能知道調用它的類:

public class Object { 

    public static Class<?> getClass2() { 
     return ...? 
    } 

} 
+2

在Enum.getValues()方法中有一個類似的技巧:它是一個靜態方法,可用於每個'enum'(又名「java.lang.Enum'的每個子類)。在這裏可以想到類似的東西。 – 2011-04-20 16:23:14

+0

我並不是說它應該代替非靜態方法getClass()(這很明顯 - 如果'SpecialFoo'是'Foo'的子類,那麼'getClass()'的'getClass一個'Foo'可以返回'Foo.class'或'SpecialFoo.class'或其他)。我在說靜態上下文爲什麼沒有第二個* static *版本的getClass()。 – 2011-04-20 16:27:36

+1

@Jason S - 你不能聲明兩種只區分靜態關鍵字的方法:) – 2011-04-20 16:29:43

5

getClass()提供了與靜態.class不同的功能。它用於獲取所調用實例的運行時類。

Object o = new String(); 
o.getClass() // returns Class<String>  
Object.class // returns Class<Object> 
+0

是的,當然 - 對不起,我在原來的問題中沒有說清楚。看我的編輯。 – 2011-04-20 16:35:38

+1

Gotcha,似乎有人已經給出了這個答案,但最有可能的原因是你不能僅僅使用static關鍵字來重載方法名。您需要使用不同名稱或參數的第二種方法。我的猜測是,他們認爲這將是不必要的和/或混淆添加第二個getClass方法。我想他們想通過使用靜態.class屬性沒有人會有問題。 – Jberg 2011-04-20 16:53:02

1

會不會有靜態getClass()方法返回類對象類的持有對象的變量是從哪裏來的?這將改變getClass()的語義。例如:

​​
1

除了其他答案(這解釋了爲什麼我們不能使用與非靜態的'getClass()'方法相同的簽名來創建靜態方法),人們會想知道是否有可能說, static Class getStaticClass()因此,例如String.getStaticClass()將相當於String.class。但是,這種方法再次不能成爲「正常」的方法,它將在何處被定義?在對象?那麼當這個方法被稱爲String.getStaticClass()或Object.getStaticClass()時,該方法如何知道返回的內容(String.class或Object.class)?它會在運行時決定嗎?沒門。因爲String.class在編譯時已知的(解決)

靜態方法沒有任何意義。該方法在運行時沒有合理的事情要做;你必須做一些編譯魔術,以便在編譯時實際解析該方法調用的結果。

2

你可以自己實現一個。獲取堆棧跟蹤,並找到調用者類。

其實記錄的lib可以實現本身

static Logger logger = LoggerFactory.getLogger(); // auto detect caller class 
25

你可以使用這個成語

Class<?> cl=new Object(){}.getClass().getEnclosingClass(); 

例如:

static class Bar { 
    public static void main(String[] args) { 
     Class<?> cl=new Object(){}.getClass().getEnclosingClass(); 
     System.out.println(cl==Bar.class); //will print true 
    } 
} 
+0

+1 ...有趣! – 2012-02-10 04:35:59

+0

我總是用這個方法得到null。它依賴於Bar是一個靜態類嗎? – 2013-11-19 21:36:42

+1

你可能寫了'new Object()。getClass()。getEnclosingClass()'。正確的方法是使用'new Object(){}',它定義並實例化一個基於'Object'的匿名類。 – wdscxsj 2014-08-26 06:01:39

相關問題