У меня есть массив 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;
Ответ 3
В библиотеке Google Guava есть Утилита примитивов, которая проверяет, является ли класс типом обертки для примитива: Primitives.isWrapperType(class)
.
Class.isPrimitive() работает для примитивов
Ответ 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 примитивных типов.
Ответ 14
Получить BeanUtils от Spring http://static.springsource.org/spring/docs/3.0.x/javadoc-api/
Вероятно, вариант Apache (commons beans) имеет схожую функциональность.
Ответ 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();
}