1. Overview
1.概述
As the name suggests, wrapper classes are objects encapsulating primitive Java types.
顾名思义,封装类是封装了原始Java类型的对象。
Each Java primitive has a corresponding wrapper:
每个Java基元都有一个相应的包装器。
- boolean, byte, short, char, int, long, float, double
- Boolean, Byte, Short, Character, Integer, Long, Float, Double
These are all defined in the java.lang package, hence we don’t need to import them manually.
这些都是在java.lang包中定义的,因此我们不需要手动导入它们。
2. Wrapper Classes
2.封装类
“What’s the purpose of a wrapper class?”. It’s one of the most common Java interview questions.
“包装器类的目的是什么?”。这是最常见的Java面试问题之一。
Basically, generic classes only work with objects and don’t support primitives. As a result, if we want to work with them, we have to convert primitive values into wrapper objects.
基本上,通用类只对对象工作,不支持基元。因此,如果我们想使用它们,我们必须将基元值转换为包装对象。
For example, the Java Collection Framework works with objects exclusively. Long back when (prior to Java 5, almost 15 years back) there was no autoboxing and we, for example, couldn’t simply call add(5) on a collection of Integers.
例如,Java集合框架只与对象一起工作。很久以前(在Java 5之前,差不多15年了),没有自动排版,例如,我们不能简单地在一个Integers的集合上调用add(5)。
At that time, those primitive values needed to be manually converted to corresponding wrapper classes and stored in collections.
当时,那些原始值需要手动转换为对应的封装类并存储在集合中。
Today, with autoboxing, we can easily do ArrayList.add(101) but internally Java converts the primitive value to an Integer before storing it in the ArrayList using the valueOf() method.
今天,通过自动框选,我们可以很容易地进行ArrayList.add(101),但是在内部,Java在将原始值存储到ArrayList之前,使用valueOf() 方法将其转换为Integer。
3. Primitive to Wrapper Class Conversion
3.原始类到封装类的转换
Now the big question is: how do we convert a primitive value to a corresponding wrapper class e.g. an int to Integer or a char to Character?
现在最大的问题是:我们如何将一个原始值转换为相应的封装类,例如,将int转换为Integer或将char转换为Character?
Well, we can either use constructor or static factory methods to convert a primitive value to an object of a wrapper class.
那么,我们可以使用构造函数或静态工厂方法来将原始值转换为包装类的对象。
As of Java 9, however, constructors for many boxed primitives such as Integer or Long have been deprecated.
但是,从 Java 9 开始,许多盒式基元的构造函数,如 Integer 或 Long 已经被弃用。
So it’s highly recommended to only use the factory methods on new code.
所以强烈建议只在新代码上使用工厂方法。
Let’s see an example of converting an int value to an Integer object in Java:
让我们看看在Java中把一个int值转换为Integer对象的例子。
Integer object = new Integer(1);
Integer anotherObject = Integer.valueOf(1);
The valueOf() method returns an instance representing the specified int value.
valueOf()方法返回一个代表指定int值的实例。
It returns cached values which makes it efficient. It always caches values between -128 to 127 but can also cache other values outside this range.
它返回缓存的值,这使得它很有效率。它总是缓存-128到127之间的值,但也可以缓存这个范围之外的其他值。
Similarly, we can also convert boolean to Boolean, byte to Byte, char to Character, long to Long, float to Float, and double to Double. Though if we have to convert String to Integer then we need to use parseInt() method because String isn’t a wrapper class.
同样,我们也可以将boolean转换为Boolean,byte转换为Byte,char转换为Character,long转换为Long,float转换为Float,double转换为Double。尽管如此,如果我们必须将字符串转换为整数,那么我们需要使用parseInt()方法,因为字符串不是一个封装类。
On the other hand, to convert from a wrapper object to a primitive value, we can use the corresponding method such as intValue(), doubleValue() etc:
另一方面,要从包装对象转换为原始值,我们可以使用相应的方法,如intValue()、doubleValue()等。
int val = object.intValue();
A comprehensive reference can be found here.
可以在这里找到一份全面的参考资料。
4. Autoboxing and Unboxing
4.自动装箱和开箱
In the previous section, we showed how to manually convert a primitive value to an object.
在上一节中,我们展示了如何将一个原始值手动转换为一个对象。
After Java 5, this conversion can be done automatically by using features called autoboxing and unboxing.
在Java 5之后,这种转换可以通过使用被称为autoboxing和unboxing的功能自动完成。
“Boxing” refers to converting a primitive value into a corresponding wrapper object. Because this can happen automatically, it’s known as autoboxing.
“装箱 “指的是将一个原始值转换为相应的包装对象。因为这可以自动发生,所以被称为自动装箱。
Similarly, when a wrapper object is unwrapped into a primitive value then this is known as unboxing.
同样地,当一个包装对象被解包为一个原始值时,这被称为解包。
What this means in practice is that we can pass a primitive value to a method which expects a wrapper object or assign a primitive to a variable which expects an object:
这在实践中意味着,我们可以将一个基元的值传递给一个期望有包装对象的方法,或者将一个基元分配给一个期望有对象的变量。
List<Integer> list = new ArrayList<>();
list.add(1); // autoboxing
Integer val = 2; // autoboxing
In this example, Java will automatically convert the primitive int value to the wrapper.
在这个例子中,Java会自动将原始的int值转换成包装器。
Internally, it uses the valueOf() method to facilitate the conversion. For example, the following lines are equivalent:
在内部,它使用valueOf()方法来促进转换。例如,下面几行是等价的。
Integer value = 3;
Integer value = Integer.valueOf(3);
Though this makes conversion easy and codes more readable, there are some cases where we shouldn’t use autoboxing e.g. inside a loop.
虽然这使转换变得简单,代码更易读,但在某些情况下,我们不应该使用自动排版,例如在一个循环内。
Similar to autoboxing, unboxing is done automatically when passing an object to a method that expects a primitive or when assigning it to a primitive variable:
与自动装箱类似,当把一个对象传递给一个期望有基元的方法或把它赋值给一个基元变量时,会自动进行解箱。
Integer object = new Integer(1);
int val1 = getSquareValue(object); //unboxing
int val2 = object; //unboxing
public static int getSquareValue(int i) {
return i*i;
}
Basically, if we write a method that accepts a primitive value or wrapper object, we can still pass both values to them. Java will take care of passing the right type e.g. primitive or wrapper depending upon context.
基本上,如果我们写了一个接受原始值或包装器对象的方法,我们仍然可以将这两个值传递给它们。Java将根据上下文处理传递正确的类型,例如原始值或包装器。
5. Conclusion
5.结论
In this quick tutorial, we talked about wrapper classes in Java, as well as the mechanism of autoboxing and unboxing.
在这个快速教程中,我们谈到了Java中的封装类,以及自动装箱和拆箱的机制。