java传值还是传引用基础关于值和引用,自动拆箱和装箱的问题

关于java自动装箱与自动拆箱的问题_java吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:631,988贴子:
关于java自动装箱与自动拆箱的问题收藏
Integer i = 10; Integer j = new Integer(10)是不相等的,这是为什么呢?前者是要指向常量池,后者是要指向堆么?前者要进行自动装箱,但是当两者比较的时候不需要拆箱,是不是对象就不一样了?
相等是指数值相等
一个是数值,一个是对象,对象也就是引用的意思了,他们直接==肯定返回假的吧
Integer是不是对象对象是不是要用equals比较,结果肯定是true,肯定是酱紫
integer i是在堆内存中有个包装类对象i值为10,j是在柞内存指向新new出来的对象值为10,所以你比较两个对象是否相等要比较他们的equals方法和hadhcode方法,对象i因为柞中没有变量指向他,所以两个对象不可能相等。个人理解,有错望指出
Integer a=10;Integer b=new Integer(10);int c=b;System.out.println(a==c);这样呢?
等号比较的是内存地址,equals比较数值,你试试integer i=10 和integer j=10
i==j,手机回复,写的比较乱
前者是常量池地址,后者是堆内存地址吧
只要是你new出来的都是一个新的对象,不会和其他值相等的,就像String s1=new String(&s&); String s2=new String(&s&); System.out.println(s1==s2);肯定是false
你可以用i.equals(j)来比较字面量如果你要用i==j,因为是两个对象,他们存储的地址是不一样的,所以是false
public static void main(String[] args) {Integer i = 10;Integer j = new Integer(10);Integer k = 10;System.out.println(i == j); // falseSystem.out.println(i == k); // trueSystem.out.println(Integer.valueOf(10) == Integer.valueOf(10)); // trueSystem.out.println(Integer.valueOf(150) == Integer.valueOf(150)); // falseInteger ii = 150;Integer jj = new Integer(150);Integer kk = 150;System.out.println(ii == jj); // falseSystem.out.println(ii == kk); // false}使用new肯定是新创建对象了,每个对象都在内存中占有独立的空间。而自动装箱看来是调用了valueOf方法,Integer源码里有自己的缓存IntegerCache,缓存了-128~127之间的整型数对象,所以i和k相等,而ii和kk不等。
学长告诉你!不是单例new两次new当然会得到2个对象!
笼统的讲Java只有比较的时候都是比较的值.
这个问题真蛋疼
Integer的常量池也在堆内存里,这不是什么高端的东西,看一下Integer.java就知道它是怎么实现的了。重点是使用new构造的对象,除了他自己,没有任何其它的对象能由==运算得到true。
i的值是10而j是对象的地址
学着自己看源码 Integer 把-127-128 之间的每个值建立了一个对应的Integer 对象,当你Integer a = 10的时候他就自动把早就创建好的对象返回过来,所以你用==比较的时候就会出现true,但==还是比较的是地址。你试试如果大于128就会是false了
Wow. ..wonderful...
不要总说equals比较的是内容,看一下api文档中object的equals方法比较是由内存地址转化而来的哈希码,哈希码和内存地址一样是唯一的,楼上已介绍的很清楚,紧紧是想纠正楼主对equals的错误理解           —— ——我问,你不说,这是隔阂;我问,你说,这是信任;我不问,你说,这是依赖;我不问你不说,这是默契。   
登录百度帐号推荐应用1.Java封装类
对于简单类型数据,为了和Java面向对象的思想一致,Java对它们进行了封装,使它们都有相应的封装类2.Java自动装箱和拆箱定义
Java 1.5中引入了自动装箱和拆箱机制:
自动装箱:把基本类型用它们对应的引用类型包装起来,使它们具有对象的特质,可以调用toString()、hashCode()、getClass()、equals()等方法。
Integer a=3;//这是自动装箱
其实编译器调用的是static Integer valueOf(int i)这个方法,valueOf(int
i)返回一个表示指定int值的Integer对象,那么就变成这样:&
Integer a=3; =& Integer a=Integer.valueOf(3);
拆箱:跟自动装箱的方向相反,将Integer及Double这样的引用类型的对象重新简化为基本类型的数据。
int i = new Integer(2);//这是拆箱
编译器内部会调用int intValue()返回该Integer对象的int值 注意:自动装箱和拆箱是由编译器来完成的,编译器会在编译期根据语法决定是否进行装箱和拆箱动作。
一个简单的例子
1. Integer integer1 = 100;
2. Integer integer2 = 100;
3. System.out.println("integer1==integer2: " +
(integer1 == integer2));// true 自动装箱的两个缓存中的 Integer对象的引用比较&
4. System.out.println("integer1.equals(integer2):
" + (integer1.equals(integer2)));// true&
5. System.out.println("pare(integer2):
" + pareTo(integer2));// 0&
6. Integer integer3 = 200;&
7. Integer integer4 = 200;&
8. System.out.println("integer3==integer4: " +
(integer3 == integer4));// false 自动装箱的两个new Integer的引用比较&
9. System.out.println("integer3&integer4:
" + (integer3 & integer4)); // false 将两个对象拆箱,再比较大小&
10. System.out.println("integer3.equals(integer4): " + (integer3.equals(integer4)));//
11. System.out.println("pare(integer4): " + pareTo(integer4));//
12. Integer integer5 = new Integer(100);&
13. Integer integer6 = new Integer(100);&
14. System.out.println("integer5==integer6: " + (integer5 == integer6)); // false
两个不同的Integer对象引用的比较&
15. System.out.println("integer5.equals(integer6): " + (integer5.equals(integer6)));//
16. System.out.println("pare(integer6): " + pareTo(integer6));//
17. int int1 = 100;&
18. System.out.println("integer1==int1: " + (integer1 == int1));// true Integer缓存对象拆箱后与int比较&
19. System.out.println("integer1.equals(int1): " + (integer1.equals(int1)));//
20. System.out.println("pare(int1): " + pareTo(int1));//
21. int int2 = 200;&
22. System.out.println("integer3==int2: " + (integer3 == int2));// true Integer对象拆箱后与int比较&
23. System.out.println("integer3.equals(int2): " + (integer3.equals(int2)));//
1. System.out.println("pare(int2): " + pareTo(int2));//
3.源码分析
1. public static Integer valueOf(inti) {&
2. if(i &= -128 &&i &=IntegerCache.high)&
3. return IntegerCache.cache[i + 128];&
5. return new Integer(i);
IntegerCache内部类
1. private static class IntegerCache {static final&
3. static final Integer cache[];&
4. 5. static {
6. final int low = -128
7. int h = 127;
8. if (integerCacheHighPropValue !=null) {&
9. int i=Long.decode(integerCacheHighPropValue).intValue();&
10. i = Math.max(i, 127);&
11. h = Math.min(i, Integer.MAX_VALUE - -low);&
13. high =&
14. cache =new Integer[(high - low) + 1];&
15. int j =&
16. for(int k = 0; k ++)
17. cache[k] =new Integer(j++);
用integerCacheHighPropValue变量设置自动装箱池大小,设置-XX:AutoBoxCacheMax=选项再次测试&3&中代码
在eclipse中,选中源文件,右键Run as―&RunConfiguratio---&Arguments,在VM arguments中做以下设置:运行,控制台报错:Unrecognized
VM option 'AutoBoxCacheMax=256'
找到JAVA_HOME/jre/lib/i386/jvm.cfg, 只需要把-server和-clent换个位置就行了.
楼主邀你扫码
参与上面帖子讨论
你尚未登录或可能已退出账号:(请先或者java装箱与拆箱的深入理解 - 简书
java装箱与拆箱的深入理解
Java有一个类型系统有两个部分组成,包含基本类型(byte、char、int、short、long、float、double、boolean)和引用类型。而基本类型则对应着各自的引用类型,称为装箱的基本类型。而引用类型对应着各自的基本类型,称为拆箱的基本类型。对应的类型为:(Byte、Character、Integer、Short、Long、Float、Double、Boolean)
下面一具体例子来说明装箱与拆箱
//java 1.5之前创建一个Integer对象
Integer i = new Integer(10);
//java 1.5之后有了装箱的特性,直接用下列方式生成一个Integer对象
//在这个过程中会将int 类型的10自动装箱成为Integer类型
Integer i = 10;
//拆箱 输出的值为20,这个过程中,会先将Integer类型的j自动拆箱为基本类型的10,最后完成运算
Integer j = new Integer(10);
int k = 10;
System.out.print(j+k);
下面来说说基本数据类型与其对应的引用类型的区别:
基本类型只有值,而装箱基本类型既具有值也具有它们对象的同一性(就是两个装箱的基本类型具有相同的值和不同的同一性(对象不一样))
基本类型只有功能完备的值,而每个装箱类型不仅具有完备的值还具有所有功能值之外的null。
基本类型通常比装箱基本类型更节省时间和空间。
下面来举一个《Effective java中》的一个例子进行分析
Comparator&Integer& comparator = new Comparator&Integer&()
public int compareTo(Integer first,Integer second)
return first & second ? 1:first == second ? 0 : -1;
//这两个Integer实例都表示相同的值42
Integer a = new Integer(42);
Integer b = new Integer(42);
int c = pareTo(a,b);
//返回值多少 0 ? 但实际结果却是-1,难道 42 & 42 ?
下面就来解释上面例子的原因:首先执行 a&b,两个Integer都自动拆箱为42,不成立,则执行 a==b,乍一看,没什么问题,42==42没问题啊,但实际上这是违反了了装箱的同一性,因为a和b都是引用类型,根据上述两个装箱类型具有相同的值和不同的同一性,只是两个对象的比较,即这两个对象是不同对象,所对应的内存也不一样,a!=b。所有正确答案应该是 -1。
现在来说说装箱和拆箱是怎么实现的:
public static void main(String[] args){
Integer i = 10;
int j = 10;
System.out.print("i+j = "+(i+j));
打印结果为:
Paste_Image.png
反编译class文件得到:
Paste_Image.png
第一行是装箱过程,查看源码实际是调用了Integer.valueOf(int)方法返回一个Integer实例第三行进行加法运算的时候是拆箱过程,将Integer实例i拆箱为int型,然后进行加法运算,实际是调用了Integer.intValue()方法返回一个int型数据。
关于装箱与拆箱大致的都讲的差不多了。下面举几个面试中关于装箱与拆箱会问到的例子:
public class Main
public static void main(String[] args)
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i1==i2); //返回true
System.out.println(i3==i4); //返回false
下面来解释下这个原因
//这是装箱的源码
public static Integer valueOf(int i) {
i &= 128 || i & -128 ? new Integer(i) : SMALL_VALUES[i + 128];}
/** * A cache of instances used by {@link Integer#valueOf(int)} and auto-boxing */
private static final Integer[] SMALL_VALUES = new Integer[256];
for (int i = -128; i & 128; i++){
SMALL_VALUES[i + 128] = new Integer(i);
//当值在[-128,127)之间时,装箱操直接取已经cache好的Integer实例,所以i1==i2,当大于127时,每次都是new出来的Integer,指向不同的对象,所以i3!=i4
public class Main {
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
Long h = 2L;
System.out.println(c==d);
System.out.println(e==f);
System.out.println(c==(a+b)); // true
System.out.println(c.equals(a+b));//true
System.out.println(g==(a+b));//false
System.out.println(g.equals(a+b));//false
System.out.println(g.equals(a+h));//true
//当 "=="运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。另外,对于包装器类型,equals方法并不会进行类型转换用户名:田皓宇
文章数:61
评论数:267
访问量:138126
注册日期:
阅读量:1297
阅读量:3317
阅读量:443722
阅读量:1129558
51CTO推荐博文
先看以下两段代码:
代码片段1:
Integer&i1&=100;&Integer&i2&=100;&&if(i1&==&i2){&&&&&System.out.println(&i1&==&i2&&);&&}&else{&&&&&System.out.println(&i1&!=&i2&);&&}&&if(i1.equals(i2)){&&&&&System.out.println(&i1&==&i2&&);&&}else{&&&&&System.out.println(&i1&!=&i2&&);&}&&i1&==&i2&i1&==&i2&
代码片段2:
Integer&i1&=200;&Integer&i2&=200;&&if(i1&==&i2){&&&&&System.out.println(&i1&==&i2&&);&}&else{&&&&&System.out.println(&i1&!=&i2&);&}&&if(i1.equals(i2)){&&&&&System.out.println(&i1&==&i2&&);&}else{&&&&&System.out.println(&i1&!=&i2&&);&}&&&&&&&&&&&&&&&&&&&&&&&&&&&&i1!=i2&&&&&&&&&&&&&&i1==i2&
&比较看出,仅仅修改了一个数字,结果却有所不同,这到底是为什么呢?
& 究其原因,原来是编译程序蜜糖(compiler sugar)给你带来的甜头。【顾名思义,我们写少且对的代码,编译器多劳动点】
先说下以下几个概念:
一,打包(Wrapper)
& 不错,java和C++中都有包(package)的概念,java中还有jar包的存在,但是此包非彼包,但是都是从同一个形象的角度说明的。
话说在 JavaSE 5.0 之前,java的八大基本数据类型:long,int,double,float,boolean,short,char,byte必须亲自使用Long,Integer,Double,Float,Boolean,Short,Character,Byte类打包为对象,才能当做对象使用。又被称之为打包器。
&上述八大基本类型打包器都位于java.lang包之中。故若使用哪种数据类型,方式之一就是用new创建该数据类型实例时,传入该数据类型即可。
Integer&data&=&10;&Integer&wrapper&=&new&Integer(data);&System.out.println(data/3);&&System.out.println(wrap.doubleValue()/3);&&
于是乎,wrapper就是一个整型的对象,便可以使用Integer类中的方法,静态变量,常量等丰富的资源。而data就不能使用,只有眼巴巴的份。
&& 从JavaSE5.0开始,自动装箱(翻译为Auto Boxing)和自动拆箱(Auto unboxing)的出现,让上面的操作变得简单起来,这是&编译程序蜜糖&的功劳。从这个角度来看,每一个技术牛人都是一个长不大且爱玩的小朋友,因为总想吃糖。
二,自动装箱(Auto Boxing):
& 装箱,其实质还是打包数据类型,如上面的例子可以改写为:
Integer&wrapper&=&10;&
& 就是这么简单,再例如更一般化的Number类来自动装箱:
Number&number&=&100L;&
【100L会先被自动装箱为Long,然后指定给number】
其他类型亦是如此。
三,自动拆箱(Auto unboxing):
& 拆箱,顾名思义,就是自动取出打包器中的基本形态信息。
Boolean&&&yes&&=&true;&System.out.println(yes&&&&false);&
四,自动装箱与拆箱的实质
&& 如例子:
Float&f&=&3.14f;&&
& 在oracle/Sun 的JDK上,编译程序蜜糖,我现在特别喜欢这个词语,会自动将程序代码展开为:
Float&f&=&Float.valueOf(3.14f);&
&& 翻了翻JDK7的API文档发现,valueOf()函数在八大基本类中是那么的受欢迎,无异于眼下莫言的《丰富肥臀》在各大图书市场的火爆。
& 事实上,下面的这个例子也是合情合理的,但是执行呢?
Float&f1&=&null;&float&f2&=&f1;&
& 蜜糖给出的解释是:
Float&float&=&null;&float&f1&=&float.floatValue();&
&& 这段代码在编译的时候是通过的,但是执行的时候就会报出一个NullPointerException的错误。就相当于莫言童鞋将除了《丰乳肥臀》之外的3本书送给了甲乙丙,他却问甲乙丙有《丰乳肥臀》.
& 分析equals()方法,因为i1,i2均为对象,且只想同样的一个数值,所以使用equals()的两个判断语句执行结果都是一样的。
& 为什么使用操作符 == 的时候却出现了变化了呢?
& 翻出JDK7安装目录下的src.zip文档,当然我是借助于IDE读取的,找到了Integer.valueOf()的定义,如下:
public&static&Integer&valueOf(int&i)&{&&&&&&&&assert&IntegerCache.high&&=&127;&&&&&&&&if&(i&&=&IntegerCache.low&&&&i&&=&IntegerCache.high)&&&&&&&&&&&&return&IntegerCache.cache[i&+&(-IntegerCache.low)];&&&&&&&&return&new&Integer(i);&&&&}&
&i的范围是【-128,127】,而200不在这范围内,根据判断条件,返回的是一个新的Integer对象,因此在使用操作符 == 的时候,便出现了&i1!=i2&的结果。
&& 其他类型的valueOf()有自己的定义,需要在查看之.
&& 编译程序蜜糖的事情再举个例子,比如增强的for循环。
&& 例如:&&
&Integer[]&array&={89,99,109};&&&&for(int&arr&:array){&&&&System.out.printf(&%2d&,arr);&}&&for(int&i=0;i&array.i++){&&&&System.out.printf(&%2d&,arr[i]);&}&&
& 本文出自 “” 博客,请务必保留此出处
了这篇文章
类别:┆阅读(0)┆评论(0)
11:46:09 12:03:44 12:37:45 13:01:59 13:51:40君,已阅读到文档的结尾了呢~~
广告剩余8秒
文档加载中
深入剖析java中的装箱和拆箱
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
深入剖析java中的装箱和拆箱
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer--144.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口

我要回帖

更多关于 java值类型和引用类型 的文章

 

随机推荐