`

java学习笔记:装箱和拆箱,包装器和缓冲池

    博客分类:
  • java
阅读更多

jdk1.5以后
Integer举例
Integer a = 3;              这是自动装箱
int     i = new Integer(2); 这是自动拆箱
就是基本类型和其对应的包装类型在需要的时候可以互相转换,具体过程由编译器完成
比如自动装箱:
Integer a=3;
其实编译器调用的是static Integer valueOf(int i)这个方法
查阅JDK知道,
valueOf(int i)返回一个表示指定的 int 值的 Integer 对象
那么就变成这样: Integer a=3;   =>    Integer a=Integer.valueOf(3);

 

对应的  int intValue()  返回该 Integer对象的int值,是拆箱

 

我们再来看Integer缓存, 
下面是IntegerCache类的源码,我加上了注释,便于讨论

private static class IntegerCache   //定义类名   
{     
    static final int high;     
    static final Integer cache[];   //cache缓存是一个存放Integer类型的数组   
  
    static  //初始化   
    {     
        final int low = -128;       //最小值是固定的   
        int h = 127;                //最大值暂时是127   
        if (integerCacheHighPropValue != null) //这段if代码不用深究,是一些判断,我看得眼花啊   
        {     
            int i = Long.decode(integerCacheHighPropValue).intValue();     
            i     = Math.max(i, 127);     
            h     = Math.min(i, Integer.MAX_VALUE - -low);     
        }     
        high = h;  //此时high就是127   
  
        cache = new Integer[(high - low) + 1];  //有256个元素   
        int j = low;                            //j的初始值是-128   
        for(int k = 0; k < cache.length; k++)   //缓存区间数据      
            cache[k] = new Integer(j++);        //将-128~127包装成256个对象存入缓存   
    }     
    private IntegerCache(){}  //构造方法,不需要构造什么   
}  

  

再来看valueOf方法

 

public static Integer valueOf(int i)    
{     
    if(i >= -128 && i <= IntegerCache.high)   
    {   
        //如果i在-128~127之间,就直接在缓存中取出i的Integer类型对象   
        return IntegerCache.cache[i + 128];     
    }       
    else   
    {   
        return new Integer(i);  //否则就在堆内存中创建   
    }       
}   

 

 

valueOf方法会自动调用IntegerCache这个类,
IntegerCache初始化后内存中就有Integer缓冲区cache[]了,
-128~127区间的int值有其对应的的包装对象
java使用该机制是为了达到最小化数据输入和输出的目的,这是一种优化措施,提高效率
其他的包装器:
Boolean: (全部缓存)
Byte:    (全部缓存)

 

Character (   <=127 缓存)
Short     (-128~127 缓存)
Long      (-128~127 缓存)

 

Float     (没有缓存)
Doulbe    (没有缓存)

补充下我对Integer缓冲池对理解:

(这个观点是我在网上看到的一些资料加上自己看源码后的一些推断,但没有在哪本书上看到过这种说法,最近打算看think in java)
缓冲池是java对系统的优化,它是一种管理内存的机制,是一种数据结构,它可以管理多个缓冲区,IntegerCache就是一个缓冲区,cache[]数组中保存的是指向Integer类型对象的指针,虽然Integer缓冲对象是new出来的,但是是由缓冲池管理,欢迎一起讨论.
然后回答一个网友的提问,问题比较典型,我贴到上面来,

先说String str = "aaa";
"aaa"本身就是一个字符串对象,它在编译时就被定义在了数据区,在运行时直接创建到常量池,或者说数据区,而str是当程序运行到这句代码时系统在内存的栈区分配的一个指针变量,指向了常量池中的"aaa"对象,
如果是String str = new String("aaa"); 在编译时,"aaa"对象被创建到数据区,在运行时执行到new String()时,程序动态的开辟一块内存空间,
并将数据区中的"aaa"对象复制一份到堆中,并返回一个引用给str所在栈中,此时这一条语句创建了1个新的String对象。加上原来在数据区中的对象一共2个对象,不知道我说的对不对,请大家指教..

还有一网友问 "Doulbe没有缓存,能说为啥莫?"

Doulbe    (没有缓存)

我也是在网上看到的,我查了下java文档源码
    public static Double valueOf(double d) {
        return new Double(d);
    }

代码中确实没有用到缓冲
对比Integer的valueOf方法,是不一样的,所以才有这个结论的吧!

====================================================

 

知道了这些原理

我们再来看一些网上关于java的有趣问题,就能知道答案了

下面我们对一网友帖子中的问题的做解答,我当时也是看到这个帖子才baidu学到这些内容的

http://xiaoyu1985ban.iteye.com/blog/1384191

主题:java迷题:等于,还是不等于?

代码片段1

public static void main(final String[] args) {  

    Integer a = new Integer(100);  

    Integer b = 100;  

    System.out.println(a == b);   

} 

解答:

结果输出 false

因为new Integer(100)是指明了再堆内存中创建对象

Integer b = 100; 这句是自动装箱,

得到的是Integer缓冲池中的对象,是这句代码return IntegerCache.cache[100 + 128]

明显ab的地址是不一样的,不是同一个对象

 

代码片段2

public static void main(final String[] args) {  

    Integer a = 100;  

    Integer b = 100;  

    System.out.println(a == b);   

} 

解答:

结果输出 true

ab指向了同一个对象,都是IntegerCache.cache[100 + 128]

 

代码片段3

public static void main(final String[] args) {  

    Integer a = 156;  

    Integer b = 156;  

    System.out.println(a == b);   

} 

解答:

结果输出 false

由于156大于128,它的包装对象不在缓冲池中,而是执行 return new Integer(156);

new2,都在堆内存中,但地址不一样

 

代码片段4

public static void main(final String[] args) {  

    Integer a = Integer.valueOf(100);  

    Integer b = 100;  

    System.out.println(a == b);   

}

解答:

结果输出 true

我们上面说过了,Integer b = 100 就相当于Integer b=Integer.valueOf(100)

所以ab指向缓冲池中的同一对象

 

 

 

9
4
分享到:
评论
16 楼 yzz9i 2012-02-07  
xouou_53320 写道
yzz9i 写道
Float     (没有缓存)
Doulbe    (没有缓存) 能说为啥莫

这2句话,我也是在网上看到的,我查了下java文档源码
    public static Double valueOf(double d) {
        return new Double(d);
    }
它确实没有用到缓冲池
对比Integer的valueOf方法,是不一样的,所以才有这个结论的吧!
你认为呢?

我不是很清楚,
15 楼 xouou_53320 2012-02-02  
723766146 写道
if (integerCacheHighPropValue != null) //这段if代码不用深究,是一些判断,我看得眼花啊    
        {      
            int i = Long.decode(integerCacheHighPropValue).intValue();      
            i     = Math.max(i, 127);      
            h     = Math.min(i, Integer.MAX_VALUE - -low);      
        }

这个判断的作用是,cache中的最大值是可以配置的,integerCacheHighPropValue 是胚子的值

哦,多谢
14 楼 723766146 2012-02-02  
if (integerCacheHighPropValue != null) //这段if代码不用深究,是一些判断,我看得眼花啊    
        {      
            int i = Long.decode(integerCacheHighPropValue).intValue();      
            i     = Math.max(i, 127);      
            h     = Math.min(i, Integer.MAX_VALUE - -low);      
        }

这个判断的作用是,cache中的最大值是可以配置的,integerCacheHighPropValue 是胚子的值
13 楼 m635674608 2012-02-02  
xouou_53320 写道
11楼的哥么你也觉得这样吗? 这些只是我的以前在网上看的资料加上自己的一些推测,
而且源码中似乎也是这样的,但我
没有具体看到哪本书上有这个说法,最近打算看看 think in java ,


是啊。我也觉得是这样的啊。我感觉你技术应该不错啊。。
我也比较喜欢研究底层的技术。。源码什么的。。。
12 楼 xouou_53320 2012-02-01  
11楼的哥么你也觉得这样吗? 这些只是我的以前在网上看的资料加上自己的一些推测,
而且源码中似乎也是这样的,但我
没有具体看到哪本书上有这个说法,最近打算看看 think in java ,
11 楼 m635674608 2012-02-01  
xouou_53320 写道
燈小嗨 写道
xouou_53320 写道
燈小嗨 写道
请问“Integer缓冲池中的对象” 是放在堆中吗?

我觉得是的,因为是new出来的对象,你认为呢?

我觉得有可能啊,就是说不同的引用共享了堆内存。那会不会有可能是和String str = "aaa"中的str一样不放在堆中呢?

先来补充下我对Integer缓冲池对理解:
缓冲池是java对系统的优化,它是一种管理内存的机制,是一种数据结构,它可以管理多个缓冲区,IntegerCache就是一个缓冲区,cache[]数组中保存的是指向Integer类型对象的指针,虽然Integer缓冲对象是new出来的,但是是由缓冲池管理,我没有书本,这个理解方式只是看源代码自己想的,可能不对,欢迎一起讨论.
然后说String str = "aaa";
"aaa"本身就是一个字符串对象,它在编译时就被定义在了数据区,在运行时直接创建到常量池,或者说数据区,而str是当程序运行到这句代码时系统在内存的栈区分配的一个指针变量,指向了常量池中的"aaa"对象,
如果是String str = new String("aaa"); 在编译时,"aaa"对象被创建到数据区,在运行时执行到new String()时,程序动态的开辟一块内存空间,
并将数据区中的"aaa"对象复制一份放到堆中,并返回一个引用复制到str所在栈中,此时这一条语句创建了1个新的String对象。加上原来在数据区中的对象一共2个对象,不知道我说的对不对,仅供讨论..

xouou_53320 写道
燈小嗨 写道
xouou_53320 写道
燈小嗨 写道
请问“Integer缓冲池中的对象” 是放在堆中吗?

我觉得是的,因为是new出来的对象,你认为呢?

我觉得有可能啊,就是说不同的引用共享了堆内存。那会不会有可能是和String str = "aaa"中的str一样不放在堆中呢?

先来补充下我对Integer缓冲池对理解:
缓冲池是java对系统的优化,它是一种管理内存的机制,是一种数据结构,它可以管理多个缓冲区,IntegerCache就是一个缓冲区,cache[]数组中保存的是指向Integer类型对象的指针,虽然Integer缓冲对象是new出来的,但是是由缓冲池管理,我没有书本,这个理解方式只是看源代码自己想的,可能不对,欢迎一起讨论.
然后说String str = "aaa";
"aaa"本身就是一个字符串对象,它在编译时就被定义在了数据区,在运行时直接创建到常量池,或者说数据区,而str是当程序运行到这句代码时系统在内存的栈区分配的一个指针变量,指向了常量池中的"aaa"对象,
如果是String str = new String("aaa"); 在编译时,"aaa"对象被创建到数据区,在运行时执行到new String()时,程序动态的开辟一块内存空间,
并将数据区中的"aaa"对象复制一份放到堆中,并返回一个引用复制到str所在栈中,此时这一条语句创建了1个新的String对象。加上原来在数据区中的对象一共2个对象,不知道我说的对不对,仅供讨论..

不错、、这位童鞋理解的很到位
10 楼 xouou_53320 2012-02-01  
燈小嗨 写道
xouou_53320 写道
燈小嗨 写道
请问“Integer缓冲池中的对象” 是放在堆中吗?

我觉得是的,因为是new出来的对象,你认为呢?

我觉得有可能啊,就是说不同的引用共享了堆内存。那会不会有可能是和String str = "aaa"中的str一样不放在堆中呢?

先来补充下我对Integer缓冲池对理解:
缓冲池是java对系统的优化,它是一种管理内存的机制,是一种数据结构,它可以管理多个缓冲区,IntegerCache就是一个缓冲区,cache[]数组中保存的是指向Integer类型对象的指针,虽然Integer缓冲对象是new出来的,但是是由缓冲池管理,我没有书本,这个理解方式只是看源代码自己想的,可能不对,欢迎一起讨论.
然后说String str = "aaa";
"aaa"本身就是一个字符串对象,它在编译时就被定义在了数据区,在运行时直接创建到常量池,或者说数据区,而str是当程序运行到这句代码时系统在内存的栈区分配的一个指针变量,指向了常量池中的"aaa"对象,
如果是String str = new String("aaa"); 在编译时,"aaa"对象被创建到数据区,在运行时执行到new String()时,程序动态的开辟一块内存空间,
并将数据区中的"aaa"对象复制一份放到堆中,并返回一个引用复制到str所在栈中,此时这一条语句创建了1个新的String对象。加上原来在数据区中的对象一共2个对象,不知道我说的对不对,仅供讨论..
9 楼 xouou_53320 2012-02-01  
据说缓冲池是由系统管理的,它可以包含多个类型的缓冲区,比如Integer的缓冲IntegerCache, 或者Byte类型的缓冲   
public static Byte valueOf(byte b) {
        final int offset = 128;
        return ByteCache.cache[(int)b + offset];
    }
8 楼 xouou_53320 2012-02-01  
yzz9i 写道
Float     (没有缓存)
Doulbe    (没有缓存) 能说为啥莫

这2句话,我也是在网上看到的,我查了下java文档源码
    public static Double valueOf(double d) {
        return new Double(d);
    }
它确实没有用到缓冲池
对比Integer的valueOf方法,是不一样的,所以才有这个结论的吧!
你认为呢?
7 楼 yzz9i 2012-02-01  
Float     (没有缓存)
Doulbe    (没有缓存) 能说为啥莫
6 楼 燈小嗨 2012-02-01  
xouou_53320 写道
燈小嗨 写道
请问“Integer缓冲池中的对象” 是放在堆中吗?

我觉得是的,因为是new出来的对象,你认为呢?

我觉得有可能啊,就是说不同的引用共享了堆内存。那会不会有可能是和String str = "aaa"中的str一样不放在堆中呢?
5 楼 xouou_53320 2012-01-31  
燈小嗨 写道
请问“Integer缓冲池中的对象” 是放在堆中吗?

我觉得是的,因为是new出来的对象,你认为呢?
4 楼 燈小嗨 2012-01-31  
请问“Integer缓冲池中的对象” 是放在堆中吗?
3 楼 xouou_53320 2012-01-31  
1楼的朋友你是jdk是什么版本啊?

2楼的朋友可以编译的 ,我的是jdk7
2 楼 jancyjin 2012-01-31  
兄弟在jdk1.5下自己试试再发表意见行不...
raitt79 写道
  Integer a = 156;  
    Integer b = 156;
胡扯这样写jdk编译都不会通过需要转换成int类型的

1 楼 raitt79 2012-01-31  
  Integer a = 156;  
    Integer b = 156;
胡扯这样写jdk编译都不会通过需要转换成int类型的

相关推荐

    (完整版)最全的java学习笔记(必看).pdf

    * 2.3 常量和变量:Java语言中的常量和变量是用于存储数据的基本单元。常量是不可改变的量,而变量是可改变的量。 * 2.4 运算符与表达式:Java语言中的运算符包括算术运算符、比较运算符、逻辑运算符、赋值运算符等...

    Java学习笔记学习笔记

    Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习...

    林信良java学习笔记

    《林信良Java学习笔记》是一本深受程序员喜爱的Java学习资源,尤其因其繁体字版,对于中文读者来说,提供了更为亲切的阅读体验。这本书深入浅出地讲解了Java编程语言的基础知识和高级特性,旨在帮助初学者快速掌握...

    林信良JAVA学习笔记

    著作:《JAVA 学习笔记》、《Spring 技术手册》,为SUN官方教材主要编写成员之一 博客: http://blog.csdn.net/caterpillar_here 详细信息: http://www.china-pub.com/computers/common/info.asp?id=31664

    java学习笔记1

    Java学习笔记1是学习Java过程中的笔记,主要记录了Eclipse开发环境中的快捷键使用、编辑功能、查找和调试等知识点。 Eclipse快捷键 Eclipse中有许多快捷键,掌握这些快捷键可以大大提高开发效率。下面列举了一些...

    java学习笔记.zip

    java学习笔记java学习笔记.zipjava学习笔记.zipjava学习笔记.zipjava学习笔记.zipjava学习笔记.zipjava学习笔记.zipjava学习笔记.zipjava学习笔记.zipjava学习笔记.zipjava学习笔记.zipjava学习笔记.zipjava学习笔记...

    Java 学习笔记Java学习笔记

    4. 集合框架:Java集合框架是用于存储和操作对象的工具,包括List(如ArrayList和LinkedList)、Set(如HashSet和TreeSet)、Map(如HashMap和TreeMap)等接口及其实现类。它们提供了丰富的API用于添加、删除、查找...

    Java学习笔记——良葛格

    Java,作为一种广泛使用的编程语言,尤其在企业级应用开发中占据着重要地位。"Java学习笔记——良葛格"是...通过学习这份笔记,读者可以逐步掌握Java编程的基本技能,并为进一步深入学习Java和相关技术打下坚实的基础。

    Java学习笔记(林信良)

    林信良的《JAVA学习笔记》聚焦于Java编程语言的关键概念和技术,特别强调了Java Standard Edition (J2SE) 5.0及JDK 6的更新与改进。本书不仅适合Java初学者,也适合想要深入了解J2SE 5.0新特性的开发者。以下是根据...

    Java JDK 5.0学习笔记:TP312JA L393.iso

    Java JDK 5.0学习笔记:TP312JA L393.iso 随书光盘,欢迎大家下载 大家共享^A^

    Java基础 学习笔记 Markdownr版

    3. 输入/输出(IO)流:Java的15IO流.md文件深入解析了IO流的使用,包括文件流、字符流、字节流以及缓冲流的处理。IO流是数据传输的桥梁,允许程序与外部设备进行数据交换。 4. 多线程:在10多线程.md中,介绍了...

    Java学习笔记(必看经典).pdf

    本知识点的标题为“Java学习笔记(必看经典)”,意味着所整理的内容是针对Java初学者的一系列核心概念和原理的总结。 首先,面向对象编程是Java语言的核心,它与传统的面向过程编程有显著的不同。面向对象编程强调的...

    JAVA学习笔记 林信良

    此外,《JAVA学习笔记》还涵盖了集合框架,包括ArrayList、LinkedList、HashSet、HashMap等各种集合类的使用,以及泛型、迭代器和流API的应用。这些内容对于处理数据和实现复杂算法至关重要。 对于多线程编程,书中...

    java学习笔记markdown

    【Java学习笔记Markdown版】是针对Java初学者和进阶者的一份详尽教程,以Markdown格式编写,便于阅读和整理。Markdown是一种轻量级的标记语言,它允许用户使用易读易写的纯文本格式编写文档,然后转换成结构化的HTML...

    java学习笔记.pdf

    "Java学习笔记" 本资源是一个关于Java编程语言的学习笔记,涵盖了Java的基础知识、语法、数据类型、变量、类型转换等方面的内容。 标题:"java学习笔记.pdf" 描述:"想自学的小伙伴可以看俺" 标签:"Java" 部分...

    韩顺平编写的java学习笔记(全)

    - **JDK简介**:Java Development Kit,包含Java运行环境(JRE)、工具和基础类库。 - **安装过程**:从Oracle官方网站下载对应版本的JDK安装包。 - **环境变量配置**:设置`JAVA_HOME`和`PATH`变量,确保命令行可访问...

    Java学习笔记(必看经典).doc

    6. **输入/输出流**:Java提供了强大的I/O流系统,支持文件读写、网络通信和数据序列化等操作,如FileInputStream和FileOutputStream用于文件操作,Socket和ServerSocket用于网络编程。 7. **多线程**:Java内置了...

    读书笔记:零基础轻松学 Java 学习笔记.zip

    读书笔记:零基础轻松学 Java 学习笔记

    java学习笔记JDK6

    - **自动装箱与拆箱**:在JDK 6中,基本类型和其对应的包装类之间可以无缝转换,提高了代码的可读性和效率。 - **枚举类型**:提供了一种更安全的方式来表示固定集合的值,避免了传统常量类的潜在问题。 - **动态...

Global site tag (gtag.js) - Google Analytics