Определение того, является ли объект примитивным типом

У меня есть массив Object[], и я пытаюсь найти те, которые являются примитивами. Я пытался использовать Class.isPrimitive(), но кажется, что я делаю что-то неправильно:

int i = 3;
Object o = i;

System.out.println(o.getClass().getName() + ", " +
                   o.getClass().isPrimitive());

выводит java.lang.Integer, false.

Есть ли правильный путь или какая-то альтернатива?

Ответ 1

Типы в Object[] никогда не будут примитивными - потому что у вас есть ссылки! Здесь тип i - int тогда как тип объекта, на который ссылается o - Integer (из-за автобокса).

Похоже, вам нужно выяснить, является ли тип "оболочкой для примитива". Я не думаю, что есть что-то встроенное в стандартные библиотеки для этого, но это легко кодировать:

import java.util.*;

public class Test
{
    public static void main(String[] args)        
    {
        System.out.println(isWrapperType(String.class));
        System.out.println(isWrapperType(Integer.class));
    }

    private static final Set<Class<?>> WRAPPER_TYPES = getWrapperTypes();

    public static boolean isWrapperType(Class<?> clazz)
    {
        return WRAPPER_TYPES.contains(clazz);
    }

    private static Set<Class<?>> getWrapperTypes()
    {
        Set<Class<?>> ret = new HashSet<Class<?>>();
        ret.add(Boolean.class);
        ret.add(Character.class);
        ret.add(Byte.class);
        ret.add(Short.class);
        ret.add(Integer.class);
        ret.add(Long.class);
        ret.add(Float.class);
        ret.add(Double.class);
        ret.add(Void.class);
        return ret;
    }
}

Ответ 2

Commons-lang ClassUtils имеет соответствующие методы.

Новая версия имеет:

boolean isPrimitiveOrWrapped = 
    ClassUtils.isPrimitiveOrWrapper(object.getClass());

Старые версии имеют wrapperToPrimitive(clazz), который будет возвращать примитивное соответствие.

boolean isPrimitiveOrWrapped = 
    clazz.isPrimitive() || ClassUtils.wrapperToPrimitive(clazz) != null;

Ответ 4

Для тех, кто любит краткий код.

private static final Set<Class> WRAPPER_TYPES = new HashSet(Arrays.asList(
    Boolean.class, Character.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Void.class));
public static boolean isWrapperType(Class clazz) {
    return WRAPPER_TYPES.contains(clazz);
}

Ответ 5

Начиная с Java 1.5 и выше появляется новая функция, называемая авто-бокс. Компилятор делает это сам. Когда он видит возможность, он преобразует примитивный тип в соответствующий класс оболочки.

Что, вероятно, происходит здесь, когда вы объявляете

Object o = i;

Компилятор скомпилирует это утверждение как

Object o = Integer.valueOf(i);

Это авто-бокс. Это объясняет вывод, который вы получаете. Эта страница из спецификации Java 1.5 объясняет авто-бокс более подробно.

Ответ 6

Integer не является примитивным, Class.isPrimitive() не лежит.

Ответ 7

Я думаю, что это происходит из-за автоматического бокса.

int i = 3;
Object o = i;
o.getClass().getName(); // prints Integer

Вы можете реализовать метод утилиты, который соответствует этим конкретным классам бокса и дает вам, если некоторый класс является примитивным.

public static boolean isWrapperType(Class<?> clazz) {
    return clazz.equals(Boolean.class) || 
        clazz.equals(Integer.class) ||
        clazz.equals(Character.class) ||
        clazz.equals(Byte.class) ||
        clazz.equals(Short.class) ||
        clazz.equals(Double.class) ||
        clazz.equals(Long.class) ||
        clazz.equals(Float.class);
}

Ответ 8

Вам нужно иметь дело с авто-боксом java.
Возьмем код

public class test
{
    public static void main(String [ ] args)
    {
        int i = 3;
        Object o = i;
        return;
    }
}
Вы получите класс test.class и javap -c test, чтобы проверить сгенерированный байт-код.
Compiled from "test.java"
public class test extends java.lang.Object{
public test();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."":()V
   4:   return

public static void main (java.lang.String []); Код:  0: iconst_3  1: istore_1  2: iload_1  3: invokestatiС# 2;//Метод java/lang/Integer.valueOf: (I) Ljava/lang/Integer;  6: astore_2  7: return

}

Как вы видите, компилятор java добавил
invokestatic    #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
для создания нового Integer из вашего int и затем сохраняет этот новый объект в o через astore_2

Ответ 9

public static boolean isValidType(Class<?> retType)
{
    if (retType.isPrimitive() && retType != void.class) return true;
    if (Number.class.isAssignableFrom(retType)) return true;
    if (AbstractCode.class.isAssignableFrom(retType)) return true;
    if (Boolean.class == retType) return true;
    if (Character.class == retType) return true;
    if (String.class == retType) return true;
    if (Date.class.isAssignableFrom(retType)) return true;
    if (byte[].class.isAssignableFrom(retType)) return true;
    if (Enum.class.isAssignableFrom(retType)) return true;
    return false;
}

Ответ 10

Просто, чтобы вы могли видеть, что is isPrimitive может возвращать true (поскольку у вас достаточно ответов, показывающих, почему оно ложно):

public class Main
{
    public static void main(final String[] argv)
    {
        final Class clazz;

        clazz = int.class;
        System.out.println(clazz.isPrimitive());
    }
}

Это имеет значение в отражении, когда метод принимает значение "int", а не "Integer".

Этот код работает:

import java.lang.reflect.Method;

public class Main
{
    public static void main(final String[] argv)
        throws Exception
    {
        final Method method;

        method = Main.class.getDeclaredMethod("foo", int.class);
    }

