深入浅出Java中参数传递的原理

这篇具有很好参考价值的文章主要介绍了深入浅出Java中参数传递的原理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

今天,想和大家聊聊关于java中的参数传递的原理,参数的传递有两种,值传递和引用传递。

  • 值传递:是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

  • 引用传递:是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

基本类型传递

先来看看下面这段最基本的代码:

@Test
public void test() {
    int n = 10;
    test01(n);
    System.out.println("最终结果n==" + n);
}

private void test01(int m) {
    System.out.println("修改之前m==" + m);
    m = 20;
    System.out.println("修改之后m==" + m);
}

输出结果:

修改之前m==10
修改之后m==20
最终结果n==10

如果跟你预期的不同,那我想你还是没有理解参数的值传递与引用传递的原理。

结合生活中的场景,深入理解一下值传递和引用传递:

你有一把钥匙,当你的朋友想要去你家的时候,如果你直接把你的钥匙给他了,这就是引用传递。这种情况下,如果他对这把钥匙做了什么事情,比如他在钥匙上刻下了自己名字,那么这把钥匙还给你的时候,你自己的钥匙上也会多出他刻的名字。

你有一把钥匙,当你的朋友想要去你家的时候,你复刻了一把新钥匙给他,自己的还在自己手里,这就是值传递。这种情况下,他对这把钥匙做什么都不会影响你手里的这把钥匙。

下面我们来画图更好的理解上述代码的例子:

深入浅出Java中参数传递的原理

当发生函数调用的时候 n 将自己传入到 test01 方法中,同时将自己的值复制了一份并赋值给了一个新变量 m 从图中可以看出这是 nm 两个变量没有一毛钱关系(m只是n的复制品),所以对 m 的修改并不会影响到 n

如果想要改变n的值,可以使用方法的返回值:

n = test01(n);

引用类型传递

下面来看看引用类型的传递:

public class Dog {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Dog(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                '}';
    }
}


@Test
public void test() {
    Dog dog1 = new Dog("小白");
    test01(dog1);
    System.out.println("最终结果dog==" + dog1);
}

private void test01(Dog dog) {
    System.out.println("修改之前 dog==" + dog);
    dog.setName("小黑");
    System.out.println("修改之后 dog==" + dog);
}

输出结果:

修改之前 dog==Dog{name='小白'}
修改之后 dog==Dog{name='小黑'}
最终结果dog1==Dog{name='小黑'}

为了方便大家理解,还是画图来分析一下:

深入浅出Java中参数传递的原理

test 方法中我们创建了一个 dog1 的对象,该对象存放于堆内存中,假设内存地址为 0x1120 ,于是 dog1 这个变量便应用了这块内存地址。

当我们调用 test01 这个方法的时候会在该方法栈中创建一个变量 dog ,这个 dog 变量是由原本的入参 dog1 复制而来,所以它所对应的堆内存依然是 0x1120

所以当我们通过 dog 这个变量修改了数据后,本质上修改的是同一块堆内存中的数据。从而原本引用了这块内存地址的 dog1 也能查看到对应的变化。

如果不理解上面的话,那么记住下面的两句话就行了:

传递引用类型的数据时,传递的并不是引用本身,依然是值;只是这个值是内存地址罢了。

因为把相同的内存地址传过去了,所以对数据的操作依然会影响到外部。

那我们继续看看下面的代码,这种情况能否改变参数的值

@Test
public void test() {
    Dog dog1 = new Dog("小白");
    test01(dog1);
    System.out.println("最终结果dog1==" + dog1);
}

private void test01(Dog dog) {
    System.out.println("修改之前 dog==" + dog);
    dog = new Dog("小黑");
    System.out.println("修改之后 dog==" + dog);
}

输出结果:

修改之前 dog==Dog{name='小白'}
修改之后 dog==Dog{name='小黑'}
最终结果dog1==Dog{name='小白'}

假设 Java 是引用传递那最终的结果应该是打印 小黑 才对,从结果看这里依然是值传递。

还是画图来分析一下:

深入浅出Java中参数传递的原理

如果是引用传递,原本的 0x1120 应该是被直接替换为新创建的 0x1121 才对;而实际情况如上图所示,dog 直接重新引用了一个对象dog = new Dog("小黑"),两个对象之间互不干扰。

总结

Java中参数传递其实还是值传递的,只不过对于引用类型参数,值的内容是对象的引用。文章来源地址https://www.toymoban.com/news/detail-427905.html

