在Java中获取包装器类类型的简单方法

在Java中获取包装器类类型的简单方法,java,reflection,wrapper,Java,Reflection,Wrapper,我有一段代码,需要在方法中传递字段的类。由于我的代码的机制,我只能处理引用对象而不能处理原语。我需要一种简单的方法来确定字段的类型是否为原始类型,并将其与适当的包装器类交换。因此,在代码中,我目前所做的是这样的: Field f = getTheField(); // Dummy method that returns my Field Class<?> c = f.getType(); if (c == int.class) { c = Integer.class; } e

我有一段代码,需要在方法中传递字段的类。由于我的代码的机制,我只能处理引用对象而不能处理原语。我需要一种简单的方法来确定
字段
的类型是否为原始类型,并将其与适当的包装器类交换。因此,在代码中,我目前所做的是这样的:

Field f = getTheField(); // Dummy method that returns my Field
Class<?> c = f.getType();
if (c == int.class) {
    c = Integer.class;
}
else if (c == float.class) {
    c = Float.class;
}
// etc
myMethod(c);
Field f=getTheField();//返回我的字段的伪方法
类c=f.getType();
if(c==int.class){
c=整数.class;
}
else if(c==float.class){
c=浮动类;
}
//等
方法(c);

这很好,除了我需要显式地检查所有的基本类型并用适当的包装器类交换它们之外。现在我知道没有那么多的基元类型,简单地将它们全部列出也不会有问题,但我想知道是否有一种更简单、更优雅的方法可以做到这一点。

您可以调用class.isPrimitive()来知道它是否是基元,但是,没有装箱方法来转换JDK中的类。至少有一个与此相关。

我在回答中使用了Google Collections Library,因为我被宠坏了,但如果您愿意,您可能会看到如何使用普通哈希图

  // safe because both Long.class and long.class are of type Class<Long>
  @SuppressWarnings("unchecked")
  private static <T> Class<T> wrap(Class<T> c) {
    return c.isPrimitive() ? (Class<T>) PRIMITIVES_TO_WRAPPERS.get(c) : c;
  }

  private static final Map<Class<?>, Class<?>> PRIMITIVES_TO_WRAPPERS
    = new ImmutableMap.Builder<Class<?>, Class<?>>()
      .put(boolean.class, Boolean.class)
      .put(byte.class, Byte.class)
      .put(char.class, Character.class)
      .put(double.class, Double.class)
      .put(float.class, Float.class)
      .put(int.class, Integer.class)
      .put(long.class, Long.class)
      .put(short.class, Short.class)
      .put(void.class, Void.class)
      .build();
//安全,因为Long.class和Long.class都是class类型
@抑制警告(“未选中”)
私有静态类包装(c类){
将c.isPrimitive()?(类)原语_返回给_WRAPPERS.get(c):c;
}
私有静态最终映射>基本体到包装器
=新建ImmutableMap.Builder>()
.put(boolean.class,boolean.class)
.put(byte.class,byte.class)
.put(char.class,Character.class)
.put(双级,双级)
.put(float.class,float.class)
.put(int.class,Integer.class)
.put(long.class,long.class)
.put(short.class,short.class)
.put(void.class,void.class)
.build();
奇怪的是,JDK中没有为此而存在的东西,但实际上什么也没有

编辑:我完全忘了我们发布了这个:


它有wrap()方法,再加上unwrap()和一些其他附带的东西。

有一个实用方法来做这件事(),这在封面下同样难看,但至少你可以假装它很好。

如果你不需要高度优化的代码,这里有另一种方法:

    Class<?> primitive=long.class;
    Class<?> boxed=Array.get(Array.newInstance(primitive,1),0).getClass();
    System.out.println(primitive.getName());
    System.out.println(boxed.getName());
Class原语=long.Class;
类boxed=Array.get(Array.newInstance(primitive,1),0).getClass();
System.out.println(primitive.getName());
System.out.println(boxed.getName());
(编辑/添加说明)

首先,它是为了查看Java是否有一个方法在给定一个基本类型时为您提供包装器类。找不到

然后,看看在给定一个基元类型时,您是否可以让Java创建一个基元值(然后您可以以某种方式从中获取一个对象)。找不到这样做的方法

但后来发现,当给定基元类型时,可以让Java创建基元值数组。然后是一个Java方法,它为您提供了一个数组元素的包装类型的对象(它是原语)。一旦拥有了对象,就可以获得类型

下面是整个过程的工作原理:

方法Array.newInstance()创建您指定的任何类型的数组,无论它是基元还是对象。对于object,所有元素都是object类型,但初始化为null。对于基元,元素是基元类型。但是基元变量/数组元素不能为null,因此它们具有基元类型的默认值,例如int将为零。因此,没有元素是空的。现在,如果您尝试使用Array.get()获取元素的值,Array.get()别无选择,只能将该基元值框到对象,例如int到Integer,因为Array.get()无法返回基元值。现在您有了一个原始基元类型的装箱(包装)类型的对象。最后,调用Object.getClass()可以得到装箱(包装)类型

