拆箱装箱

  举个例子

  @Test

  public void testEquals() {

  int int1 = 12;

  int int2 = 12;

  Integer integer1 = new Integer(12);

  Integer integer2 = new Integer(12);

  Integer integer3 = new Integer(127);

  Integer a1 = 127; //或者写成Integer a1 = Integer.valueOf(127);

  Integer a2 = 127;//或者写成Integer a2 = Integer.valueOf(127);

  Integer a = 128;

  Integer b = 128;

  System.out.println("int1 == int2 -> " + (int1 == int2));

  System.out.println("int1 == integer1 -> " + (int1 == integer1));

  System.out.println("integer1 == integer2 -> " + (integer1 == integer2));

  System.out.println("integer3 == a1 -> " + (integer3 == a1));

  System.out.println("a1 == a2 -> " + (a1 == a2));

  System.out.println("a == b -> " + (a == b));

  }

  答案是:

  1、int1 == int2 -> true

  2、int1 == integer1 -> true

  3、integer1 == integer2 -> false

  4、integer3 == a1 -> false

  5、a1 == a2 -> true

  6、a == b -> false

  看看结果跟我们自己做的是不是都一样。

  下面我们就来详细解释一下,为什么是上面的结果。(下面的序号就是对应的是上面的答案序号)

  1、int1 == int2 为true,这个我就讲了,这个都知道

  2、int1 == integer1,Integer是int的封装类,当Integer与int进行==比较时,Integer就会拆箱成一个int类型,所以还是相当于两个int类型进行比较,这里的Integer,不管是直接赋值,还是new创建的对象,只要跟int比较就会拆箱为int类型,所以就是相等的。

  3、integer1 == integer2 -> false,这是两个都是对象类型,而且不会进行拆箱比较,所以不等

  4、integer3 == a1 -> false , integer3是一个对象类型,而a1是一个常量它们存放内存的位置不一样,所以也不等,具体存在内存的位置看以看文章

  5、6 看起来是一模一样的为什么一个是true,一个是false?这是因为Integer作为常量时,对于-128到127之间的数,会进行缓存,也就是说int a1 = 127时,在范围之内,这个时候就存放在缓存中,当再创建a2时,java发现缓存中存在127这个数了,就直接取出来赋值给a2,所以a1 == a2的。当超过范围就是new Integer()来new一个对象了,所以a、b都是new Integer(128)出来的变量,所以它们不等。

  根据以上总结:

  ①、无论如何,Integer与new Integer不会相等。不会经历拆箱过程,因为它们存放内存的位置不一样。(要看具体位置,可以看看这篇文章:点击打开链接)

  ②、两个都是非new出来的Integer,如果数在-128到127之间,则是true,否则为false。

  ③、两个都是new出来的,则为false。

  ④、int和integer(new或非new)比较,都为true,因为会把Integer自动拆箱为int,其实就是相当于两个int类型比较。

  行为差异

  当我们选择不同的值时,这种行为会改变:

  Integer int2_1 = Integer.valueOf("1000");

  Integer int2_2 = Integer.valueOf(1000);

  System.out.println("int2_1 == int2_2: " + (int2_1 == int2_2)); // false

  System.out.println("int2_1 equals int2_2: " + int2_1.equals(int2_2)); // true

  在这种情况下,只有比较equals才能得到正确的结果。

  这种行为差异的原因是JVM维护Integer范围为-128到127 的对象的缓存(可以使用系统属性“java.lang.Integer.IntegerCache.high”

  或JVM来覆盖上限值参数“-XX:AutoBoxCacheMax = size”)。对于此范围内的值,Integer.valueOf()将返回缓存的值,而不是创建一个新的值。

  因此,在第一个示例中,Integer.valueOf(1)并且Integer.valueOf(“1”)调用返回相同的缓存Integer实例。相比之下,在第二个示例中Integer.valueOf(1000),Integer.valueOf(“1000”)创建并返回了新Integer对象。

  ==参考类型的运算符测试参考相等(即同一对象)。因此,在第一个例子中int1_1 == int2_1是true因为引用是相同的

  。第二个例子int2_1 == int2_2是false,因为引用是不同的。

  Integer的缓存

  原因就在Integer的方法 valueOf

  我们来看这个方法的源码:字节码里调用的就是这个方法:

  public static Integer valueOf(int i) {

  if(i >= -128 && i <= IntegerCache.high)

  return IntegerCache.cache[i + 128];

  else

  return new Integer(i);

  }

  private static class IntegerCache {

  static final int high;

  static final Integer cache[];

  static {

  final int low = -128;

  // high value may be configured by property

  int h = 127;

  if (integerCacheHighPropValue != null) {

  // Use Long.decode here to avoid invoking methods that

  // require Integer's autoboxing cache to be initialized

  int i = Long.decode(integerCacheHighPropValue).intValue();

  i = Math.max(i, 127);

  // Maximum array size is Integer.MAX_VALUE

  h = Math.min(i, Integer.MAX_VALUE - -low);

  }

  high = h;

  cache = new Integer[(high - low) + 1];

  int j = low;

  for(int k = 0; k < cache.length; k++)

  cache[k] = new Integer(j++);

  }

  private IntegerCache() {}

  }无锡人流多少钱 http://www.xaytsgyy.com/

  Integer里弄了一个缓存,对于在 -128—127 之间的数值,会直接使用该缓存里的对象

  也就是说 Integer c = 3 或者 Integer c = Integer.valueOf(3) ,最终 c 得到的是Integer里的缓存对象

  同理,d也是获得该相同对象因此 进行 c == d 比较时,c和d引用的是同一个对象,因此就true

  而对于321,已经超出缓存范围了,因此 valueOf 方法会生成一个新的Integer对象因此e和f就引用不同 的对象了,进行==比较,当然就false了

  另外,对Integer的缓存,我们在日常开发时,对于小的整型值应该充分利用Integer的缓存对象省去过多的对象创建,回收的操作,这样会极大的提高程序性能

  Integer妙用与陷阱

  考虑下面的小程序,你认为会输出为什么结果?

  public class Test {

  public static void main(String[] args) {

  Integer n1 = 123;

  Integer n2 = 123;

  Integer n3 = 128;

  Integer n4 = 128;

  System.out.println(n1 == n2);

  System.out.println(n3 == n4);

  }

  }

  答案如下,请选择刮开:

  true

  fase

  是否和你预想的一致?

  我们知道==比较的是对象的引用,那这里为什么会这出这种情况呢?

  原理

  首先这是JDK在1.5版本中添加的一项新特性,把-128~127的数字缓存起来了,用于提升性能和节省内存。所以这个范围内的自动装箱(相当于调用valueOf(int i)方法)的数字都会从缓存中获取,返回同一个数字,所以现在你理解为什么了吧。同时这也会给我们开发带来预想不到的陷阱,直得注意!!

  而我们通过new Integer(1)这样就不会从缓存中获取,大家可以自行测试。

  我们来翻看下jdk中Integer的源码,下面是IntegerCache的源码,把从-128~high放在缓存中

  下面是valueOf的源码,先从缓存中获取,获取不到再new一个返回。

  从源码里面我们可以看到最小边界是-128,最大边界可以通过-XX:AutoBoxCacheMax进行配置,但也不会大于Integer.MAX_VALUE最大值。

  也就是说。该代码表示valueOf的隐士加包是有范围的只能加包-128~127,超过这个范围将用new Interger的方法。因此将代码中的123改为1000,两个输出将都是false,而且所用的方法也一样都是在堆中调用一个地址用来储存值,Interger类型的变量,储存地址。

  Integer在方法中的参数传递、返回值

  (1)JAVA里除了8种基本类型传参数是值传递,其他的类对象传参数都是引用传递。

  (2)Integer作为参数传递时引用传递。

  (3)Integer作为参数传入方法,如果不设置返回值,Inerger的值就不会改变,原因:Integer每次赋值/改变都是被赋予新的对象,当Integer作为引用传入后,接收的形参会被赋值成其他的引用,因为Integer里面的value是final类型的Int。

  举个栗子:

  public class test{

  public void add3(Integer i){

  System.out.println("i赋值前的地址:"+System.identityHashCode(i));

  i=3;

  System.out.println("i赋值后的地址:"+System.identityHashCode(i));

  }

  @Test

  public void test(){

  Integer a=5;

  System.out.println("a赋值前的地址:"+System.identityHashCode(a));

  add3(a);

  System.out.println("a赋值后的地址:"+System.identityHashCode(a));

  a=10;

  System.out.println("a修改值后的地址:"+System.identityHashCode(a));

  System.out.println(a);

  }

  }

  输出结果是:

  a赋值前的地址:352359770

  i赋值前的地址:352359770

  i赋值后的地址:243745864

  a赋值后的地址:352359770

  a修改值后的地址:699780352

  10

  源码分析

  在Integer源码中,int值是final修饰的,不可以改变

  class Integer{

  final int value; //一旦赋值,就不能改变。

  }

