Java浅解 值传递和引用传递

2024-06-18 21:38
文章标签 java 引用 传递 浅解

本文主要是介绍Java浅解 值传递和引用传递,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在上一篇文章对象中,略微提出了一些值传递和引用传递的概念,感觉需要写出篇简单的理解一下。

首先声明一点,java的传递时值传递,而非引用传递(即指针)。

  • 值传递:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
  • 引用传递:引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。是C语言的一种传递方式。

如何体现是值传递,代码如下:

public class Test{public static void main(String[] args) {int a=10;//静态变量System.out.println(a);updata(a);System.out.println(a);}public static void updata(int a) {a=a+10;System.out.println("updata中a的值   "+a);}}
//输出结果
10
updata中a的值   20
10

可见在updata 中对a进行多了修改,但是没有实际的参数值a进行修改,而a的值只能在方法体内生效,也就是局部变量。

我们这里也就简单的拓展一下局内变量和全局变量。

  • 局部变量:也称内部变量,是指在一个函数内部或复合语句内部定义的变量。

    简单的看,就是在方法体内生效,在之外是不会生效的变量。

  • 成员变量(全局变量):就是在方法体之外的变量。

java 变量取值,会就近原则,就是方法体内部有就不会去外部寻找如何理解:

注意: 此处的的a会全局变量

public class Test{static int a=10;//全局变量public static void main(String[] args) {System.out.println(a);updata(a);System.out.println(a);}public static void updata(int a) {a=a+10;System.out.println("updata中a的值"+a);}}
//输出结果
10
updata中a的值   20
10

这样看程序运行似乎,虽然变成了全局变量,但是具体结果和局部变量没有什么区别。

请看下面代码:

public class Test{static int a=10;public static void main(String[] args) {System.out.println(a);updata();System.out.println(a);}public static void updata() {a=a+10;System.out.println("updata中a的值"+a);}}
//输出结果
10
updata中a的值20
20

看见结果变了,难道就不知值传递了吗?

不,还是值传递,但是在updata 方法中没有形参 int a,所以也就没有所谓参数传递。而其运行规则我们说过,就近原则,所以局部没有,那么就需要找外面的的,而updata 中的a也就是全局变量a。所以此处不是引用传递,而是两个变量作用域不同而结果不同而已。

我们区别了全局变量和局内变量,现在我们回来继续说java中的值传递,想要理解这个,就必须对于java的堆和栈进一步理解。

java内存中分三个区:堆,栈,方法区。

  • 堆:分配的是对象的存储空间,也就是new之后真正数据存在的内存空间。其中可以理解比如new Dog,而dog就会存储在堆当中,而其就是一个大房子,而其毛色 color,公母 sex 等属性就其里面的房间信息。

  • 栈:基本数据类型以及对象的引用的地址

  • 方法区:就是类运行的时候加载类的信息以及static修饰的变量。

    • 加载类的信息:
      1. 这个类型的完整有效名。
      2. 这个类的直接父类的有效名,当然接口和object是除外,两者无父类
      3. 以及类的类型修饰符 public abstract等
    • 方法信息:就是防护的修饰符,以及方法类型,方法的参数和类型等,方法有关信息
    • static修饰的模块,以及修饰的变量

    方法区包含以上,以及其他的域信息,方法表(提高运算是一种数据结构)等

现在有疑问了,不是说java是值传递吗?为什么栈的定义提到了引用。

java的参数传递的时候是值传递,而其java中也没有如同C语言中指针的概念(也就是引用),但是不代表其没有使用指针。

在这里插入图片描述

可以简单理解如上图所示的一个结构。

int num=10;
String str="apple";

因为int是基本数据类型,所以直接存储在栈中,而string是类,所以在栈中存放的是堆的地址。

在这里插入图片描述

看到上面结构,有的就了一个大胆的想法,那就是,如果用string 类型的话,是否在局部修改的时候会影响实际参数呢?不解释,先看代码:

public class Test{public static void main(String[] args) {String a="test";System.out.println(a);updata(a);System.out.println(a);}public static void updata(String a) {a=a+10;System.out.println("updata中a的值"+a);}}
//输出结果
test
updata中a的值test10
test

实参完全没有修改,不是说string是引用吗?为什么改变了而其实参没有改变。

在这里插入图片描述

其实这个就是在传递的时候形参复制了实参引用,但是string,本身尤其自己的特点,以为string 本身在建立后是不可改变的,但是所以虽然是通过+ 号进行了一个字符串添加,但是其意思就是新建了string对象,而其索引也就会变。

而如果需要string类型本身改变,因为大量使用string+会造成资源浪费,而java gc(垃圾回收)机制是jvm自己安排的。而是新建字符串,那就需要其衍生的两个类 StringBuffer和StringBuilder。这两个有append的方法可以在其对象上添加数据。

