如何在java里面实现值交换

您所在的位置:网站首页 交换两个整数的值java语言 如何在java里面实现值交换

如何在java里面实现值交换

2024-07-12 03:59| 来源: 网络整理| 查看: 265

看到一道题目,如何实现java的值交换 看起来好像很简单

public static void main(String[] args) { Integer a=1; Integer b=2; swap(a,b); //要求输出a=2 b=1 System.out.println("a="+a+",b="+b); } private static void swap(Integer a, Integer b) { }

二逼程序员

public static void main(String[] args) { Integer a=1; Integer b=2; swap(a,b); //要求输出a=2 b=1 System.out.println("a="+a+",b="+b); } private static void swap(Integer a, Integer b) { Integer temp=a; a=b; b=temp; }

结果 在这里插入图片描述

java是值传递的,方法里面只是有一份值的拷贝,如果传递的是对象,则是对象的引用值的拷贝。 只对这个拷贝进行操作,不会改变原来的引用关系。

比如说 在这里插入图片描述

在方法里面,交换了两个对象 在这里插入图片描述

实际上方法里面对引用对操作 ,并没有改变原来的引用关系,a b还是指向原来的object对象

甚至 改成 在这里插入图片描述

在这里插入图片描述

仍然不会有影响。 这个就是java的值传递,区别于c或者c++的指针。

但是 ,如果是在方法里面,改掉了原来对象里面的属性,则会生效。

在这里插入图片描述 在这里插入图片描述

回到刚刚的那个问题,熟练程序员会一眼看出由于java是值传递,所以普通交换是无效的。 于是就会自然而然的想到, 得去改这个引用指向的对象本身。 然后,会发现 在Integer对象里面,有value 在这里插入图片描述

如果能改掉这个value值,就可以改变值了。 但是这个值被 private final 修饰。 但可以尝试通过反射改掉这个对象的修饰符 将private改为public 然后去尝试改变value的值。

比如说 在这里插入图片描述

在这里插入图片描述

这个时候发现,私有字段可以改,但是final修饰的是否可以改呢? 在这里插入图片描述

在这里插入图片描述 private final String username; 也可以改。

再试试基本类型能否改。 在这里插入图片描述

在这里插入图片描述

发现 牛逼!! 也可以改。

接下来顺着这个思路 完成之前那个问题。

Class aClass = a.getClass(); Field field= aClass.getDeclaredField(“username”); field.setAccessible(Boolean.TRUE); field.set(a,666); System.out.println(a.getUsername() + " " + b.getUsername());

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Integer a = 4444; Integer b = 5555; swap(a, b); //要求输出a=5555 b=4444 System.out.println("a=" + a + ",b=" + b); } private static void swap(Integer a, Integer b) throws NoSuchFieldException, IllegalAccessException { Class bb = b.getClass(); Field bbb = bb.getDeclaredField("value"); bbb.setAccessible(Boolean.TRUE); bbb.set(b, 4444); Class aa = a.getClass(); Field aaa = aa.getDeclaredField("value"); aaa.setAccessible(Boolean.TRUE); aaa.set(a, 5555); }

输出结果 在这里插入图片描述

事实证明: 即使private final 修饰的字段,依然可以通过反射进行修改!! 所以,即使一个对象,被private+final修饰,且没有set方法,没有任何可以改变其值的方法,依然可以通过反射改掉。

但是 反射修改不掉static修饰的字段 在这里插入图片描述 java.lang.IllegalAccessException: Can not set static final java.lang.String field

甚至就连号称不可变的String类,也能被反射改掉值!! 在这里插入图片描述 在这里插入图片描述

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Integer a = 1; Integer b = 2; swap(a, b); //要求输出a=2 b=1 System.out.println("a=" + a + ",b=" + b); } private static void swap(Integer a, Integer b) throws NoSuchFieldException, IllegalAccessException { Integer temp=new Integer(b); Class bb = b.getClass(); Field bbb = bb.getDeclaredField("value"); bbb.setAccessible(Boolean.TRUE); bbb.set(b, a); Class aa = a.getClass(); Field aaa = aa.getDeclaredField("value"); aaa.setAccessible(Boolean.TRUE); aaa.set(a, temp); }

在这里插入图片描述 注意点! Integer里面有缓存,缓存了-127 到128之间的值 使用valueOf的时候会去返回的缓存!! 在这里插入图片描述

但是 普通的赋值 Integer temp=2 这个时候实际上也是取的缓存的值 在这里插入图片描述 在这里插入图片描述

只是通过反射去改了a的值,导致temp也发生了变化。

这里面,a的值为1,b的值为2, 这里的a和b的引用均指向缓存地址,地址上存储的值分别为1和2。

因此 将把b指向的值,通过反射改为1的时候,实际上 是将缓存地址上的值改掉了。 原本b引用指向的就是2。 而temp=2 也是指向的2。 b和temp都是指向了同一个值,将那个值改掉之后,b和temp都会变。

验证如下。如果b和temp不是指向同一个在-127和128范围的数,b改变 temp不改变!

在这里插入图片描述

在这里插入图片描述

大神级程序员 手动滑稽 在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3