可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have an Object[]
array, and I am trying to find the ones that are primitives. I\'ve tried to use Class.isPrimitive()
, but it seems I\'m doing something wrong:
int i = 3;
Object o = i;
System.out.println(o.getClass().getName() + \", \" +
o.getClass().isPrimitive());
prints java.lang.Integer, false
.
Is there a right way or some alternative?
回答1:
The types in an Object[]
will never really be primitive - because you\'ve got references! Here the type of i
is int
whereas the type of the object referenced by o
is Integer
(due to auto-boxing).
It sounds like you need to find out whether the type is \"wrapper for primitive\". I don\'t think there\'s anything built into the standard libraries for this, but it\'s easy to code up:
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
has relevant methods. The new version has:
boolean isPrimitiveOrWrapped =
ClassUtils.isPrimitiveOrWrapper(object.getClass());
The old versions have wrapperToPrimitive(clazz)
method, which will return the primitive correspondence. So you can do:
boolean isPrimitiveOrWrapped =
clazz.isPrimitive() || ClassUtils.wrapperToPrimitive(clazz) != null;
回答3:
Google\'s Guava library has a Primitives utility that check if a class is a wrapper type for a primitive:
http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/primitives/Primitives.html
Primitives.isWrapperType(class)
Class.isPrimitive() works for primitives
回答4:
For those who like terse code.
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:
Starting in Java 1.5 and up, there is a new feature called auto-boxing. The compiler does this itself. When it sees an opportunity, it converts a primitive type into its appropriate wrapper class.
What is probably happening here is when you declare
Object o = i;
The compiler will compile this statement as saying
Object o = Integer.valueOf(i);
This is auto-boxing. This would explain the output you are receiving. This page from the Java 1.5 spec explains auto-boxing more in detail.
回答6:
Integer
is not a primitive, Class.isPrimitive()
is not lying.
回答7:
I think this happens due to auto-boxing.
int i = 3;
Object o = i;
o.getClass().getName(); // prints Integer
You may implement a utility method that matches these specific boxing classes and gives you if a certain class is primitive.
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:
You have to deal with the auto-boxing of java.
Let\'s take the code
public class test
{
public static void main(String [ ] args)
{
int i = 3;
Object o = i;
return;
}
}
You get the class test.class and
javap -c test let\'s you inspect the generated bytecode.
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[]);
Code:
0: iconst_3
1: istore_1
2: iload_1
3: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
6: astore_2
7: return
}
As you can see the java compiler added
invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
to create a new Integer from your int and then stores
that new Object in o via 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:
Just so you can see that is is possible for isPrimitive to return true (since you have enough answers showing you why it is false):
public class Main
{
public static void main(final String[] argv)
{
final Class clazz;
clazz = int.class;
System.out.println(clazz.isPrimitive());
}
}
This matters in reflection when a method takes in \"int\" rather than an \"Integer\".
This code works:
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)
{
}
}
This code fails (cannot find the method):
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:
As several people have already said, this is due to autoboxing.
You could create a utility method to check whether the object\'s class is Integer
, Double
, etc. But there is no way to know whether an object was created by autoboxing a primitive; once it\'s boxed, it looks just like an object created explicitly.
So unless you know for sure that your array will never contain a wrapper class without autoboxing, there is no real solution.
回答12:
The primitve wrapper types will not respond to this value. This is for class representation of primitives, though aside from reflection I can\'t think of too many uses for it offhand. So, for example
System.out.println(Integer.class.isPrimitive());
prints \"false\", but
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;
}
prints \"true\"
回答13:
I\'m late to the show, but if you\'re testing a field, you can use 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));
}
}
The Oracle docs list the 8 primitive types.
回答14:
This is the simplest way I could think of. The wrapper classes are present only in java.lang
package. And apart from the wrapper classes, no other class in java.lang
has field named TYPE
. You could use that to check whether a class is Wrapper class or not.
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;
}
回答15:
Get ahold of BeanUtils from Spring
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/
Probably the Apache variation (commons beans) has similar functionality.
回答16:
you could determine if an object is wrapper type by beneath statements:
***objClass.isAssignableFrom(Number.class);***
and you could also determine a primitive object by using the isPrimitive() method
回答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