首页 > 编程语言 >Java到底是值传递还是引用传递?

Java到底是值传递还是引用传递?

时间:2023-04-12 14:33:27浏览次数:38  
标签:Java update 传递 引用 实参 main 方法 user

1. 什么是形参和实参

形参: 就是形式参数,用于定义方法的时候使用的参数,是用来接收调用者传递的参数的。

实参: 就是实际参数,用于调用时传递给方法的参数。实参在传递给别的方法之前是要被预先赋值的。

/**
 * @author 一灯
 * @apiNote Java传递示例
 **/
public class Demo {

    public static void main(String[] args) {
        String name = "一灯"; // 这里的name就是实际参数
        update(name);
        System.out.println(name);
    }

    // 这里方法参数列表中name就是形式参数
    private static void update(String name) {
        // doSomething
    }

}

在Java方法调用的过程中,就是把实参传递给形参,形参的作用域在方法内部。

2. 什么是值传递和引用传递

值传递: 是指在调用方法时,将实际参数拷贝一份传递给方法,这样在方法中修改形式参数时,不会影响到实际参数。

引用传递: 也叫地址传递,是指在调用方法时,将实际参数的地址传递给方法,这样在方法中对形式参数的修改,将影响到实际参数。
也就是说值传递,传递的是副本。引用传递,传递的是实际内存地址。这是两者的本质区别,下面会用到。

3. 测试验证

3.1 基本数据类型验证

先用基本数据类型验证一下:

/**
 * @author 一灯架构
 * @apiNote Java传递示例
 **/
public class Demo {

    public static void main(String[] args) {
        int count = 0;
        update(count);
        System.out.println("main方法中count:" + count);
    }

    private static void update(int count) {
        count++;
        System.out.println("update方法中count:" + count);
    }

}

输出结果:

update方法中count:1
main方法中count:0

可以看到虽然update方法修改了形参count的值,但是main方法中实参count的值并没有变,但是为什么没有变?我们深究一下底层原理。

我们都知道Java基本数据类型是存储在虚拟机栈内存中,栈中存放着栈帧,方法调用的过程,就是栈帧在栈中入栈、出栈的过程。

当执行main方法的时候,就往虚拟机栈中压入一个栈帧,栈帧中存储的局部变量信息是count=0。

 

 当执行update方法的时候,再往虚拟机栈中压入一个栈帧,栈帧中存储的局部变量信息是count=0。

 

 

修改update栈帧中数据,显然不会影响到main方法栈帧的数据。

3.2 引用类型验证

再用引用类型数据验证一下:

/**
 * @author 一灯架构
 * @apiNote Java传递示例
 **/
public class Demo {

    public static void main(String[] args) {
        User user = new User();
        user.setId(0);
        update(user);
        System.out.println("main方法中user:" + user);
    }

    private static void update(User user) {
        user = new User();
        user.setId(1);
        System.out.println("update方法中user:" + user);
    }

}

输出结果:

update方法中user:User(id=1)
main方法中user:User(id=0)

由代码得知,update方法中重新初始化了user对象,并重新赋值,并不影响main方法中实参数据。

当执行main方法时,会在堆内存中开辟一块内存,在栈内存中压入一个栈帧,栈帧中存储一个引用,指向堆内存中的地址。

 

当调用update方法时,会把main方法的栈帧拷贝一份,再压入栈内存中,指向同一个堆内存地址。

 

 当执行update方法,重新初始化user对象,并重新赋值的时候。会在堆内存中再开辟一块内存,再把栈内存中update栈帧指向新的堆内存地址,并修改新的堆内存中的数据。

 

 从这里可以看出是值传递,修改了形参里面数据,实参并没有跟着变化。

3.3 同一地址的引用类型验证

/**
 * @author 一灯架构
 * @apiNote Java传递示例
 **/
public class Demo {

    public static void main(String[] args) {
        User user = new User();
        user.setId(0);
        update(user);
        System.out.println("main方法中user:" + user);
    }

    private static void update(User user) {
        user.setId(1);
        System.out.println("update方法中user:" + user);
    }

}

输出结果:

update方法中user:User(id=1)
main方法中user:User(id=1)

可以看出update方法修改user对象的属性,main方法中user对象也跟着变了。

 