这个技巧适用于现在和将来Java中的任何基元类型。

(Idea)获取类名并将首字母大写,然后调用class.forInstance(className).newInstance(primitive)。例外情况是“char”->字符和“int”->整数

                                Class c=Primitive class object
                                if (c.isPrimitive()) {
                                    if (c == char.class) {
                                        Object wrapper=new Character(primitive var);
                                    }
                                    if (c == int.class) {
                                        Object wrapper=new Integer(primitive var);
                                    }
                                    else {
                                        String name=c.getName();
                                        try {
                                            Class<?> c2=Class.forName("java.lang."+name.substring(0,1).toUpperCase()+name.substring(1,name.length()));
                                            Object wrapper=c2.getConstructor(c).newInstance(primitve_var);
                                        } catch (ClassNotFoundException ex) {
                                            System.out.println("RROR");
                                        }
                                    }

                                }
Class c=基本类对象
if(c.isPrimitive()){
if(c==char.class){
对象包装器=新字符(原语变量);
}
if(c==int.class){
对象包装器=新整数(原语变量);
}
否则{
String name=c.getName();
试一试{
Class c2=Class.forName(“java.lang.”+name.substring(0,1).toUpperCase()+name.substring(1,name.length());
对象包装器=c2.getConstructor(c).newInstance(primitve\u var);
}捕获(ClassNotFoundException ex){
系统输出打印项次(“错误”);
}
}
}
拖网机(clazz级){
如果(!clazz.isPrimitive())
回击声;
if(clazz==Integer.TYPE)
返回Integer.class;
if(clazz==Long.TYPE)
返回Long.class;
if(clazz==Boolean.TYPE)
返回Boolean.class;
if(clazz==Byte.TYPE)
返回Byte.class;
if(clazz==Character.TYPE)
返回字符.class;
if(clazz==Float.TYPE)
返回Float.class;
if(clazz==Double.TYPE)
返回Double.class;
Class<?> toWrapper(Class<?> clazz) {
    if (!clazz.isPrimitive())
        return clazz;

    if (clazz == Integer.TYPE)
        return Integer.class;
    if (clazz == Long.TYPE)
        return Long.class;
    if (clazz == Boolean.TYPE)
        return Boolean.class;
    if (clazz == Byte.TYPE)
        return Byte.class;
    if (clazz == Character.TYPE)
        return Character.class;
    if (clazz == Float.TYPE)
        return Float.class;
    if (clazz == Double.TYPE)
        return Double.class;
    if (clazz == Short.TYPE)
        return Short.class;
    if (clazz == Void.TYPE)
        return Void.class;

    return clazz;
}
Field f = getTheField(); // Dummy method that returns my Field
Class<?> c = f.getType();
Field f = getTheField();
Class<?> c = f.getType();
Object wrapper = c.newInstance();
//  java.lang.InstantiationException thrown: int
//        at Class.newInstance (Class.java:545) 
Field f = getTheField();
Class<?> c = f.getType();
Object wrapper = c.cast(0);
//  java.lang.ClassCastException thrown: Cannot cast java.lang.Integer to int
//        at Class.cast (Class.java:3578)
Field f = getTheField();
Class<?> c = f.getType();
Object wrapper = c.cast(null);
boolean isSuperClass = Integer.class.isAssignableFrom(int.class); // false
public class Simple {
    public static int field;

    public static void main(String[] args) {
        Field f = Simple.class.getField("field"); // Actual method that returns my Field
        Class<?> c = f.getType();
    }
}
public class Simple {
    public static int field;

    public static void main(String[] args) {
        Simple boxer = new Simple();
        Field f = Simple.class.getField("field");
        Object wrapped = f.get(null);    // Integer value 0
        Class<?> c = wrapped.getClass(); // class java.lang.Integer
    }
}
public class Simple {
    public static int field;

    public static <T> T wrap(T t) {
        return t;
    }

    public static void main(String[] args) {
        Field f = Simple.class.getField("field");
        Class<?> c = Simple.wrap(f.get(null)).getClass(); // class java.lang.Integer
    }
}
Field f = getTheField(); // Dummy method that returns my Field
Class<?> c = f.get(null).getClass(); 
@SuppressWarnings("unchecked")
public static <T> Class<T> wrap(Class<T> c) {
    return (Class<T>) MethodType.methodType(c).wrap().returnType();
}

@SuppressWarnings("unchecked")
public static <T> Class<T> unwrap(Class<T> c) {
    return (Class<T>) MethodType.methodType(c).unwrap().returnType();
}
Benchmark                        Mode  Cnt   Score   Error  Units
PrimitiveToWrapper.ifStatements  avgt   30  42.112 ± 0.716  ns/op
PrimitiveToWrapper.map           avgt   30  45.018 ± 0.923  ns/op
PrimitiveToWrapper.wrap          avgt   30  52.369 ± 0.836  ns/op