在Java中基础类型的包装类都是不可变的类,如Boolean、Byte、Character、Double、Float、Integer、Long、Short,另外还有String。
这些类创建的实例都是不可以变的实例。
//Integer类代码 JDK1.8
public final class Integer extends Number implements Comparable<Integer> {
private final int value;
public Integer(int value) {
this.value = value;
}
}
可以看到Integer类是final类型的不可被继承,其封装的int值是也是final的。这就导致了实例创建后我们没有其他办法去修改这个int值,所以说Integer对象是不可变对象。
那不可变对象又是如何提高性能的呢,这里看Integer的valueOf方法。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Integer在调用valueOf时是先从IntegerCache查找对象,如果没有才去创建一个新的对象,有的话就直接将引用指向这个对象。IntegerCache是个静态内部类,存储了-128到127的值的对象数组(可以通过java.lang.Integer.IntegerCache.high jvm属性修改这个区间的大小)。
因为Integer对象是不可变的,这样这个缓存数组就可以在多个线程中进行共享,减少Integer对象的创建。
比如你通过一个ORM框架查询出1万条人员数据,人员数据使用Person类封装,Person类有一个字段Integer sex存储性别数据,1男2女。实例化这1万个Person类的时候就可以将这1万个Integer sex分别指向Integer(1)和Integer(2)的内存地址。如果张三的当前性别是男,你想改成女,那就把sex的引用指向缓存中Integer(2)的内存地址。这样的话在没有创建任何额外的Integer实例的情况下,达到了节省内存的目的。
反过来看,如果对象是可变的,就没法做缓存了。对象内部int值变化会导致所有对这个对象的引用不安全,就必须为每个Person创建一个Integer sex对象。
包装类型的缓存机制和字符串的缓存机制都是用的这个思想,就是减少对象的创建数量。
来源:https://www.cnblogs.com/soker/p/16444260.html
本站部分图文来源于网络,如有侵权请联系删除。