Java 确定对象是否为基元类型
我有一个Java 确定对象是否为基元类型,java,reflection,Java,Reflection,我有一个Object[]数组,我正试图找到那些是原语的数组。我试图使用Class.isPrimitive(),但似乎我做错了什么: int i = 3; Object o = i; System.out.println(o.getClass().getName() + ", " + o.getClass().isPrimitive()); 打印java.lang.Integer,false 有没有正确的方法或其他选择?对象[]中的类型永远不会是原始类型,
Object[]
数组,我正试图找到那些是原语的数组。我试图使用Class.isPrimitive()
,但似乎我做错了什么:
int i = 3;
Object o = i;
System.out.println(o.getClass().getName() + ", " +
o.getClass().isPrimitive());
打印java.lang.Integer,false
有没有正确的方法或其他选择?对象[]中的类型永远不会是原始类型,因为您有引用!这里,
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;
}
}
import java.util.*;
公开课考试
{
公共静态void main(字符串[]args)
{
System.out.println(isWrapperType(String.class));
System.out.println(isWrapperType(Integer.class));
}
私有静态最终集>getWrapperTypes()
{
Set>();
ret.add(Boolean.class);
ret.add(Character.class);
ret.add(Byte.class);
ret.add(简称class);
ret.add(Integer.class);
ret.add(长类);
ret.add(Float.class);
ret.add(双级);
重新添加(作废类别);
返回ret;
}
}
整数
不是一个基元,类。isPrimitive()
没有说谎。从Java 1.5及更高版本开始,有一个新功能称为自动装箱。编译器自己做这件事。当它看到机会时,它会将一个基本类型转换为相应的包装器类
这里可能发生的事情是当你宣布
Object o = i;
编译器将编译此语句,如下所示
Object o = Integer.valueOf(i);
这是自动装箱。这将解释您收到的输出 我认为这是由于自动装箱造成的
您可以实现一个实用程序方法,该方法匹配这些特定的装箱类,并给出某个类是否为基元类
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);
}
公共静态布尔isWrapperType(类clazz){
返回clazz.equals(Boolean.class)|
clazz.equals(Integer.class)||
clazz.equals(Character.class)||
clazz.equals(Byte.class)||
clazz.equals(短类)||
clazz.equals(双级)||
clazz.equals(长类)||
clazz.equals(Float.class);
}
您必须处理java的自动装箱问题。
让我们参加codepublic类测试
public class test
{
public static void main(String [ ] args)
{
int i = 3;
Object o = i;
return;
}
}
{
公共静态void main(字符串[]args)
{
int i=3;
对象o=i;
返回;
}
}您将获得类test.class和javap-c测试,让我们来检查生成的字节码
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
}
公共类测试扩展了java.lang.Object{
公开考试();
代码:
0:aload_0
1:invokespecial#1;//方法java/lang/Object。“:()V
4:返回
公共静态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中创建一个新的整数,然后通过astore_2将该新对象存储在o中,正如一些人已经说过的,这是由于
invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
您可以创建一个实用方法来检查对象的类是否为Integer
,Double
,等等。但是无法知道对象是否是通过自动装箱原语创建的;一旦装箱,它看起来就像是显式创建的对象
因此,除非您确定数组中永远不会包含没有自动装箱的包装类,否则就没有真正的解决方案。只是为了让您看到isPrimitive可以返回true(因为您有足够的答案说明它为什么为false):
当方法采用“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)
{
}
}
此代码失败(找不到方法):
primitve包装类型不会响应此值。这是用于原语的类表示,尽管除了反射之外,我想不出它有多少用途。比如说
System.out.println(Integer.class.isPrimitive());
打印“假”,但是
为那些喜欢简洁代码的人打印“true”
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);
}
private static final Set WRAPPER\u TYPES=new HashSet(Arrays.asList(
Boolean.class、Character.class、Byte.class、Short.class、Integer.class、Long.class、Float.class、Double.class、Void.class));
公共静态布尔isWrapperType(类clazz){
返回包装器类型。包含(clazz);
}
从春天抓到小海狸
可能Apache变体(commons beans)也有类似的功能。有相关的方法
新版本包括:
boolean isPrimitiveOrWrapped =
ClassUtils.isPrimitiveOrWrapper(object.getClass());
旧版本有wrapperToPrimitive(clazz)
方法,该方法将返回原语对应关系
boolean isPrimitiveOrWrapped =
clazz.isPrimitive() || ClassUtils.wrapperToPrimitive(clazz) != null;
Google的Guava库有一个检查类是否是原语的包装类型的方法:
Class.isPrimitive()适用于原语这是我能想到的最简单的方法。包装器类仅存在于java.lang
包中。除了包装类之外,java.lang
中没有其他类具有名为TYPE
的字段。您可以使用它来检查类是否为包装类
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
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;
}
publicstaticbooleanisboxingclass(Class clazz)
{
String pack=clazz.getPackage().getName();
if(!“java.lang”.equals(pack))
返回false;
尝试
{
clazz.getField(“类型”);
}
捕获(无此字段例外)
{
返回false;
}
返回true;
}
我来晚了,但是如果你正在测试一个字段,你可以使用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));
}
}
import static org.junit.Assert.*;
导入java.lan
boolean isPrimitiveOrWrapped =
clazz.isPrimitive() || ClassUtils.wrapperToPrimitive(clazz) != null;
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
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;
}
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));
}
}
***objClass.isAssignableFrom(Number.class);***
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;
}