2013-11-26 3 views
3

См. Boolean#TYPE для примера того, что я имею в виду.Примитивные обертки и статические «ТИП» Объект класса

Все классы-оболочки (Boolean, Double, Integer и т. Д.) Имеют статическое поле класса, связанное с ними, которое называется TYPE. Что это означает?

В частности, здесь есть несколько мягких тестов:

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

Оба оценивают как ложные. (И как примечание стороны, .equals сравнения является ненужным, так как класс не переопределяет равно от Object.)

Оба Boolean.class и Boolean.TYPE являются Class<Boolean>, потому что они сопоставимы == без ошибок. Сравнение двух объектов с разными объявленными типами является незаконным.

При дальнейшем рассмотрении, TYPE полей извлекаются путем вызова пакета-частный нативный метод Class#getPrimitiveClass вдоль линий следующего:

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

Комментария на самом методе не особо информативен либо. В нем говорится, что он возвращает объект класса VM для типа, который является довольно очевидным, поскольку он является нативным методом.

Я не могу найти никакой документации по этому поводу за пределами неопределенного намека Java-документов на «представление примитивного типа». Есть ли какая-то польза для этого поля? Он не используется в самих классах обертки.

(Edited)

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. Я предполагаю, что я пришел из «неправильного конца» Google, чтобы говорить, чтобы не найти никаких результатов.

Но с учетом существования «примитивных классов» (boolean.class, int.class и т. Д.), Что на самом деле не объясняет существование ТИП-поля. В основном это «просто»? Я все еще не понимаю.

ответ

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.class и Integer.TYPE были примерно с начала Java, хотя я могу ошибаться. Integer.TYPE может быть первоначально присвоен Class.getPrimitiveClass("int").

+0

Сделав еще несколько поисков, я обнаружил, что литералы .class - это просто ярлыки для полей .TYPE. Оба они были добавлены одновременно с API отражения (Java 1.1), и литералы заменяются (возможно) во время компиляции, аналогичной автобоксингу. – Radiodef

+0

* «... литералы заменяются (возможно) во время компиляции ...» * И я полагаю, что компиляция на тот же байт-код доказывает это. – Radiodef

Смежные вопросы