您的位置:首页 > 编程语言 > Java开发

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: