JAVA和C中的值传递

JAVA和C中有且只有值传递,而C++在是C超集的基础上拥有引用传递和值传递。

public class Number(){
int num;
}

Number a = new Number();

Number b = new Number();



我们先来创建一个Number类,其中有成员num;Number a此时声明了a的类型,但还未给a分配空间,直到new Number()时,才真正分配了空间。

而此时即代表,将一块新的对象的引用地址赋予a,此后a便能通过该引用地址来对该对象进行操作可以理解为真正的对象是匿名的,我们只不过是创建了一个对该对象的一个实名(a)的引用来操作该对象,而在每次new Number()时,实际上都是在创建一个新的对象(其地址不同,只有属性相同),我们可以假设第一条的new Number()地址为0x123456 ,第二条为0x78910,那么此时a的值为0x123456,b的值为0x78910,皆通过这条引用地址来达成对匿名对象的各种操作,为了方便说明两个对象并非同一,我们将第一条先表达为为new Number1(),第二条 new Number2();

public class Number(){
int num;
}

Number a = new Number();

Number b = new Number();

b=a;

此时我们将b=a;将a的值赋予b,会发生什么?a的值将被传给b,此时a=0x123456,b也等于0x123456了,b的引用地址也指向了new Number1();此时b的一切操作也将改变new Number1(),而new Number2()因为没人引用其地址,被放入了垃圾回收。

基础讲解完了,来看为何JAVA和C中有且只有值传递;

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

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/qq_41854911/article/details/122149948

ps:感谢小熊coder大佬的例子

可以看见图中还是有两个new user(),第一个我们设为new User1(),第二个new User2()

,第一个我们假设hollis此时获得的new User1()的引用地址是0x123456 ,而下面的hollis.setName也能通过引用地址来对new User1()对象进行修改。而值传递的要点在于只是传递一个没有任何意义的值。此时pt.pass(hollis),意思即为将hollis的值复制了一份传入函数,实际上传入的是pt.pass(0x123456),那么进到函数后此时user的值为0x123456,但在函数中的第一步,user被赋予了一个新的对下new User2() (0x78910),每个new都是创建一个新对象指向一个新的引用地址,因此user的值被改变为0x78910,那么以后的操作自然无法再影响到先前的hollis指向的new User1()对象了。输出结果为

print in pass , user is User{name='hollischuang', gender='Male'}
print in main , user is User{name='Hollis', gender='Male'}

hollis指向的new User1()并未被改变,改变的只是new User2();

再来看c语言

void modify(int *x)
{
    // 将x的值改为200
    *x = 200;
    x = (int *)0;
}
int main(void)
{
    int a=0;
    int *p = &a;
    modify(p);  
    printf("%d\n", a);  // 此时a是200
    printf("%p\n", p);  // 此时p的值仍然是变量a的地址
    return 0;
}

我们假设p获得的地址&a为0x123456,地址p拷贝一份传入函数modify,此时x=0x123456,而通过*对地址解引用,a的值由0改为了200,第二句x=(int *)0试图将p的地址改为0,但这没有意义,因为p的值只是拷贝了一份进来而已,这个地址只是一个能解引用到a的地址,但绝不代表0x123456就等于a,直接修改函数中x=0x123456为x=0,只能改变x的地址而不能通过传递改变到外部a的地址,a的地址就是a的地址,函数中的只不过是拷贝的一份值,java中也是如此,只不过java对引用地址没有c语言中*解引用的操作,但java中的引用地址和c一样,都绝不代表等于。引用地址就像钥匙,能打开通往房子,但钥匙不等于房子。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值