zoukankan      html  css  js  c++  java
  • Java参数传递问题

    一个数组参数抛出的问题

    当时的情况是这样的:
        public static void test(Integer[] x){
            x[1] = 99;
        } 
        
        public static void main(String[] args) {
            
            Integer[] temp1 =  new Integer[] {3, 4};
            test(temp1);// 1
            Integer[] temp2 = {5, 6};
            test(temp2);// 2
        }

    1temp1被改变,2temp2没有改变。几个月没写代码,一下子我很疑惑(前几天连数组的定义都忘记了...),于是就到网上各种baidu,google,然后就有了下面的故事:

    class People{
        int eyes = 2;
    }
    
    public class JustDoIt0801 {
    
        public static void main(String[] args) {
    
            // 基本类型
            int i = 9;
            changeInt(i);
            System.out.println(i);
            
            // 引用类型
            People p = new People();
            changePeople(p);
            System.out.println(p.eyes);
            
        }
        private static void changeInt(int x){
            x = x + 9;
        }
        
        private static void changePeople(People x){
            x.eyes = x.eyes + 1;
        }
    }

    以参数形式传递基本类型的变量时,实际上是将参数的值作了一个拷贝传进方法函数的,那么在方法函数里再怎么改变其值,其结果都是只改变了拷贝的值,对原来的数据没有影响!

    那么引用数据类型传递的时候,是传递了这个实例的一个引用,基地址,这个地址在方法中被改变了指向,而我们程序是不管真实实例的情况的,只管这个引用指向的内容,从而改变了数据。

    那么第一个数组又怎么解释呢?

    第一种 new Integer[]{} 是放在堆区的,而temp1是在栈区的,两者通过引用相互连接
    第二种  直接在栈区的

    然后就出现了一个传说经典的问题:传值和传址

    然而我们经常碰见的问题那就是String,总是不走寻常路,当用String 传值的时候不能改变它的原来值(用 new 也不行)。

    网上给出的一个比较好的解释:

    我们来看看new出String对象的那小段代码(String类中),也就是String类的构造函数:

    publicString(String original) {
    
             int size = original.count;
    
             char[] originalValue = original.value;
    
             char[] v;
    
           if (originalValue.length > size) {
    
                 // The array representing the String is bigger than the new
    
                 // String itself. Perhaps this constructor is being called
    
                 // in order to trim the baggage, so make a copy of the array.
    
                  int off = original.offset;
    
                  v = Arrays.copyOfRange(originalValue, off, off+size);
    
             } else {
    
                 // The array representing the String is the same
    
                 // size as the String, so no point in making a copy.
    
                 v = originalValue;
    
             }
    
             this.offset = 0;
    
             this.count = size;
    
             this.value = v;
    
    }

      也 许你注意到了里面的char[],这说明对String的存储实际上通过char[]来实现的。怎么样?其实就是一层窗户纸。不知道大家还记不记得在 Java API中定义的那些基本类型的包装类。比如Integer是int包装类、Float是float的包装类等等。对这些包装类的值操作实际上都 是通过对其对应的基本类型操作而实现的。是不是有所感悟了?对,String就相当于是char[]的包装类。包装类的特质之一就是在对其值进行操作时会 体现出其对应的基本类型的性质。在参数传递时,包装类就是如此体现的。所以,对于String在这种情况下的展现结果的解释就自然而然得出了。同样 的,Integer、Float等这些包装类和String在这种情况下的表现是相同的,具体的分析在这里就省略了,有兴趣的朋友可以自己做做试验。

    不错的解释,看来基础真的很重要。

     

    必要知识搜集:
    java数据类型图: ┏数值型━┳━整数型:byte short int long ┏基本数据类型━━┫ ┗━浮点型:float double ┃ ┣字符型:char     数据类型╋ ┗布尔型:boolean ┃ ┏类(class) ┗引用数据类型━━╋接口(interface) ┗数组(array)

    传值还是传引用:
    最后得出的结论是:
    
    在Java中,当基本类型作为参数传入方法时,无论该参数在方法内怎样被改变,外部的变量原型总是不变的,代码类似上面的示例:
    
    int number = 0;
    
    changeNumber(number) {number++}; //改变送进的int变量
    
    System.out.println(number); //这时number依然为0
    
    这就叫做“值传递”,即方法操作的是参数变量(也就是原型变量的一个值的拷贝)改变的也只是原型变量的一个拷贝而已,而非变量本身。所以变量原型并不会随之改变。
    
    但当方法传入的参数为非基本类型时(也就是说是一个对象类型的变量),方法改变参数变量的同时变量原型也会随之改变,代码同样类似上面的示例:
    
    StringBuffer strBuf = new StringBuffer(“original”);
    
    changeStringBuffer(strBuf) {strbuf.apend(“ is changed!”)} //改变送进的StringBuffer变量
    
    System.out.println(strBuf); //这时strBuf的值就变为了original is changed! 
    
    这
     
    种特性就叫做“引用传递”,也叫做传址,即方法操作参数变量时是拷贝了变量的引用,而后通过引用找到变量(在这里是对象)的真正地址,并对其进行操作。当
     
    该方法结束后,方法内部的那个参数变量随之消失。但是要知道这个变量只是对象的一个引用而已,它只是指向了对象所在的真实地址,而非对象本身,所以它的消
     
    失并不会带来什么负面影响。回头来看原型变量,原型变量本质上也是那个对象的一个引用(和参数变量是一样一样的),当初对参数变量所指对象的改变就根本就
     是对原型变量所指对象的改变。所以原型变量所代表的对象就这样被改变了,而且这种改变被保存了下来。
    

     以上来自网上共享的知识!

  • 相关阅读:
    Android之rild进程启动源码分析
    ListView使用详解,listActivity使用方法
    打开其他android应用代码
    Android剖析和运行机制
    自定义Dialog(图片,文字说明,单选按钮)----类ListPreference实现(2)
    Internet采用哪种网络协议?该协议的主要层次结构?Internet物理地址和IP地址转换采用什么协议?
    引用与指针有什么区别?
    在C/C++中static有什么用途?
    软件验收测试包括
    自底向上集成
  • 原文地址:https://www.cnblogs.com/killbug/p/2619209.html
Copyright © 2011-2022 走看看