  1. StringBuilder 适用于单线程,其速度快但是不够安全。
  2. StringBuffer 适用于多线程,其速度慢但安全

现在我们看一下对象使用的引用,同样首先看代码

public class Dog {String name;public String getName() {return name;}public void setName(String name) {this.name = name;}
}public class Test{public static void main(String[] args) {Dog dog = new Dog();dog.setName("旺财")   System.out.println(dog.getName());updata(dog);System.out.println(dog.getName());}public static void updata(Dog dog) {dog.setName("元宝")System.out.println("updata中的值"+dog.getName());}}
//输出的值
旺财
updata中的值元宝
元宝

在这里插入图片描述

同理,也是传递了所在堆的地址,但是其没有新建一个dog对象,等于还是在原有的对象上调用了setName对dog进行赋值,所以本质还是值传递,而是引用一直没有说,但是一直存在。

这篇关于Java浅解 值传递和引用传递的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1073124

相关文章

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注

Java操作Word文档的全面指南

《Java操作Word文档的全面指南》在Java开发中,操作Word文档是常见的业务需求,广泛应用于合同生成、报表输出、通知发布、法律文书生成、病历模板填写等场景,本文将全面介绍Java操作Word文... 目录简介段落页头与页脚页码表格图片批注文本框目录图表简介Word编程最重要的类是org.apach

Spring Boot中WebSocket常用使用方法详解

《SpringBoot中WebSocket常用使用方法详解》本文从WebSocket的基础概念出发,详细介绍了SpringBoot集成WebSocket的步骤,并重点讲解了常用的使用方法,包括简单消... 目录一、WebSocket基础概念1.1 什么是WebSocket1.2 WebSocket与HTTP

SpringBoot+Docker+Graylog 如何让错误自动报警

《SpringBoot+Docker+Graylog如何让错误自动报警》SpringBoot默认使用SLF4J与Logback,支持多日志级别和配置方式,可输出到控制台、文件及远程服务器,集成ELK... 目录01 Spring Boot 默认日志框架解析02 Spring Boot 日志级别详解03 Sp

java中反射Reflection的4个作用详解

《java中反射Reflection的4个作用详解》反射Reflection是Java等编程语言中的一个重要特性,它允许程序在运行时进行自我检查和对内部成员(如字段、方法、类等)的操作,本文将详细介绍... 目录作用1、在运行时判断任意一个对象所属的类作用2、在运行时构造任意一个类的对象作用3、在运行时判断

java如何解压zip压缩包

《java如何解压zip压缩包》:本文主要介绍java如何解压zip压缩包问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java解压zip压缩包实例代码结果如下总结java解压zip压缩包坐在旁边的小伙伴问我怎么用 java 将服务器上的压缩文件解压出来,

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具

Spring WebFlux 与 WebClient 使用指南及最佳实践

《SpringWebFlux与WebClient使用指南及最佳实践》WebClient是SpringWebFlux模块提供的非阻塞、响应式HTTP客户端,基于ProjectReactor实现,... 目录Spring WebFlux 与 WebClient 使用指南1. WebClient 概述2. 核心依

Spring Boot @RestControllerAdvice全局异常处理最佳实践

《SpringBoot@RestControllerAdvice全局异常处理最佳实践》本文详解SpringBoot中通过@RestControllerAdvice实现全局异常处理,强调代码复用、统... 目录前言一、为什么要使用全局异常处理?二、核心注解解析1. @RestControllerAdvice2

Spring IoC 容器的使用详解(最新整理)

《SpringIoC容器的使用详解(最新整理)》文章介绍了Spring框架中的应用分层思想与IoC容器原理,通过分层解耦业务逻辑、数据访问等模块,IoC容器利用@Component注解管理Bean... 目录1. 应用分层2. IoC 的介绍3. IoC 容器的使用3.1. bean 的存储3.2. 方法注