2011-12-21 92 views
2

Java有沒有什麼方法可以在運行時獲取編譯時類型的引用?在運行時的編譯時間類型

實施例:

private void doSomething(final Object o) 
{ 
    // do somthing 
} 

final Number n = 1; 
doSomething(n); 

final Object o = 1; 
doSomething(o); 

final Integer i = 1; 
doSomething(i); 

第一呼叫 - >號

第二呼叫 - >對象

第三呼叫 - >整數

編輯:這是一個非常簡單的問題的版本。我想要做的是檢測(而不是被告知)內部框架元數據關於傳遞的對象。可能發生的情況是,該方法先用Integer調用,然後用Double調用,都聲明爲Number。

+1

'getClass()'?也許檢查一下API。 – 2011-12-21 17:03:34

+1

@Dave牛頓將返回整數不是數字。 – Stefan 2011-12-21 17:03:55

+2

這是不可能的。 – SLaks 2011-12-21 17:05:16

回答

2

我看到的唯一方法是使用過載。但是你需要爲繼承關係的每個類指定一個重疊方法來排除子類。

private void doSomething(final Object o) 
{ 
    // do something 
} 

private void doSomething(final Number n) 
{ 
    // do something 
} 

private void doSomething(final Integer i) 
{ 
    // do something 
} 

final Number n = 1; 
doSomething(n); // doSomething(final Number) is called. 
+0

我擔心我不得不使用重載,但我可能能夠限制類型,然後生成代碼。 – Stefan 2011-12-21 17:21:19

+0

畢竟這可能不是那麼糟糕。我可以爲受支持的數據類型創建接口,然後使用代理/處理程序將元數據處理代碼放入其中。客戶甚至可以創建自己的接口,通用的InvocationHandler仍然可以工作。 – Stefan 2011-12-21 17:47:53

1

很簡單,你不能。

您已經知道函數參數的編譯時間(Object),您可以找到傳入的對象的運行時類型(使用getClass())。但是,沒有辦法獲得您要求的信息。

0

使用object.getClass()

private static void doSomething(final Object o) { 
    System.out.println(o.getClass().getSuperclass()); 
} 

private static <T extends Number> void doSomething(final T o) { 
    System.out.println(o.getClass()); 
} 


final Integer n = 2; 
doSomething(n); 

final Double n = 2D; 
doSomething(n); 
+0

返回整數而不是數字。 – Stefan 2011-12-21 17:11:06

+0

@Stefan,看到我的答案 - 你不能擁有Number的實例,因爲Number是一個抽象類。 – Paul 2011-12-21 17:14:49

+0

@Paul看我的編輯 – Stefan 2011-12-21 17:18:46

0

你可以使用 '的instanceof'

public class Test { 
    private static void doSomething(final Object o){ 
    if(o instanceof Number){ 
     System.out.println("it's a number!"); 
    } 
    System.out.println("canonical class : "+o.getClass().getCanonicalName()); 
    } 
    public static void main(String[] args) { 
    Number n = new Integer(10); 
    doSomething(n); 
    } 
} 

打印出

it's a number! 
canonical class : java.lang.Integer 

Anoth呃選項是遞歸查詢超

public class Test { 
    private static Class<?> doSomething(final Object o){ 
    // assuming o is not null 
    Class<?> klass = getSuperClass(o.getClass()); 
    return klass; 
    } 

    private static Class<?> getSuperClass(Class<?> klass){ 
    // if super class is object or null break recursion 
    if(klass.getSuperclass() == null || klass.getSuperclass().equals(Object.class)){ 
     return klass; 
    } 
    // keep looking higher up 
    return getSuperClass(klass.getSuperclass()); 
    } 

    public static void main(String[] args) { 
    Number n = new Integer(10); 
    System.out.println("n is a "+doSomething(n).getCanonicalName()); 
    Object o = new Integer(10); 
    System.out.println("o is a "+doSomething(o).getCanonicalName()); 
    Number d = new Double(10.0d); 
    System.out.println("d is a "+doSomething(d).getCanonicalName()); 
    String s = "10"; 
    System.out.println("s is a "+doSomething(s).getCanonicalName()); 
    Object so = "10"; 
    System.out.println("so is a "+doSomething(so).getCanonicalName()); 
    } 
} 

打印出

n is a java.lang.Number 
o is a java.lang.Number 
d is a java.lang.Number 
s is a java.lang.String 
so is a java.lang.String 
+0

請參閱編輯。我不知道什麼對象正在通過。我試圖'檢測'編譯時間類型。 – Stefan 2011-12-21 17:19:41

+0

在這種情況下,我會推薦方法重載並查看實際調用哪個方法。 – 2011-12-21 18:09:52

+0

我將嘗試重載。 – Stefan 2011-12-21 18:17:07

0

你不能。 Integer是正確的答案,因爲Number是一個抽象類,您不能擁有抽象類的實例,並且您依靠自動裝箱來轉換基元int

+0

它的抽象無關緊要。我試圖獲得編譯時的類型,這實際上是數字。請參閱編輯。 – Stefan 2011-12-21 17:16:26

+0

你不能有一個實例,但你可以有一個參考;那就是 - 一切就是這樣。 – 2011-12-21 17:25:47

+0

@DaveNewton,一個實例是一個參考。在Java中,將實例傳遞給另一個方法只是傳遞引用(通過值傳遞)。 – Paul 2011-12-21 17:55:13