Integer 函数传参实现值交换
Posted xch-xiaocheng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Integer 函数传参实现值交换相关的知识,希望对你有一定的参考价值。
import java.lang.reflect.Field; public class MainClass { public static void main(String[] args) { Integer a = 128; Integer b = -129; swarp(a,b); System.out.println(a); System.out.println(b); try { System.out.println("________________________________________________"); swarp1(a,b); System.out.println(a); System.out.println(b); System.out.println("--------------------------------------------------"); Integer c = 128; System.out.println(c); Integer d = new Integer(128); System.out.println("--------------------------------------------------"); swarp2(a,d); System.out.println(a); System.out.println(d); } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void swarp(Integer a, Integer b){ Integer temp = a; a = b; b = temp; } public static void swarp1(Integer a, Integer b) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{ Field field = a.getClass().getDeclaredField("value"); field.setAccessible(true); Integer a1 = a; field.set(a, b); field.set(b, a1); field.setAccessible(false); } public static void swarp2(Integer a, Integer b) { Field field; try { field = a.getClass().getDeclaredField("value"); field.setAccessible(true); int a1 = new Integer(a); field.set(a, b); field.set(b, a1); field.setAccessible(false); } catch (NoSuchFieldException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
java 8
Integer 内部类
private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; } private IntegerCache() {} }
内部类预初始化从-128~127的Integer实例,每个具体实例的下标为i + (-IntegerCache.low),比如-128下标为-128-(-128)=0,再看一下自动装箱的函数valueOf
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
到这里我们上面的类的结果已经很明显
一、将在main函数内,将a,b,c,d 分别赋值为128,-129,128,128
输出结果为:
128
-129
________________________________________________
-129
128
--------------------------------------------------
128
--------------------------------------------------
128
-129
二、将main函数内的a,b,c,d 分别赋值为127,-128,127,127
输出结果为:
127
-128
________________________________________________
-128
-128
--------------------------------------------------
-128
--------------------------------------------------
127
-128
如果读到这里还不知道为什么会有这样的结果,那么请继续看
1、java 的传参都是传值,函数接收到的形参都是指向实例引用的副本,第一个函数(swap)在内部的操作都是对副本的操作,所以不管值是多少,两个值得交换都失败
2、当ab的值在-128~127范围内时,第二个函数内,虽然给a做了备份,但是已经利用反射,将具体的在缓存内相应下标的Integer的value值改变,在b值赋值时,调用valueOf,指向该实例,所以返回的结果是ab值相等;而第三个函数为什么会交换成功呢?因为d是new出来的值,并没有走valueOf自动装箱,是一个在缓存之外的实例
3、当ab值在-128~127范围外时,ab都是new的新实例,固可以交换成功
以上是关于Integer 函数传参实现值交换的主要内容,如果未能解决你的问题,请参考以下文章