    public static void foo(final int x)
    {
    }
}

Этот код не работает (не удается найти метод):

import java.lang.reflect.Method;

public class Main
{
    public static void main(final String[] argv)
        throws Exception
    {
        final Method method;

        method = Main.class.getDeclaredMethod("foo", Integer.class);
    }

    public static void foo(final int x)
    {
    }
}

Ответ 11

Как уже говорилось, это связано с autoboxing.

Вы можете создать метод утилиты для проверки того, является ли класс объекта Integer, Double и т.д. Но существует , чтобы не знать, был ли объект создан автобоксированием примитива; как только он помещается в коробку, он выглядит так же, как объект, созданный явно.

Итак, если вы точно не знаете, что ваш массив никогда не будет содержать класс-оболочку без autoboxing, нет реального решения.

Ответ 12

Типы оболочки primitve не будут реагировать на это значение. Это для классового представления примитивов, хотя, помимо отражения, я не могу думать о слишком большом использовании для него. Итак, например

System.out.println(Integer.class.isPrimitive());

печатает "false", но

public static void main (String args[]) throws Exception
{
    Method m = Junk.class.getMethod( "a",null);
    System.out.println( m.getReturnType().isPrimitive());
}

public static int a()
{
    return 1;
}

печатает "true"

Ответ 13

Я опаздываю на шоу, но если вы тестируете поле, вы можете использовать getGenericType:

import static org.junit.Assert.*;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;

import org.junit.Test;

public class PrimitiveVsObjectTest {

    private static final Collection<String> PRIMITIVE_TYPES = 
            new HashSet<>(Arrays.asList("byte", "short", "int", "long", "float", "double", "boolean", "char"));

    private static boolean isPrimitive(Type type) {
        return PRIMITIVE_TYPES.contains(type.getTypeName());
    }

    public int i1 = 34;
    public Integer i2 = 34;

    @Test
    public void primitive_type() throws NoSuchFieldException, SecurityException {
        Field i1Field = PrimitiveVsObjectTest.class.getField("i1");
        Type genericType1 = i1Field.getGenericType();
        assertEquals("int", genericType1.getTypeName());
        assertNotEquals("java.lang.Integer", genericType1.getTypeName());
        assertTrue(isPrimitive(genericType1));
    }

    @Test
    public void object_type() throws NoSuchFieldException, SecurityException {
        Field i2Field = PrimitiveVsObjectTest.class.getField("i2");
        Type genericType2 = i2Field.getGenericType();
        assertEquals("java.lang.Integer", genericType2.getTypeName());
        assertNotEquals("int", genericType2.getTypeName());
        assertFalse(isPrimitive(genericType2));
    }
}

Документы Oracle перечисляют 8 примитивных типов.

Ответ 15

Это самый простой способ, о котором я мог думать. Классы-оболочки присутствуют только в пакете java.lang. И кроме классов-оболочек, ни один класс в java.lang не имеет поля с именем TYPE. Вы можете использовать это, чтобы проверить, является ли класс классом Wrapper или нет.

public static boolean isBoxingClass(Class<?> clazz)
{
    String pack = clazz.getPackage().getName();
    if(!"java.lang".equals(pack)) 
        return false;
    try 
    {
        clazz.getField("TYPE");
    } 
    catch (NoSuchFieldException e) 
    {
        return false;
    }           
    return true;        
}

Ответ 16

вы можете определить, является ли объект типом-оболочкой ниже операторов:

***objClass.isAssignableFrom(Number.class);***

и вы также можете определить примитивный объект с помощью метода isPrimitive()

Ответ 17

public class CheckPrimitve {
    public static void main(String[] args) {
        int i = 3;
        Object o = i;
        System.out.println(o.getClass().getSimpleName().equals("Integer"));
        Field[] fields = o.getClass().getFields();
        for(Field field:fields) {
            System.out.println(field.getType());
        }
    }
}  

Output:
true
int
int
class java.lang.Class
int

Ответ 18

Десять лет, и этот вопрос все еще актуален, по крайней мере, для меня... Что такое связь isPrimitive, если он не работает с экземплярами примитивов? Я знаю, что int.class примитивен, поэтому мне не нужно спрашивать об этом... Ну, я сделал это:

import java.lang.reflect.*;
class Test{
  public static void main(String[] args) throws Exception{
    char x=3; boolean b=true; int i=2;
    Object o= i;
    Object name =o.getClass().getField("TYPE").get(o);
    System.out.println(""+name);
  }
}

Это вернет строку типа int, char, boolean и т.д. Все восемь примитивов имеют класс-оболочку с полем "TYPE", которое содержит эти значения. Тип void также делает.

Другой способ практического использования:

import java.util.*;
import java.lang.reflect.*;
class Test{
  static void print(Object O){System.out.println(O);}
  public static void main(String[] args) throws Exception{
    List list2 = new ArrayList<Object>(List.of("word",2,3.0f,4.0,(char)65, a)); //where a= any user class instance. 
//And see like this list simulates a tuple like in Pyhton, another lack i see in Java.
//But indeed, this kind of List<Object> is still better then a immutable tuple. 
//And this was another of my doubts (tuples), and of other people, as i've seen in my searchs at web.
    ver(list2);

  }
  static void ver(List lis){
    List prims = new ArrayList<String>(List.of("Boolean","Character","Byte","Double","Float","Integer","Long","Short"));
    for(Object o: lis){
      String s=o.getClass().getSimpleName();
      print((prims.contains(s)?"Yes":"No"));
    }
  }

вывод: нет да да да да нет

Ответ 19

Для пользователей javapoet, также существует такой способ:

private boolean isBoxedPrimitive(Class<?> type) {
    return TypeName.get(type).isBoxedPrimitive();
}