A Coder

Coding My Dream!

0%

java 参数传递探究

对于java的传参有些了解,今天正好在重温C语言的传值和传址,顺便一起研究下java

##基本数据类型##
对于基本数据类型,如 int long bool 等 是值传递,传递时将值复制一份给形参,如下:

package com.loftor;

public class Argument {
public static void main(String[] args) {
int value = 1;
change(value);
System.out.print(value); //输出结果为1
}

public static void change(int value){
value=2;
}
}


##引用类型##

对于引用类型如 User 等 传递的是引用,传递是将对象的地址复制给形参 如下

package com.loftor;

class User{
    public String name;
}

public class Argument {

    public static void main(String[] args) {
        User user = new User();
        user.name="小明";
        change(user);
        System.out.print(user.name); //输出小红
    }

    public static void change(User user){
        user.name="小红";
    }
}

调试时可以看到如下的结果
java参数传递1.jpg
@后面跟的参数可以理解为地址,在为进入change方法前的值为454
java参数传递2.jpg
进入change后的值依然为454,说明这两个是同一个对象,传参时只是将对象的地址复制给了方法的形参。

##小结##

基本类型在传递时传递的是参数的值,引用类型(如类)传递的是对象的地址。

##特殊但又不特殊的情况##

但是有一个例外,那就是String,Long等简单的Object,在Java中,String是一个引用类型,但是在作为参数传递的时候表现出来的却是基本类型的特性,即在方法中改变了String类型的变量的值后,不会影响方法外的String变量的值。

这个情况我们还是用修改了一下代码做说明

package com.loftor;

public class Argument {


    public static void main(String[] args) {
        String value = "小明";
        change(value);
        System.out.print(value);
    }

    public static void change(String value){
        String str="小红";
        value=str;
    }
}

在未进入change方法前,value 的指向的地址为 453
java参数传递3.jpg
进入方法后 形参 value 的指向的地址依然为 453 说明形参复制了实参的地址
java参数传递4.jpg
其中str变量的指向的地址为 454
java参数传递5.jpg
value=str;这行很关键,出现以上错觉的原因就是String的赋值,java里赋值的做法是将地址赋值给变量,因为value指向的地址453,现在将它赋值后,指向的地址将变成str的地址454,只是指向的地址进行了改变,对于地址453上存的值便没有发生改变,change方法的形参在change生命周期结束后便回收了,而在方法change外面的value的指向地址便没有发生改变还是指向453,所以value的值不会改变。

类似C中的两个指针,一个是change外面的value,一个是change里面的value,一开始他们指向同一个地址453,后来change里面的value指向了454,便没有对453上面存储的值进行改变,所以外面的value的值不会发生改变。

##结论##
java中常量存储在常量池中。这些常量的地址和值是固定的,只会增加,不会对现有地址上的值做出修改。同一个值对应的地址是一样的。

java参数传递6.jpg
以上图片可以看到str1和str2的地址是一样的

基本类型的值都是常量,看起来是传值,但是实际上传的是还是这个常量的地址,而基础类型变量可以理解为一个指针,指向的都是常量的地址,根据上面的规则,要想改变一个基础类型的变量的值,只能通过更改变量指向的地址。所以只要基础类型变量的地址没有改变,那么他们指向的地址就不会改变,这也就是为什么基础类型看起来像是是传值。