包装类型及缓存池

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对象

ByteShortLong有固定范围: -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参数的方法被调用...
}
 
posted @ 2022-03-22 09:51  与长安故里  阅读(228)  评论(0)    收藏  举报