2013-01-17 37 views
4

如何在不使用類名的情況下獲取靜態方法中的Class對象?

public class A { 
    static X s_x = new X(A.class); 
} 

public class B { 
    static X s_x = new X(B.class); 
} 

等許多類別沒有任何特殊關係或共性。我真正希望我能做的是在超類中初始化s_x,但使用特定於子類的代碼;這是不可能的,因爲靜態代碼是不可覆蓋的。所以,我想至少讓我的複製粘貼更容易。我想要一個魔法表達式求值爲類對象,即寫:

static X s_x = new X(/* magic expression here */); 

其中魔術表達是無論相同,其中我聲明我的X中的類的,但確實與上述相同的例子。次優選項將是一種靜態方法來達到同樣的效果。

注:

  • Java 6中如果可能的話。
  • 這個問題不(一定)有關記錄...
+2

確實類'A'和類'B'有某種形式的關係呢? –

+0

@BuhakeSindi:無。編輯更清楚。 – einpoklum

+0

您可以使用getClass()方法。 –

回答

0

一些問題的答案在這裏有一個解決方案的想法,但不完全的代碼片段,我需要。所以這裏,在任何JVM工作:

static X s_x = new X(getClassStatic()); 

public static Class<?> getClassStatic() { 
    try { 
     // we're using the third highest stack element, since the 
     // first highest is the getStackTrace() method, followed by this method itself. We 
     // want the calling code's class. 
     String name = Thread.currentThread().getStackTrace()[2].getClassName(); 
     return Class.forName(name); 
    } catch (ClassNotFoundException e) { 
     // shouldn't be able to get here... 
     return null; 
    } 
} 

,或者選定的JVM,按照彼得Lawrey的建議:

static X s_x = new X(getCallerClass(1)); 
1

我也有過這樣奇怪的要求一次,我試圖尋找,但沒有發現任何東西,所以我想答案是這是不可能的可能。

但我被告知要重新考慮我的方法,並且當我試着找出沒有這個奇怪要求的同樣的解決方案。所以請重新考慮你的方法。我相信你能像我一樣解決它。此外,如果您可以發佈您正在嘗試解決的問題/場景,可能是我可以提供幫助。

+0

你其實是對的,你的回答不僅激勵我自己提供一個答案,而且讓那些讓我使用這段代碼的人嘗試以另一種方式嘗試。 – einpoklum

0

我認爲唯一的解決辦法是從目前的堆棧跟蹤(見Thread.getStackTrace()),這將給它給你作爲一個String,從中可以得到使用Class.forName(String)一個Class對象中提取類的名字,但這是多少比你目前的方法更醜陋。

1

在Java 7中,可以使用類java.lang.invoke.MethodHandles此:

Class c = MethodHandle.lookup().lookupClass() 

你可能會得到關於使用原始類型,而不是參數化版本的警告Class<X>,但我看不出你如何能避免在沒有恢復到自己對類名進行硬編碼的情況下。

1

在熱點/ OpenJDK的,你可以使用

Class c = Reflection.getCallerClass(1) 

注:這是一個內部API,並可能無法在所有JVM工作。

0

你可以做到這一點,但需要在你的方法,一些重新分解:

嘗試了這一點:

class X 
{ 

    public X(String cName) 
    { 
    try 
    { 
     Class.forName(cName); 
     }catch(ClassNotFoundException cne) 
     {} 
    } 
} 

public class Test 
{ 
    static X x1 = new X(Thread.currentThread().getStackTrace()[1].getClassName()); 
} 
0

如果你想創建一個日誌對象,你可以使用lombok注入一個記錄對象給你。從頁面 示例:

@Log 
public class LogExample { 

    public static void main(String... args) { 
    log.error("Something's wrong here"); 
    } 
} 
1

這裏是一個一行應在的Java 5+ JVM和工作不添加任何額外的進口代碼:

new Object(){}.getClass().getEnclosingClass() 

它創建一個匿名內部類,獲取其Class對象,然後得到它包圍類的實例,這應該是你的類。例如:

public class HelloClass { 
    static final Class<?> THIS_CLASS = new Object(){}.getClass().getEnclosingClass(); 

    public static void main(String[] args) { 
     System.out.println(THIS_CLASS); // prints "class HelloClass" 
    } 
} 

在你的問題的情況下:

static X s_x = new X(new Object(){}.getClass().getEnclosingClass()); 
+0

不錯......看起來這可以在編譯時進行優化,而不是查看堆棧跟蹤。然而,你不能真的把它放在一個方法中,而new()很醜陋。 – einpoklum

相關問題