簡體   English   中英

Integer.class 與 int.class

[英]Integer.class vs int.class

Integer.classInteger.TYPEint.class之間有什么區別?

接受我

  1. Integer.class是 Integer (Wrapper) Class 對象的引用
  2. 但是什么是int.class作為int不是一個類,它是一個原始類型。 Integer.TYPE指的是什么?

正如您所說, Integer.class是對Integer類型的Class對象的引用。

int.class是,相似性,是對int類型的Class對象的引用。 你說得對,這聽起來不對; 作為特例,原語都有一個Class對象。 如果你想區分foo(Integer value)foo(int value) ,它對於反射很有用。

Integer.TYPE (不是Integer.type ,請注意)只是int.class的快捷方式。

您可以通過一個簡單的程序了解這一點:

public class IntClasses {
  public static void main(String[] args) {
    Class<Integer> a = int.class;
    Class<Integer> b = Integer.TYPE;
    Class<Integer> c = Integer.class;

    System.out.println(System.identityHashCode(a));
    System.out.println(System.identityHashCode(b));
    System.out.println(System.identityHashCode(c));
  }
}

示例輸出(每次都會不同,但前兩個總是相同的,第三個幾乎總是不同的):

366712642
366712642
1829164700

來自java.lang.Class.isPrimitive API

有九個預定義的 Class 對象來表示八種基本類型和 void。 它們由 Java 虛擬機創建,並與它們所代表的原始類型具有相同的名稱,即 boolean、byte、char、short、int、long、float 和 double。

這些對象只能通過以下公共靜態最終變量java.lang.Boolean.TYPEjava.lang.Integer.TYPE等訪問

簡單來說:

int --> 是基元..用於簡單的數學運算。 您不能將它們添加到集合中。

整數 --> 本身就是對象.. 是整數的包裝器。 即,它們可以與集合一起使用(因為它們是對象)。 它們被 GC 作為普通對象收集。

編輯 :

public static void main(String[] args) {
    int i = 5;
    System.out.println(int.class);

    Integer i1 = new Integer(5);
    System.out.println(Integer.TYPE);

}

O/P : int
      int

所以,基本上,兩者都返回一個整數。 Integer.TYPE 只返回 Integer 類的原始類型。 對於任何包裝類都是如此

Java 通過為每個原始類型定義兩種類型,以精神分裂的方式處理原始類型與類類型。

例如int是原始類型, Integer是類類型。 當您使用泛型時,您將被迫使用非原始類型,因此ArrayList<Integer>是允許的,但ArrayList<int>不是。

由於您有時想要執行反射,因此這種二元性導致兩個類(您如何檢查方法public int foo (); )。

假設你有一個類:

public class Foo {

    private Integer value;

    public int value1 () {
        return value;
    }

    public Integer value2 () {
        return value;
    }

}

這兩個方法不會總是返回相同的值,因為value2()可以返回nullvalue1()將拋出運行時錯誤。

對我來說,理解int.classInteger.class的最簡單方法是停止認為Integer是一個包裝器(這意味着它是“特殊的”)。 事實上,將 int 視為一種特殊情況更容易,也可能更合適。

Integer 只是一個普通的Java 類,與例如String 沒有什么不同。 它派生自Object ,像Object一樣操作,在運行時您可以創建Integer的實例,該實例采用類似對象的內存布局,例如,開頭的指針指向Integer.class ,這就是啟用多態運行時的原因java的行為。

Integer真的沒有什么特別之處。 如果你想象一個 Java 沒有 boolean、int、long 這些原語,而只有 Integer、Boolean、Long 等,那么類型系統實際上是非常一致的。

從概念上講,您可以將int視為稍后出於性能原因引入的特殊 最初,它與 Integer 無關。 在創建 Java 時,為純數字維護類似對象的內存布局對於算術繁重的程序來說非常昂貴。 大多數算術運算甚至根本不涉及多態動態調度。 例如,在數字上調用諸如 toString 之類的方法就不太常見了。

int 是特殊的,因為它是一個類,它的“實例”被放置在內存中,去掉了公共對象結構——只有四個連續的字節,沒有額外的元數據。

因此,您不能執行123.getClass()因為 int 123 的運行時內存布局沒有類指針。 int.class確實存在,它與Integer.class完全無關(還)。 從某種意義上說, int 更類似於 Void ,因為在 Void.class 中確實存在,但是您永遠不能擁有對象 o 其中o.class == Void.class

Java 可以在這里解決,int 是 int,Integer 是 Integer。 但是人們意識到,雖然不太常見,但能夠將 int 視為普通 Java 對象仍然非常有用,否則您將始終至少需要維護兩組方法——一組采用普通對象,另一組采用普通對象需要原語 - 即使性能不是你關心的。 在這些場景中,int 實際上表現得像 Integer。 Java 允許這種轉換通過自動裝箱過程自動發生,從而有效地使 int 和 Integer 相關。

但是 int 仍然是 int,而 Integer 仍然是 Integer(例如int.class != Integer.class )。 但是 Integer.class 中引入了一個額外的字段來表明它與 int.class 相關,即Integer.TYPE 所以Integer.TYPE == int.class 對我來說Integer.TYPE只是為了捕捉 Integer 和 int 相關的概念 如何使用它,或者它是否有用,取決於你。

實際上, int 和 Integer 仍然是重要的不同類型。 例如:

void accept (int value);
void accept (Integer value);

仍然被認為是兩個重載。 因此,在使用反射時,您可以使用 int.class 和 Integer.class 來區分兩者。

當不使用反射或某種形式的元編程時,因為您無法從對象導航到 int.class,所以在您的代碼中很少會看到 int.class 被使用。 有時會讓人感到困惑,因為自動裝箱語法似乎建議您應該獲取 int.class:

int value = 1;
Class c = ((Object)value).getClass();

但這只是一種錯覺,當您執行((Object)value) ,您實際上是在創建一個具有相同值的新 Integer 實例。

我需要明確使用 int.class 和 Integer.class 的唯一時間是構建一個泛型 api <T> T getValue(String name, Class<T> type); 我需要區分是否允許 api 返回 null:

int value = getValue("key", Integer.class); // will potentially throw NPE
int value = getValue("key", int.class); // will never throw NPE

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM