c++ main如何引用class_【Java基础—数据类型】什么是值传递和引用传递

​什么是值传递,什么是引用传递呢?在深入了解这个问题之前,我们先通过一段代码来看看:

public class Main {
    public static void main(String[] args) {
        int c = 2; //c 叫做实参
        User user = new User(); //user叫做实参
        user.setName("nick");
        user.setAge(2);
​
        pass(user, c);
        System.out.println("c的值是:" + c );
        System.out.println("name的值是:" + user.getName());
}
​
       public static void pass(User user, int c) {
        c = 3;
        user.setName("pass");
       }
}
​
class User {
    String name;
    int age;
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    @Override
    public String toString() {
        return "name = " + name + " --- age = " + age;
    }
}

代码运行结果:

c的值是:2
​name​的值是:pass

你会发现,为什么c的值保持不变,而d的值却变了呢?这就是值传递和引用传递区别导致的。在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数,这个过程叫值传递。在调用函数时将实际参数的地址直接传递到函数中的形参,那么在函数中对参数所进行的修改,将影响到实际参数,这个过程叫做引用传递。

那为什么值传递后,原来的值不变,而引用传递却变了呢?我们再来复习下基本类型和引用类型的值是如何存储的,int c = 66由于是基本类型,值将会直接存储在栈内存中,而user由于是基本类型,实际值存储在堆内存中,user引用存储在栈内存中,并且指向实际值地址。

7cfce50df054f5f38edb8fc47122bdb3.png

main() 方法中的 user 引用,与 pass() 方法中的 user 引用,指向的是同一个堆内存中的 user对象,红色虚线是在 main() 方法中初次给 name 属性赋的值"main"。实线部分,是在 pass() 方法中给 name 属性赋的值"pass"。因为在堆内存中只有一个 User 类实体,因此 main() 方法与 pass() 方法中的 user 指向的都是同一个 User 类 0x000031。因此,无论在 main() 方法还是 pass() 方法中,改变其 user 的属性值后,打印 User 类的属性值肯定是一样的,他们用的是一个实体类。而可以看到基本类型d在栈内存中,分别有两个,一个是main方法的d=66,一个是pass方法的d=0,在pass方法赋值时,是赋值给了d=0这个值类型,所以原先的d=66这个值类型依然保持不变。

对以上内容理解清楚后,我们再来看一个例子:

public class StringBase {
    public static void main(String[] args) {
        int c = 2; //c 叫做实参
        String b = "hello"; // b 叫做实参
​
        StringBase stringBase = new StringBase();
        stringBase.change(c, b); // 此处 c 与 b 叫做实参
​
         System.out.println("c的值是:" + c );
         System.out.println("b的值是:" + b);
    }
​
    public void change(int a, String b) { // a 与 b 叫做形参
        a = 3;
        b = "no";
    }
}

运行结果为:

c的值是:2
b的值是: hello

这个时候是不是有点懵了,按照我的理解,String是对象类型,应该属于引用类型了,内部b赋值应该会影响外边才对啊!怎么b的值没有变呢?

String类型在值传递和引用传递问题中比较特殊,为什么说特殊呢,因为对于一些常量字符串的创建,只要判断对象在堆中不存在,便会创建一个新的,如果是创建新对象,那么引用地址都会变。我们可以通过一个简单的例子来解释下:

String a = "hello"; //a 相当于实参
String b= a; //a1 就相当于形参
b = "你好";
System.out.println("a是:" + a + " --- b是:" + b);

运行结果为:

a是:hello --- b是:你好

String a = "hello"; 在 String 池中检查并创建一个常量:"hello",给 a 分配一个栈内存,在此存储常量 hello 的地址。

String b= a; 给 b 分配一个栈内存,在此存储常量 hello 的地址。相当于 a 把自己持有的地址,复制给了 b。

92328d93c48cce7da7cce380aded208f.png

b = "你好"; 在 String 池中检查是否有 "你好" 的常量。如果有,将 b 的地址指向 "你好" 的地址。如果 String 池中没有 "你好" 常量,在堆内存中创建 "你好" 常量,并将 b 地址指向 "你好"。

5e8690bf265bb43de427da8c91f7f47d.png

通过这个例子,我们再来回顾下最开始的这个试题,如果我们将在pass方法中的赋值改成new对象复制,结果又会是什么样呢?

public class Main {
 
    public static void main(String[] args) {
        int c = 2; //c 叫做实参
        String d = "hello"; //d 叫做实参
​
        User user = new User(); //user叫做实参
        user.setName("main");
        user.setAge(2);
 
        System.out.println("c的值是:" + c );
        System.out.println("name的值是:" + user.getName());
      }
    
       public static void pass(User user, int c) {
        c = 3;
        User user1 = new User(); //user叫做实参
        user1.setName("main");
        user1.setAge(2 );
        user = user1;
       }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值