之前朋友面试遇到了一个挺有趣的问题,题目如下:
public static void main(String[] args) throws Exception{ int a = 1; int b = 2; swap(a, b); System.out.println("a is "+a+", b is "+b); }
编写swap方法使a、b两个值交换数据,即a=2,b=1
这在个人知识范围内,觉得不可能实现,找了一段写的比较好的解释,如下:
java的基本数据类型共有8种,即int,short,long,byte,float,double,boolean,char(注意,并没有String的基本类型 )。
这种类型的定义是通过诸如int a = 1;long b = 255L;的形式来定义的。
如int a = 1;这里的a是一个指向int类型的引用,指向1这个字面值。这些字面值的数据,
由于大小可知,生存期可知(这些字面值定义在某个程序块里面,程序块退出后,字段值就消失了),出于追求速度的原因,就存在于栈中。
另外,栈有一个很重要的特殊性,就是存在栈中的数据可以共享。比如:
我们同时定义:
int a=1;
int b=2;
编译器先处理int a = 1;
首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为1的地址,没找到,就开辟一个存放1这个字面值的地址,然后将a指向3的地址。
接着处理int b = 2;在创建完b这个引用变量后,由于在栈中已经有2这个字面值,便将b直接指向2的地址。这样,就出现了a与b同时均指向2的情况。
定义完a与b的值后,再令a = 4;
那么,b不会等于4,还是等于2。在编译器内部,遇到时,它就会重新搜索栈中是否有4的字面值,如果没有,重新开辟地址存放4的值;
如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。
那怎么解决这个呢?
贴代码:
public static void main(String[] args) throws Exception { Integer a = 1333; Integer b = 2333; swap(a, b); System.out.println("a is "+a+", b is "+b); } private static void swap(Integer x, Integer y) throws Exception { int z= x; Field field = Integer.class.getDeclaredField("value"); field.setAccessible(true); field.set(x, y); field.set(y, z); System.out.println("x is "+x+", y is "+y); }
将基本类型改为对象类型,这样是不是就好了呢?看上去应该没什么问题,输出结果也是正确的,可试试a=1,b=2呢!
结果成了2 2,是不是觉得很怪异,JD反编译后如下:
private static void swap(Integer x, Integer y) throws Exception { int z= x; Field field = Integer.class.getDeclaredField("value"); field.setAccessible(true); field.set(x, y); field.set(y, Integer.valueOf(z)); System.out.println("x is "+x+", y is "+y); }
查看Integer源码valueOf(i)方法,就会发现原因了!
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
Integer是有自己的缓冲池[-128-128],field.set(x, y);这行代码会把缓冲池里面的值给修改了,将IntegerCache.cache[129]=IntegerCache.cache[130]=2
所以导致a=b=2,怎么破呢?
无非就是将获取的z值不走IntegerCache,那就直接new吧!修改代码
field.set(y, z);改为field.set(y, new String(z));问题解决,可还是最好不要使用公用的IntegerCache,继续修改代码:
public static void main(String[] args) throws Exception { Integer a = new Integer(1); Integer b = new Integer(2); swap(a, b); System.out.println("a is "+a+", b is "+b); }
成功了。
总结一下:
一)int数据存储在常量池,地址在栈。
二)Integer 定义的两个变量(如:integer a = 1; integer b = 2),它们公用一个IntegerCache。
相关推荐
而二维码则更进一步,能够存储大量数据,包括文字、网址、联系信息等,并且可以水平和垂直两个方向上存储信息,因此比传统的条形码具有更高的数据密度。 **Zint库介绍** Zint是一款开源的、强大的条码和二维码生成...
本PDF文件主要介绍了C#语言的面向对象编程相关知识点,涵盖了交换两个数据的值、定义方法、静态与非静态成员的调用方式、Main方法的四种形式、可变参数、代码规范、数组的定义和操作等方面的内容。 一、交换两个...
这里定义了两个方法,一个用于发送数据,一个用于接收数据。 **处理Parcelable数据** 在Android中,Parcelable是数据序列化的一种高效方式,常用于IPC。为了使自定义对象支持Parcelable,需要实现`Parcelable`接口...
冒泡排序是一种简单的排序算法,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。 ##### ϖ6. 快速排序 快速排序是一种非常高效的排序算法,采用分治法的思想,通过一趟排序...
Intent的数据传递主要通过两个方法实现:putExtra()和getExtra()。例如,要从一个Activity A传递字符串数据到另一个Activity B,可以在A中创建Intent,然后调用putExtra()方法添加数据: ```java Intent intent = ...
在这段代码中,通过定义了一个静态方法shuffle()来随机交换数组元素的位置: ```java public static void shuffle(int[] a) { for (int i = 0; i ; i++) { int j = new Random().nextInt(a.length); int t = a[i]...
面向对象的方法将数据及对数据的操作方法放在一起,作为一个相互依存、不可分离的整体--对象。对同类型对象抽象出其共性,形成类。类中的大多数数据,只能用本类的方法进行处理。类通过一个简单的外部接口,与外界...
2. **解析方法**:对应地,创建一个方法接收JSON字符串,返回特定的Java对象。 例如,创建一个名为`JsonUtil`的工具类: ```java public class JsonUtil { public static String toJson(Object object) { Gson ...
1. **通过Intent.putExtra()**:将基本类型、字符串、Parcelable、Serializable等数据类型放入`Intent`的额外数据中,然后在接收端通过`getExtra()`系列方法获取。 ```java // 发送端 Intent intent = new ...
- **交换函数** (`Swap`):用于交换两个变量的值。 ### 4. 代码解析 #### 4.1 输入处理 ```cpp int shuzu[10]; int i; int num = 0; cout ; cin >> i; while (i != 0 && num ) { shuzu[num] = i; cin >> i; num...
例如,如果我们有两个8位的字节和两个32位的整数作为数据,可以这样做: ```python def send_data_packet(x, y): temp = struct.pack(", TITLE1, TITLE2, int(x), int(y)) uart.write(temp) ``` 这里的`表示两个...
以下是一个交换两个值类型变量的泛型方法示例: ```csharp static void Swap(ref T a, ref T b) { T temp = a; a = b; b = temp; } // 使用示例 Swap<int>(ref m, ref n); ``` 上述代码在调用时,T会被...
2. **类型转换与变量声明**:在Java中,两个字节类型(byte)相加会自动提升为整型(int),因此在赋值给另一个字节变量时会导致编译错误,需要显式转换。 3. **Web Service与数据传输**:Web Service通常使用XML(可...
这个方法返回一个`System.Type`对象,该对象包含了关于对象的数据类型的所有信息。在示例代码中: ```csharp int i = 5; Console.WriteLine("i is an int? {0}", i.GetType() == typeof(int)); ``` 这里,`i....
C语言是一种静态类型的编程语言,支持多种基本数据类型,包括整型(int、short、long等)、浮点型(float、double)、字符型(char)等。这些数据类型支持各种算术运算、逻辑运算和位运算等。 #### 二、知识点详细解析 *...
- **思想**: 重复地遍历待排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。 - **时间复杂度**: O(n^2),其中n是...
`swap`方法用于交换数组中的两个元素。 ```java public static void swap(int i, int j) { int temp = a[i]; a[i] = a[j]; a[j] = temp; } ``` 4. **主函数**: 在`main`方法中,首先创建了一个`...