Integer装箱拆箱、参数传递的更多相关文章

  1. int和Integer及拆箱与装箱

    int和Integer 如果面试官问Integer与int的区别:估计大多数人只会说道两点,Ingeter是int的包装类,int的初值为0,Ingeter的初值为null.但是如果面试官再问一下In ...

  2. int和Integer的区别?包装类?装箱?拆箱?

    int和Integer的区别: 1) int是基本数据类型,直接存储的数值,默认是0; 2) Integer 是int的包装类,是个对象,存放的是对象的引用,必须实例化之后才能使用,默认是null; ...

  3. JAVA的自动装箱拆箱

    转自:http://www.cnblogs.com/danne823/archive/2011/04/22/2025332.html 蛋呢  的空间 ??什么是自动装箱拆箱 基本数据类型的自动装箱(a ...

  4. Java中的装箱拆箱

    一)  装箱与拆箱 Java中有概念是一切皆对象,因为所有的类都默认继承自Object.但是,对于数据类型是个例外,如short,int,long,float,double, byte,char,bo ...

  5. Java 装箱 拆箱

    Java 自动装箱与拆箱   ??什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing).拆箱(unboxing)是自J2SE 5.0开始提供的功能. 一般我们要创建一个类的对象的时候,我 ...

  6. Java 的自动装箱拆箱

    Java 是面向对象的语言,其基本数据类型也就有了相对应的类,称为包装类.以下是基本数据类型对应的包装类: 基本数据类型 包装类 byte(1字节) Byte short(2字节) Short int ...

  7. java(17) - 增强for循环、装箱拆箱、可变参数

    一.增强型for循环: 语法格式: 打印: A B C D E 当遍历集合或数组时,如果需要访问集合或数组的下标时,最好使用旧的方法来便利或循环,而不要用增强型for循环,因为它丢失了下标信息. 对于 ...

  8. Java之集合初探(二)Iterator(迭代器),collections,打包/解包(装箱拆箱),泛型(Generic),comparable接口

    Iterator(迭代器) 所有实现了Collection接口的容器都有一个iterator方法, 用来返回一个实现了Iterator接口的对象 Iterator对象称作迭代器, 用来方便的实现对容器 ...

  9. 理解JDK1.5的自动装箱拆箱

    JDK1.5的升级引入了装箱和拆箱概念,简单说就是为了简化书写. JDK1.5之前,创建Integer对象是需要这么写的  Integer i = new Integer("3") ...