这是不是说明Java支持引用传递呢?
并不是。这里在参数传递的过程中,只是把实参的地址拷贝了一份传递给形参,update方法中只修改了参数地址里面的内容,并没有对形参本身进行修改。

4. 总结

经过上述分析,Java参数传递中,不管传递的是基本数据类型还是引用类型,都是值传递。

当传递基本数据类型,比如原始类型(int、long、char等)、包装类型(Integer、Long、String等),实参和形参都是存储在不同的栈帧内,修改形参的栈帧数据,不会影响实参的数据。

当传参的引用类型,形参和实参指向同一个地址的时候,修改形参地址的内容,会影响到实参。当形参和实参指向不同的地址的时候,修改形参地址的内容,并不会影响到实参。

 举例,引用传递中,修改实参的地址时,应该将新地址传递给形参,实际上并没有传递,所以java中没有引用传递。

标签:Java,update,传递,引用,实参,main,方法,user
From: https://www.cnblogs.com/kisshappyboy/p/17309704.html

相关文章

  • java 逗号拼接字符串
    逗号拼接字符串可以使用String类的静态方法join()来实现这个功能,示例代码如下:```javapublicclassPhoneNumbers{publicstaticvoidmain(String[]args){StringphoneNumber1="18801083588";StringphoneNumber2="15709106355";Stri......
  • 【JAVA】四则运算计算题生成及完成情况分析程序
    第七周结对编程任务为给出一个300道四则运算计算题并能够完成和检查答案是否正确,我(2152113)邀请到了我计科专业的舍友(2152123)与我一同组队,编程语言选择了我们都较为熟悉的JAVA。代码初现先由我来进行了计算题生产器的代码编写代码如下importjava.util.Random;publicclass......
  • Java中ThreadLocal的用法和原理
    用法隔离各个线程间的数据避免线程内每个方法都进行传参,线程内的所有方法都可以直接获取到ThreadLocal中管理的对象。packagecom.example.test1.service;importorg.springframework.scheduling.annotation.Async;importorg.springframework.stereotype.Component;imp......
  • Java:使用hutool工具类UrlBuilder、urlQuery构建url查询参数
    依赖<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.4.6</version></dependency>url查询参数构建packagecom.example;importcn.hutool.core.net.url.UrlQuery;im......
  • java事件处理机制
     事件源可以是一个键可以是一个鼠标可以是一个按钮.....发生了就是事件源事件就是事件的对象,当事件源发生了就会有事件对象(事件对象就会传递给事件监听者)事件监听者接受刀事件对象了之后会进行事件处理方法   ......
  • java项目 学生成绩管理系统 (源码+数据库文件)
    ​ 需要的私信我备注来意:项目名称来了就点个赞再走呗,即将毕业的兄弟有福了文章底部获取源码java项目  学生成绩管理(源码+数据库文件)技术框架:java+springboot+vue+mysql后端框系统共分为三种用户系统主要功能:系统设计三个角色,学生端,教师端,系统管理员端一、系统运行......
  • java判断字符串是否包含汉字工具类
       /***判断字符串中是否包含中文**@paramstr待校验字符串*@return是否为中文*@warn不能校验是否为中文标点符号*/publicstaticbooleanisContainsChinese(Stringstr){if(str==null){returnfalse;}P......
  • JavaScript Window.Location - 获取当前页面地址(URL)并重定向到新页面。
    JavaScriptWindow.Location-获取当前页面地址(URL)并重定向到新页面。1、常用:window.location.href//返回当前页面的href(URL)window.location.host//或window.location.hostname//返回web主机的域名或IP地址,window.location.pathname//返回当前页面的路径或......
  • RUST——借用与引用
    引用与借用引用可以保证一个对象的引用作为参数而不是所有权fnmain(){lets1=String::from("hello");letlen=cal_len(&s1);println!("Thelengthof{}is{}",s1,len);}fncal_len(s:&String)->usize{//s.push_str(",world");无法通过......
  • java怎么样判断一个进程是否已近结束
    以记事本程序为例Processp=Runtime.getRuntime().exec("notepad.exe");try{p.waitFor();//等待notepad.exe的结束}catch(InterruptedExceptionex){System.err.println("ERROR");System.exit(1);}//继续自己的程序参见http://zhidao.baidu.com/qu......