java的值传递和引用传递

值传递:在方法被调用时,实参通过形参把它的内容副本传入方法内部,此时形参接收到的内容是实参值的一个拷贝,因此在方法内对形参的任何操作,都仅仅是对这个副本的操作,不影响原始值的内容
引用传递:就是指向真实内容的地址值,在方法调用时,实参的地址通过方法调用被传递给相应的形参,在方法体内,形参和实参指向同一块内存地址,对形参的操作会影响的真实内容

对于基本数据类型是值传递,对于引用数据类型是引用传递。
在基本数据类型中,变量和值都存储在栈中,用一个方法修改变量时,只是修改了变量的副本,而变量本身没有被改变。

引用数据类型中,变量存在栈中,值存在堆中,变量通过指针指向值。用一个方法修改变量时,形参和实参的地址是相同的。所以改变形参的内容,实参也被改变。

当然也可以说java就是值传递,只不过对于引用数据类型来说,复制的是地址值。

例题一

public static void main(String[] args) {
        Numtransport numtransport = new Numtransport();
        int i = 10;
        numtransport.fermin(i);
        System.out.println(i);
    }
    void fermin(int i){
        i++;
    }

输出:

10

因为基本数据类型是值传递的,方法体的变量存储的是副本,无法影响到main方法的i值。所以输出是10

例题二:

public static void main(String[] args) {
        Referencetransport referencetransport = new Referencetransport();
        User hollis = new User();
        hollis.setName("Hollis");
        hollis.setGender("Male");
        referencetransport.pass(hollis);
        System.out.println("print in main , user is " +hollis.getName()+ ","+hollis.getGender());
    }

    public void pass(User user) {
        user.setName("hollischuang");
        System.out.println("print in pass , user is " +user.getName()+","+ user.getGender());
    }

输出:

print in pass , user is hollischuang,Male
print in main , user is hollischuang,Male

对于引用数据类型user,传递的是地址值。所以name属性被改变。

例题三:

public static void main(String[] args) {
        Referencetransport referencetransport = new Referencetransport();
        User hollis = new User();
        hollis.setName("Hollis");
        hollis.setGender("Male");
        referencetransport.pass(hollis);
        System.out.println("print in main , user is " +hollis.getName()+ ","+hollis.getGender());
    }

    public void pass(User user) {
        user = new User();
        user.setName("hollischuang");
        user.setGender("Male");
        System.out.println("print in pass , user is " +user.getName()+","+ user.getGender());
    }

输出:

print in pass , user is hollischuang,Male
print in main , user is Hollis,Male

因为方法pass中新建了一个变量。这使得原变量没有改变。pass中输出的是新建变量user的属性值。
需要特别注意String类型。这是一个引用类型,却在很多方面上体现出值传递的特征。

例题四:

public static void main(String[] args) {
        Stringtransport pt = new Stringtransport();

        String name = "Hollis";
        pt.pass(name);
        System.out.println("print in main , name is " + name);
    }

    public void pass(String name) {
        name = "hollischuang";
        System.out.println("print in pass , name is " + name);
    }

输出:

print in pass , name is hollischuang
print in main , name is Hollis

显然在方法pass中,name指向了字符串“hollischuang”,但是主方法的name却并没有发生改变。这是因为String是final类型的。

终极一题:

class Value{
    public int i=15;
}
public class Test{
    public static void main(String argv[]){
        Test t=new Test( );
        t.first( );
    }
 
public void first( ){
    int i=5;
    Value v=new Value( );
    v.i=25;
    second(v,i);
    System.out.println(v.i);
}
 
public void second(Value v,int i){
    i = 0;
    v.i = 20;
    Value val = new Value( );
    v = val;
    System.out.println(v.i+" "+i);
   }
}

这道题的输出结果会是什么?
答案是15 0 20
首先,要分清楚属性和与属性重名的局部变量。v.i输出属性值,i输出局部变量值。其次,在second方法中,新定义了一个val变量,并将val赋给second中的变量v,此时v和val的属性值i同为初始值15。而second中的局部变量 i 为0。second结束后,返回继续执行first方法。因为v.i在second中被修改为20,所以此时输出20。为什么不是15呢?因为15是v指向second方法中new Value()这个对象的属性值。而first方法中的v对象的属性值是被修改成了20

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值