JAVA 参数传递 小记一则
2016-01-06 19:26
399 查看
JAVA 参数传递 小记一则
问题起源环境是JDK 7。
在修改一处BUG的时发现,原代码试图将Integer类型的参数传入方法,在方法内更新值,并在方法外部使用。
当然这样是行不通的,实际每次方法内部都会产生新的Integer对象。因为代码涉及的地方非常多,因此尝试在方法内修改传入的Integer参数值。
网上搜了一下,Integer是Immutable对象,其所有成员变量均是final的,另有其他几个条件构成Immutable对象的条件不一一列出。进一步,可以通过反射改变对象的Immutable特性,这样传入的Integer对象即为普通对象,能在方法内部改变Integer值。
如下测试代码,在方法内部改变了Integer值,但是却导致另一个问题。
private static void intPlus(Integer x) throws Exception{ Field f = x.getClass().getDeclaredField("value"); f.setAccessible(true); f.setInt(x, x+1); } public static void main(String[] args) { Integer x = 10; intPlus(x); System.out.println("x="+x); // 结果 11 Integer tempX1 = 10; System.out.println("tempX1="+tempX1); // 结果 11 }
方法intPlus导致之后任何地方使用Integer x = 10;都有问题。
进一步
1.Integer 对象定义中有如下内部类。它会缓存一部分 Integer 对象,因为Integer是不可改变的Immutable对象,更改等价于重新生成。因此常用数值的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) { 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); } 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() {} }
Integer a = 10 这条语句,JAVA会进行装箱操作,实际执行的是下面这句代码
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); }
3.JAVA参数传递是值传递,intPlus 方法拿到的是x对象的引用的副本,但方法内部改变了x对象实际的值和属性,x恰好是存储在那个缓存中的一个,因此实际上改变了缓存区中的值。而Integer a = 10 时,JAVA会进行装箱操作时又恰好使用的valueOf方法类似搜索相应的缓存下标取出值,因此取出来的值就对不上了。
4. Integer x = new Integer(10);就能简单避免这个问题。
完整测试代码如下
private static void intPlus(Integer x) throws Exception{ Field f = x.getClass().getDeclaredField("value"); f.setAccessible(true); f.setInt(x, x+1); } public static void main(String[] args) { System.out.println("**********************"); for(long k=0;k<5;k++){ Integer x = new Integer(10); intPlus(x); System.out.println(x); } // 测试 Integer tempX1 = 10; System.out.println("tempX1="+tempX1); // 结果10 System.out.println("**********************"); for(long k=0;k<5;k++){ Integer x = 10; intPlus(x); System.out.println(x); } System.out.println("**********************"); for(long k=0;k<5;k++){ Integer b = 127; intPlus(b); System.out.println(b); } System.out.println("**********************"); for(long k=0;k<5;k++){ Integer c = 128; intPlus(c); System.out.println(c); } // 测试 System.out.println("**********************"); Integer tempX2 = 10; System.out.println("tempX2="+tempX2); // 结果 15 Integer tempB = 127; System.out.println("tempB="+tempB); // 结果 132 Integer tempC = 128; System.out.println("tempC="+tempC); // 结果 128 }
首博, 2016-01-11, 纪念一下!
欢迎指正!
主要参考:
http://blog.csdn.net/kkdelta/article/details/3955399
/article/2578056.html
相关文章推荐
- Java基础(下)
- 高斯消元算法实现(Java)
- Java基础之枚举妙用
- Java基础之枚举妙用
- Java基础之枚举妙用
- Java基础之枚举妙用
- Spring MVC @ResponseBody 中文乱码解决
- Spring环境下MyBatis支持多个Datasource参考实现
- 自己 用到的 spring注解
- java synchronized关键字
- JAVA的面向对象编程----笔记
- Java——Java接口
- Prim最小生成树算法详解以及java实现源代码
- java 修改项目web访问根目录
- Java——Java封装
- java比较器
- IO流中的其他对象
- Java——Java抽象类
- java 国际化
- opensuse42.1下jdk的安装