随机推荐

  1. Netty 4 实现一个 NettyClient

    本文章为作者原创,有问题的地方请提出指正. 1.类继承Diagram 2.定义EndPoint类 目前仅仅定义了2个方法,分别用来获取本地或远程服务器的地址. package netty; impor ...

  2. Deepin系统中手动开启swap的方法

    Deepin系统中手动开启swap的方法 如何设置 swap(交换空间)的大小建议设置和你的实际物理内存一样大,如你的内存是8G的,则可将下面的count的值设为8192(当然这只是参考值,你可根据你 ...

  3. Python统计数据库中的数据量【含MySQL、Oracle】

    Python程序文件如下: # -*- coding: utf-8 # File : start.py # Author : baoshan import json import pymysql im ...

  4. Java8相关底层

    Java8是往并行方向走的.由面向对象到函数式编程. 在支持函数式编程的同时还可以支持面向对象的开发. 在JDK1.8里面,接口里面可以有实现方法的!默认方法,default.实现这个接口. 接口里面 ...

  5. SDKMAN一个基于命令行界面的SDK用户环境管理程序

    1.背景 使用过Python开发的朋友,应该了解到Python2和Python3语法的差异,有时候从网上下载了基于不同解释器的代码,要来回切换版本, 使用起来不是很方便,有时候甚至很麻烦.于是有人发明 ...

  6. 快速读取TXT几百万行数据, 然后插入到数据,SqlBulkCopy功能的确是有效率

    public static void Main(string[] args) { string strPath = "F:\\Download\\600.txt"; int lin ...

  7. java核心技术(卷一)

    一,java基本程序设计结构: 1,在网页中运行的 Java 程序称为 applet. 要使用 applet ,需要启用 Java 的 Web 浏览器执行字节码. 2,jdk安装目录下的 src.zi ...

  8. SQLServer for linux安装

    linux下安装sqlserver数据库有2种办法,第一使用yum镜像安装,第二使用rpm安装包安装 rpm安装地址为:https://packages.microsoft.com/rhel/7/ms ...

  9. 微服务, 架构, 服务治理, 链路跟踪, 服务发现, 流量控制, Service Mesh

    微服务, 架构, 服务治理, 链路跟踪, 服务发现, 流量控制, Service Mesh 微服务架构   本文将介绍微服务架构和相关的组件,介绍他们是什么以及为什么要使用微服务架构和这些组件.本文侧 ...

  10. 【问题】Could not locate PropertySource and the fail fast property is set, failing

    这是我遇到的问题 Could not locate PropertySource and the fail fast property is set, failing springcloud的其他服务 ...