到了这里,关于深入浅出Java中参数传递的原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【朴素贝叶斯】深入浅出讲解朴素贝叶斯算法(公式、原理)

    本文收录于《深入浅出讲解自然语言处理》专栏,此专栏聚焦于自然语言处理领域的各大经典算法,将持续更新,欢迎大家订阅! ​个人主页:有梦想的程序星空 ​个人介绍:小编是人工智能领域硕士,全栈工程师,深耕Flask后端开发、数据挖掘、NLP、Android开发、自动化等

    2024年02月03日
    浏览(40)
  • 【深入浅出Spring Security(三)】默认登录认证的实现原理

    由默认的 SecurityFilterChain 为例(即表单登录),向服务器请求 /hello 资源Spring Security 的流程分析如下: 请求 /hello 接口,在引入 Spring Security 之后会先经过一系列过滤器(一中请求的是 /test 接口); 在请求到达 FilterSecurityInterceptor 时,发现请求并未认证。请求被拦截下来,并

    2024年02月09日
    浏览(32)
  • 深入浅出Nginx的基本原理和配置指南「负载均衡篇」

    6.1 四层负载均衡 6.1.1 四层负载均衡与七层负载均衡的区别 四层负载均衡数据包是在底层就进行了分发,而七层负载均衡数据包则在最顶端进行分发,所以四层负载均衡的效率比七层负载均衡的要高。四层负载均衡不识别域名,而七层负载均衡识别域名。 6.1.2 四层负载均衡配

    2024年02月09日
    浏览(40)
  • 【C++深入浅出】初识C++上篇(关键字,命名空间,输入输出,缺省参数,函数重载)

         目录 一. 前言 二. 什么是C++ 三. C++初探 四. 命名空间 4.1 为什么要引入命名空间 4.2 命名空间的定义 4.3 命名空间使用 五. C++的输入输出 六. 缺省参数 6.1 缺省参数的概念 6.2 缺省参数的分类 七. 函数重载  7.1 函数重载的概念 7.2 函数重载的条件 7.3 C++支持函数重载

    2024年02月13日
    浏览(42)
  • 《深入浅出SSD:固态存储核心技术、原理与实战》----学习记录(二)

    SSD主要由两大模块构成—— 主控和闪存介质 。其实除了上述两大模块外,可选的还有缓存单元。主控是SSD的大脑,承担着指挥、运算和协调的作用,具体表现在 一是实现标准主机接口与主机通信 二是实现与闪存的通信 三是运行SSD内部FTL算法 可以说,一款主控芯片的好坏直

    2024年02月12日
    浏览(43)
  • 深入浅出讲解Stable Diffusion原理,新手也能看明白

    最近一段时间对多模态很感兴趣,尤其是Stable Diffusion,安装了环境,圆了自己艺术家的梦想。看了这方面的一些论文,也给人讲过一些这方面的原理,写了一些文章,具体可以参考我的文章: 北方的郎:图文匹配:Clip模型介绍 北方的郎:VQGAN(Vector Quantized Generative Adversar

    2024年02月08日
    浏览(36)
  • 深入浅出阿里数据同步神器:Canal原理+配置+实战全网最全解析!

    canal 翻译为管道,主要用途是基于 MySQL 数据库的增量日志 Binlog 解析,提供增量数据订阅和消费。 早期阿里巴巴因为杭州和美国双机房部署,存在跨机房同步的业务需求,实现方式主要是基于业务 trigger 获取增量变更。从 2010 年开始,业务逐步尝试数据库日志解析获取增量变

    2024年02月10日
    浏览(31)
  • 【深入浅出 Spring Security(七)】RememberMe的实现原理详讲

    先看看最简单用法的默认页面效果变化。 SecurityConfig 配置类 测试 TestController 代码 以下是给出的默认的登录页面。 观察页面源代码可以发现,比原先没配置 RememberMe 之前多了个 name 为 remember-me 的 checkbox 选项。 如果我们勾选了它并且登录成功后,当我们关闭掉当前浏览器,

    2024年02月09日
    浏览(32)
  • 【大虾送书第七期】深入浅出SSD:固态存储核心技术、原理与实战

    目录  ✨写在前面   ✨内容简介  ✨作者简介  ✨名人推荐  ✨文末福利      🦐博客主页:大虾好吃吗的博客      🦐专栏地址:免费送书活动专栏地址         近年来国家大力支持半导体行业,鼓励自主创新,中国SSD技术和产业良性发展,产业链在不断完善,与

    2024年02月10日
    浏览(45)
  • 【前端工程化】深入浅出vite(一)--vite的优点及原理、性能优化

    Vite 需要 Node.js 版本 14.18+,16+。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。 webpack 支持多种模块化,将不同模块的依赖关系构建成依赖图来进行统一处理,当构建的项目越来越大时,需要处理的 JS 代码也越

    2024年02月11日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包