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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1704634/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 17:40:51  来源:igfitidea点击:

Simple way to get wrapper class type in Java

javareflectionwrapper

提问by Savvas Dalkitsis

I have a piece of code where I need to pass the class of a field in a method. Because of the mechanics of my code I can only handle reference objects and not primitives. I want an easy way of determining if a Field's type is primitive and swap it with the appropriate wrapper class. So in code what I do so far is something like this:

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

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

This works fine, except for the fact that I need to explicitly check for all the primitive types and swap them with the appropriate wrapper class. Now I know that there are not so many primitive types and it won't be a problem to simply list them all, but I was wondering if there was an easier and more elegant way of doing it.

这工作正常,除了我需要显式检查所有原始类型并将它们与适当的包装类交换的事实。现在我知道没有那么多原始类型,简单地列出它们也不是问题,但我想知道是否有一种更简单、更优雅的方法来做到这一点。

回答by Kevin Bourrillion

I use Google Collections Library in my answer, because I'm spoiled like that, but you can probably see how to do it with plain HashMaps if you prefer.

我在回答中使用了 Google Collections Library,因为我被宠坏了,但是如果您愿意,您可能会看到如何使用普通的 HashMap 来做到这一点。

  // 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();

It is odd that nothing exists in the JDK for this, but indeed nothing does.

奇怪的是,JDK 中没有任何内容,但确实没有。

EDIT: I'd totally forgotten that we released this:

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

http://google.github.io/guava/releases/21.0/api/docs/com/google/common/primitives/Primitives.html

http://google.github.io/guava/releases/21.0/api/docs/com/google/common/primitives/Primitives.html

It has the wrap() method, plus unwrap() and a few other incidental things.

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

回答by skaffman

Apache Commons Langhas a utility method to do this (ClassUtils.primitiveToWrapper()), which will be just as ugly under the covers, but at least you can pretend it's nice.

Apache Commons Lang有一个实用方法来做到这一点(ClassUtils.primitiveToWrapper()),它在幕后同样丑陋,但至少你可以假装它很好。

回答by Fai Ng

Here is another way if you don't need highly optimized code:

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

    Class<?> primitive=long.class;
    Class<?> boxed=Array.get(Array.newInstance(primitive,1),0).getClass();
    System.out.println(primitive.getName());
    System.out.println(boxed.getName());

(Editing/adding explanation)

(编辑/添加说明)

At first, it was to see if Java has a method to give you the wrapper class when given a primitive type. Couldn't find any.

起初,它是看 Java 是否有一种方法可以在给定原始类型时为您提供包装器类。找不到任何。

Then, it was to see if you can have Java create a primitive value when give a primitive type (then you can somehow get an object out of it). Couldn't find a way to do this.

然后,看看你是否可以让 Java 在给出原始类型时创建一个原始值(然后你可以以某种方式从中获取一个对象)。找不到办法做到这一点。

But then it was found out that you CAN have Java create an array of primitive values when given a primitive type. And then there is a Java method that gives you an object of the wrapping type of the array element(which is primitive). Once you have the object, you can then get the type.

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

So here is how the whole thing work:

所以这里是整个事情的工作原理:

The method Array.newInstance() creates a array of whatever type you specify, whether it is primitive or object. In the case of object, all elements are object type but initialized to null. In the case of primitive, elements are primitive type. But primitive variable/array element can't be null, so they have the default value of the primitive type, e.g. int will be zero. Thus no elements will be null. And now if you try to get the value of an element by using Array.get(), Array.get() has no choice but box that primitive value to an object, e.g. int to Integer, because Array.get() can't return primitive value. Now you have an object of the boxing(wrapping) type of you original primitive type. Finally calling Object.getClass() gives you the boxing(wrapping) type.

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

This trick works with any primitive type you have in Java today and in the future.

这个技巧适用于您现在和将来在 Java 中使用的任何原始类型。

回答by Yishai

You can call class.isPrimitive() to know if it is a primitive or not, however, there is no boxing method to convert the classes within the JDK. There is at least one open bugrelating to this.

您可以调用 class.isPrimitive() 来了解它是否是原始类型,但是,JDK 中没有用于转换类的装箱方法。至少有一个与此相关的开放错误

回答by LMD

(Idea) Get class name and make first letter capital, then call Class.forInstance(className).newInstance(primitive). Exceptions are "char" -> Character and "int" -> Integer

(思路)获取类名,首字母大写,然后调用Class.forInstance(className).newInstance(primitive)。例外是 "char" -> Character 和 "int" -> Integer

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

                                }

