2013-11-26 32 views
3

有關我所指的示例,請參閱Boolean#TYPE原始包裝和靜態「TYPE」類對象

所有的包裝類(布爾,雙精度,整數等)都有一個與它們相關的靜態類字段,稱爲TYPE。這是什麼意思?

具體來說,這裏有一些軟測試:

System.out.println(Boolean.class == Boolean.TYPE); 
System.out.println(Boolean.TYPE.isInstance(Boolean.valueOf(true))); 

兩個評估爲假。 (而作爲邊注,一個.equals比較是不必要的,因爲類不覆蓋從Object等。)

兩個Boolean.classBoolean.TYPEClass<Boolean>,因爲它們是==可比沒有發生錯誤。將兩個對象與不同的聲明通用類型進行比較是非法的。

在進一步檢查,TYPE字段由沿着下面的行調用包專用本地方法Class#getPrimitiveClass檢索到:

public static final Class<Boolean> TYPE = Class.getPrimitiveClass("boolean"); 

在方法本身的註釋,沒有特別信息要麼。它表示它返回VM的類對象,因爲它是一個本地方法,所以它非常明顯。

除了Java文檔中對「表示原語類型」的模糊暗示,我無法找到任何關於此的文檔。這個領域有什麼用途嗎?它在包裝類本身中未被使用。

(編輯)

System.out.println(boolean.class == Boolean.TYPE); 

是真實的。

還一個用途是再反思:

try { 
    Constructor ctor = Boolean.class.getConstructor(Boolean.class); 
} catch (Exception e) { 
    System.out.println("NoSuchMethodException gets thrown"); 
} 

try { 
    Constructor ctor = Boolean.class.getConstructor(Boolean.TYPE); 
    System.out.println(ctor.newInstance(true)); 
} catch (Exception e) { 
    // (no exception thrown) 
} 

而且我發現,引用一些SO線程,如this one。我想我是從谷歌的「錯誤的結局」中發現的,所以沒有找到任何結果。

但考慮到「原始類」(boolean.class,int.class等)的存在,並沒有真正解釋TYPE字段的存在。基本上它是「在那裏」?我仍然不明白。

回答

4

表示基元類型的類在指定或檢查接收或返回基元的方法時很有用。例如,如果你的類有一個看起來像這樣

class Test { 
    static int round(float val) {...} 
} 

的方法,你希望通過反射來訪問這個方法,你需要做的是:

Method round = Test.class.getMethod("round", Float.TYPE); 

您可以檢查返回值類型,太:

if (round.getReturnType == Integer.TYPE) { 
    System.out.println("Method 'round' returns an int."); 
} 

使用Float.class代替

Method round = Test.class.getMethod("round", Float.class); 

是行不通的,因爲這會拉一個不同的方法 - 這一個:

static int round(Float val) {...} 
+0

+1換句話說,'Float.TYPE'指的是實際的原始類,但是'Float.class'返回到擴展Object的包裝類型。 – mellamokb

+0

@mellamokb正確,這就是發生了什麼。 – dasblinkenlight

+0

你知道是否有任何區別,比如'Float.TYPE'和'float.class'?我的意思是*技術*,而不僅僅是*在使用*因爲它們在運行時顯然是相同的對象。 – Radiodef

1

(不要有代表發表意見,所以必須回答)

說得簡明扼要:Float.TYPE == float.class ,和Float.class != float.class。試想一下:

class Test { 
    void func() { 
     Class clazz; 
     // The two statements do the same thing. On my system, they even compile 
     // to the same bytecode. 
     clazz = Integer.TYPE; // explicitly asking for this 
     clazz = int.class;  // must yield the same object as above. 

     // Both of these below are valid, as the `true' is autoboxed. In 
     // Java < 1.5, both had to be explicitly boxed 
     Test.class.getMethod("test", Boolean.class).invoke(this, true); 
      // calls method A 
     Test.class.getMethod("test", boolean.class).invoke(this, true); 
      // calls method B. Could also use getMethod("test", Boolean.TYPE) 
    } 

    void test(Boolean b) { System.out.println("Method A"); } 
    void test(boolean b) { System.out.println("Method B"); } 
} 

我會假設這兩個int.classInteger.TYPE已經出現從Java的開始,雖然我可能是錯的。 Integer.TYPE最初可以分配Class.getPrimitiveClass("int")

+0

在做了一些更多的搜索之後,我發現.class文字基本上只是.TYPE字段的快捷方式。它們都是在反射API(Java 1.1)的同時添加的,文字在編譯期間(可能)被替換爲類似於自動裝箱。 – Radiodef

+0

*「...文字在編譯期間(可能)被替換...」*我想編譯到相同的字節碼證明它。 – Radiodef