确定对象是否是原始types

我有一个Object[]数组,我试图find那些是原始的。 我试图使用Class.isPrimitive() ,但似乎我做错了什么:

 int i = 3; Object o = i; System.out.println(o.getClass().getName() + ", " + o.getClass().isPrimitive()); 

打印java.lang.Integer, false

有没有正确的方法或一些替代方法?

Object[]的types永远不会是原始的,因为你已经有了引用! 这里的i的types是into引用的对象的types是Integer (由于自动装箱)。

这听起来像你需要找出是否types是“原始包装”。 我不认为这里有什么内置的标准库,但很容易编码:

 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; } } 

commons-lang ClassUtils有相关的方法 。 新版本有:

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

旧版本有wrapperToPrimitive(clazz)方法,它将返回原始的对应关系。 所以你可以这样做:

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

Google的Guava库有一个Primitives实用程序,用于检查某个类是否为原始types的包装types: http : //guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/primitives/Primitives.html

 Primitives.isWrapperType(class) 

Class.isPrimitive()适用于基元

对于那些喜欢简洁的代码。

 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); } 

从Java 1.5开始,有一个叫做自动装箱的新function。 编译器自己做这个。 当它看到一个机会时,它将一个原始types转换为适当的包装类。

这里可能发生的是当你声明

 Object o = i; 

编译器会按照说法编译这个语句

 Object o = Integer.valueOf(i); 

这是自动装箱。 这将解释你收到的输出。 这个来自Java 1.5规范的页面更详细地解释了自动装箱。

Integer不是原语, Class.isPrimitive()不是说谎。

你必须处理java的自动装箱。
我们来看看代码

 公共课testing
 {
     public static void main(String [] args)
     {
         int i = 3;
        对象o = i;
        返回;
     }
 } 

你得到类test.class和javap -ctesting让我们来检查生成的字节码。

 编译自“test.java”
公共类testing扩展java.lang.Object {
 public test();
  码:
    0:aload_0
    1:调用特定的#1;  //方法java / lang / Object。“”:()
    4:回报 

public static void main(java.lang.String []);
码:
0:iconst_3
1:istore_1
2:iload_1
3:invokestatic#2; //方法java / lang / Integer.valueOf:(I)Ljava / lang / Integer;
6:astore_2
7:回报

} 正如你可以看到的Java编译器添加

  invokestatic#2;  //方法java / lang / Integer.valueOf:(I)Ljava / lang / Integer; 

从int中创build一个新的Integer,然后通过astore_2将新的Object存储在o中

我认为这是由于自动装箱

 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); } 

只是所以你可以看到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”时,这在reflection中很重要。

此代码工作:

 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) { } } 

此代码失败(无法find该方法):

 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) { } } 

正如几个人已经说过,这是由于自动装箱 。

可以创build一个实用程序方法来检查对象的类是否为IntegerDouble等。但是无法知道对象是否是通过自动构造一个基元来创build的 。 一旦它被装箱,它看起来就像一个明确创build的对象。

所以,除非你确定地知道你的数组永远不会包含没有自动装箱的包装类,否则没有真正的解决scheme。

primitve包装types将不会响应此值。 这是对基元的阶级表示,尽pipe除了反思之外,我想不到太多的用法。 所以,例如

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

打印“假”,但

 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; } 

打印“真”

这是我能想到的最简单的方法。 包装类只存在于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; } 

从Spring获取beanUtils的地址http://static.springsource.org/spring/docs/3.0.x/javadoc-api/

可能Apache的变种(commons beans)具有相似的function。

 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 

我迟到了,但是如果你正在testing一个字段,你可以使用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种基本types。

你可以通过下面的语句来确定一个对象是否是包装types:

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

你也可以通过使用isPrimitive()方法来确定一个原始对象

 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; }