回答by Jim Smith

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

回答by nickl-

So you want to get the wrapper class type, ok.

所以你想得到包装类类型,好的。

Synopsis

概要

We are retrieving a field and then find it contains a primitive type.

我们正在检索一个字段,然后发现它包含一个原始类型。

Field f = getTheField(); // Dummy method that returns my Field
Class<?> c = f.getType();

But instead we want the wrapper type.

但是我们想要包装器类型。

Primitive types in Java

Java 中的原始类型

Now as you already found out the only thing a primitive class is good for is to return true for c.isPrimitive();.

现在你已经发现原始类唯一的好处就是为 返回 true c.isPrimitive();

From wiki books - java programming:

来自wiki 书籍 - java 编程

Primitive types are the most basic data types available within the Java language. There are 8: boolean , byte , char , short , int , long , float and double . These types serve as the building blocks of data manipulation in Java. Such types serve only one purpose — containing pure, simple values of a kind.

原始类型是 Java 语言中可用的最基本的数据类型。有 8 个: boolean 、 byte 、 char 、 short 、 int 、 long 、 float 和 double 。这些类型用作 Java 中数据操作的构建块。此类类型仅用于一个目的——包含一种纯粹、简单的值。

Attempting to use them any other way and you are in for a lot of hurt.

试图以任何其他方式使用它们,你会受到很大伤害。

Cannot make a new instance of a primitive.

无法创建基元的新实例。

Field f = getTheField();
Class<?> c = f.getType();
Object wrapper = c.newInstance();
//  java.lang.InstantiationException thrown: int
//        at Class.newInstance (Class.java:545) 

Cannot cast to a primitive type.

无法转换为原始类型。

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)

Can cast to a null wrapper type. Yeah! \o/

可以转换为空包装器类型。是的!\o/

Field f = getTheField();
Class<?> c = f.getType();
Object wrapper = c.cast(null);

No exceptions and the variable wrapperis of type class java.lang.Integerbut with a value of null, a whole lot of good that will do us.

没有例外,变量wrapper的类型为 ,class java.lang.Integer但值为null,这对我们有很多好处。

Primitives are not even inherited from wrappers.

原语甚至不是从包装器继承的。

boolean isSuperClass = Integer.class.isAssignableFrom(int.class); // false

This is obviously not getting us anywhere lets rather take a step back from the problem and have a look at the bigger picture.

这显然不会让我们走到任何地方,让我们从问题中退后一步,看看更大的图景。

When at first you don't succeed...

当一开始你没有成功时......

Lets recap: We are retrieving a field which has to come from somewhere since java.lang.reflect.Fieldis marked final and exposes no public constructors.

让我们回顾一下:我们正在检索一个必须来自某个地方的字段,因为它java.lang.reflect.Field被标记为 final 并且没有公开任何公共构造函数。

If we were to fill in the gaps it might look something like this.

如果我们要填补空白,它可能看起来像这样。

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

Instead of fighting against the machine lets rather work with it. One of the perks of primitives are that they will initialise to a default value 0instead of null. Lets see if we can use that.

与其与机器对抗,不如与其合作。原语的好处之一是它们将初始化为默认值0而不是null. 让我们看看我们是否可以使用它。

Get wrapper class from wrapped instance.

从包装的实例中获取包装类。

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

That was much easier than before and we didn't even have to do anything, everything was done for us. Yet another perk for not trying to go against the stream.

这比以前容易多了,我们甚至不需要做任何事情,一切都为我们做了。不试图逆流而上的另一个好处。

Lets improve on that, refactor and make it a little more reusable by extracting a method.

让我们对此进行改进,重构并通过提取方法使其更具可重用性。

Implement a manual boxing method.

实施手动装箱方法。

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

A simple primitive wrap without ever having to look at the types or use look up tables because java already does it anyway.

一个简单的原始包装,无需查看类型或使用查找表,因为无论如何 java 已经做到了。

The simple solution

简单的解决方案

Field f = getTheField(); // Dummy method that returns my Field
Class<?> c = f.get(null).getClass(); 

Or you can replace null with an instance if the field is not static.

或者,如果字段不是静态的,您可以用实例替换 null。

nJoy!

快乐!

回答by Flávio Etrusco

There's also com.sun.beans.finder.PrimitiveWrapperMap#getType(primitiveName). But of course using classes from the "com.sun" package is not really recommended...

还有 com.sun.beans.finder.PrimitiveWrapperMap#getType(primitiveName)。但是当然不推荐使用“com.sun”包中的类...