先来看一个经典的int,integer 的面试题。
传参如果是int 类型,则无法实现交换。
public void main (String[] args){
Integer a=1,b=2;
system.out.println("a= "+a+" b= "+b);
swap(a,b);
system.out.println("a= "+a+" b= "+b);
}
public void swap(int m,int n){
//实现交换a,b的值。
}
-
如果不了解a,b在内存的存储,那么这个肯定会写错。
-
int 在内存的存储方式是1-128是存在一个常量池里。即m和a指向同一个地址,交换m,n的值只是交换了引用的地址。
-
没有改变地址里存储的值。
-
这个传参是一个值传参,而不是一个引用传参。
-
通过修改m,n 的值来改变a,b的值,就是要改变m,n指向地址里的值。
-
普通的交换只是单纯的交换了m,n指向的地址,并不改变原来地址里存放的值。
-
由于a,b都是对象,通过反射来实现。
-
`
private static void swap(Integer a, Integer b) {
// TODO Auto-generated method stubtry { Field field = Integer.class.getDeclaredField("value"); Integer temp=new Integer(d.intValue()); field.setAccessible(true); field.set(b, a); field.set(a, temp); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println();
}`
-
如果swap 定义为swap(int a, int b),如何实现交换呢?
-
那可以直接将a,b转换为integer,再进行修改。
-
`static void swap(int a, int b) {
// TODO Auto-generated method stubtry { Integer c=a,d=b; Field field = Integer.class.getDeclaredField("value"); Integer temp=new Integer(d.intValue()); field.setAccessible(true); field.set(d, c); field.set(c, temp); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }
}`
-
如果main 方法里 如下定义: int x=1211,y=1922;,那么能够实现交换x ,y的值吗?不能
-
本次环境: jdk1.8
-
超过Integer 的缓存范围那么交换就不可以这么做了,看下Integer.valueOf()方法:
-
if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i);
-
最小值为-128,最大值为127;说明系统缓存了-128 到127 的对象,那么通过改变缓存对象的值,就改变了缓存对象原来地址指向的缓存值。
-
超过之后都是新的new 对象,故此swap方法无法交换两个对象的值。
-
swap(Integer a,Integer b) 则可以改变值,swap(int a,int b) 则无法改变值。
-
总结: 归根到底改变对象的值,必须是同一个对象。在一个局部方法里如果想交换两个对象的属性值,则只能是改变传递引用指向地址里的属性值,直接交换两个对象的引用是无效的。对象可以有多个引用,改变引用的地址并不能改变对象的值。