Integer 函数传参实现值交换

Posted xch-xiaocheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Integer 函数传参实现值交换相关的知识,希望对你有一定的参考价值。

 

import java.lang.reflect.Field;

public class MainClass {
    public static void main(String[] args) {
        Integer a = 128;
        Integer b = -129;
        swarp(a,b);
        System.out.println(a);
        System.out.println(b);
        try {
            System.out.println("________________________________________________");
            swarp1(a,b);
            System.out.println(a);
            System.out.println(b);
            System.out.println("--------------------------------------------------");
            Integer c = 128;
            System.out.println(c);
            Integer d = new Integer(128);
            System.out.println("--------------------------------------------------");
            swarp2(a,d);
            System.out.println(a);
            System.out.println(d);
            
            
            
        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
    public static void  swarp(Integer a, Integer b){
        Integer temp = a;
        a = b;
        b = temp;
    }
    
    public static void swarp1(Integer a, Integer b) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
        Field field = a.getClass().getDeclaredField("value");
        field.setAccessible(true);
        Integer a1 = a;
        field.set(a, b);
        field.set(b, a1);
        field.setAccessible(false);
    }
    public static void swarp2(Integer a, Integer b) {
        Field field;
        try {
            field = a.getClass().getDeclaredField("value");
            field.setAccessible(true);
            int a1 = new Integer(a);
            field.set(a, b);
            field.set(b, a1);
            field.setAccessible(false);
        } catch (NoSuchFieldException | SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

 

 

java 8
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) {
                try {
                    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);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

 

内部类预初始化从-128~127的Integer实例,每个具体实例的下标为i + (-IntegerCache.low),比如-128下标为-128-(-128)=0,再看一下自动装箱的函数valueOf

public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

 


到这里我们上面的类的结果已经很明显
一、将在main函数内,将a,b,c,d 分别赋值为128,-129,128,128
输出结果为:
128
-129
________________________________________________
-129
128
--------------------------------------------------
128
--------------------------------------------------
128
-129
二、将main函数内的a,b,c,d 分别赋值为127,-128,127,127
输出结果为:
127
-128
________________________________________________
-128
-128
--------------------------------------------------
-128
--------------------------------------------------
127
-128
如果读到这里还不知道为什么会有这样的结果,那么请继续看
1、java 的传参都是传值,函数接收到的形参都是指向实例引用的副本,第一个函数(swap)在内部的操作都是对副本的操作,所以不管值是多少,两个值得交换都失败
2、当ab的值在-128~127范围内时,第二个函数内,虽然给a做了备份,但是已经利用反射,将具体的在缓存内相应下标的Integer的value值改变,在b值赋值时,调用valueOf,指向该实例,所以返回的结果是ab值相等;而第三个函数为什么会交换成功呢?因为d是new出来的值,并没有走valueOf自动装箱,是一个在缓存之外的实例
3、当ab值在-128~127范围外时,ab都是new的新实例,固可以交换成功































以上是关于Integer 函数传参实现值交换的主要内容,如果未能解决你的问题,请参考以下文章

浅析Integer类型传参值不变来理解Java值传参

实现用函数交换两个数的值

java基础3-重载+命令行传参+递归+数组+排序

C语言中的值传参和引用传参是指啥?

063-PHP函数按地址传参,交换数值函数

062-PHP函数按值传参,交换数值函数