包装类型及缓存池
Java是面向对象编程
Java中new创建的对象是存储在堆中的,在栈中创建一个引用,引用堆中的对象(堆中对象,栈中引用)
基本的数据类型的定义不需要new创建,而是直接在栈内存中直接存储
包装类型即是将基本类型具有对象性质,Java是面向对象编程,包装类能够在编程中提供方便,如集合容器中元素的要求是Object类型的 包装类就能直接使用,基本类型就不能直接在集合中使用
包装类型均位于java.lang包中 该包由final修饰 不能继承不可改变
| 基本数据类型 | 包装类 |
|---|---|
| byte | Byte |
| boolean | Boolean |
| short | Short |
| char | Character |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
拆箱与装箱(基本数据类型和包装类型之间的转换)
(自动)装箱 基本数据类型(自动)转换成包装类型
(自动)拆箱 包装类型(自动)转换成基本数据类型
Integer i = 666 // 自动装箱 Integer i = Integr.valueOf(666)
int b = i //自动拆箱 int b = integer.intValue(i)
自动装箱都是通过包装类的 valueOf() 方法来实现的
自动拆箱都是通过包装类对象的 xxxValue() 来实现的
public static void main(String[]args){
Integer integer=1; //装箱
int i=integer; //拆箱
}
public static void main(String[]args){
Integer integer=Integer.valueOf(1);
int i=integer.intValue();
}
自动拆箱装箱的场景
1、基本数据类型放入集合类
List<Integer> li = new ArrayList<>();
for (int i = 1; i < 50; i ++){
li.add(i); //自动装箱 li.add(Integer.valueOf(i));
}
2、基本数据类型和包装类型进行比较
Integer a = 1;
System.out.println(a == 1 ? "等于" : "不等于"); //自动装箱 a.intValue()==1
Boolean bool = false;
System.out.println(bool ? "真" : "假"); //自动拆箱 bool.booleanValue
3、包装类运算(自动拆箱成基本数据类型 进行运算)
Integer i = 10; // 自动装箱 Integer.valueOf(10) Integer j = 20;// 自动装箱 Integer.valueOf(20)System.out.println(i+j); //自动拆箱 i.intValue()+j.intValue()
4、三目运算符的使用
三目运算符语法:当第二,第三位操作数分别为基本类型和对象时,其中的对象就会拆箱为基本类型进行操作。
boolean flag = true; Integer i = 0; int j = 1; int k = flag ? i : j; //int k = flag ? i.intValue() :j;第二位包装类 第三位基本类型 包装类自动拆箱
三目运算符和自动拆箱可能会导致了空指针异常 ,包装类是对象类型 ,对象为空时进行拆箱,会报空指针异常
Map<String,Boolean> map = new HashMap<String, Boolean>();
Boolean b = (map!=null ? map.get("test") : false); //map.get("test") 是对象类型 可能为空
Boolean.valueOf(hashmap == null ? false : ((Boolean)hashmap.get("test")).booleanValue());
Boolean b = (map!=null ? map.get("test") : Boolean.FALSE); // 解决方法 将三目运算第二第三都设为对象类型
5、函数参数与返回值
public int getNum1(Integer num) { return num;// num.intValue() 自动拆箱}
public Integer getNum2(int num) {
return num; //Integer.valueOf(num) 自动装箱
}
自动装箱、自动拆箱与缓存
包装对象的数值比较,不能简单的使用 ==,虽然 -128 到 127 之间的数字可以,但是这个范围之外还是需要使用 equals 比较。
大部分包装类型的valueOf方法都会有缓存的操作,即:将某段范围内的数据缓存起来(缓存池),创建时如果在这段范围内(缓存池中查找有的话),直接返回已经缓存的这些对象,这样保证在一定范围内的数据可以直接复用,而不必要重新生成。(如果缓存池中没有就直接使用构造函数构造)
valueOf方法 建议使用valueOf进行构建对象。利用构造器构造出来的对象不会经过取缓存操作
对于Float和Double这种类型,两个就没有采用这种缓存的方式,都是直接使用了构造器直接构造对应包装类型的对象。
其余数据类型基本逻辑都差不多了,都有一个缓存值范围,如果超过了,就利用构造器直接构造,否则直接返回缓存的对象。
以 Integer 中的缓存机制为例 整数值区间 -128 至 +127。当需要进行自动装箱时,如果数字在 -128 至 127 之间时,会直接使用缓存IntegerCache中的对象,而不是重新创建一个对象。
有ByteCache用于缓存Byte对象
有ShortCache用于缓存Short对象
有LongCache用于缓存Long对象
有CharacterCache用于缓存Character对象
Byte, Short, Long有固定范围: -128 到 127。对于Character, 范围是 0 到 127。除了Integer以外,这个范围都不能改变。
只有Integer整数值范围可以改变:可以通过 java.lang.Integer.IntegerCache.high 设置最大值。(其它的不能)
public static void main(String... strings) {
Integer integer1 = 3;
Integer integer2 = 3;
if (integer1 == integer2)
System.out.println("integer1 == integer2"); //输出
else
System.out.println("integer1 != integer2");
Integer integer3 = 300;
Integer integer4 = 300;
if (integer3 == integer4)
System.out.println("integer3 == integer4");
else
System.out.println("integer3 != integer4"); //输出 超过了127 相当于直接调用构造函数构造,内存地址就不一样了
}
包装对象的数值比较,不能简单的使用 ==,虽然 -128 到 127 之间的数字可以,但是这个范围之外还是需要使用 equals 比较。
如果一个 for 循环中有大量拆装箱操作,会出现大量的无用对象造成内容空间的浪费,同时加重了垃圾回收的工作量,会浪费很多资源。
Integer sum = 0; for(int i=1000; i<5000; i++){ sum+=i; // sum= Integer.valueOf((int)(sum.intValue() + i));
}
方法重载 会区分类型 不会进行自动拆箱和装箱操作
public static void test(Integer num) {
System.out.println("Integer参数的方法被调用...");
}
public static void test(int num) {
System.out.println("int参数的方法被调用...");
}
public static void main(String[] args) {
int i = 2;
test(i); //int参数的方法被调用...
Integer j = 4;
test(j);//Integer参数的方法被调用...
}

浙公网安备 33010602011771号