Java 值传递与引用传递

news2024/9/21 0:48:07

在这里插入图片描述
以下是包含引用的完整博客文章,以markdown格式输出,附带“Java 只有值传递”的相关参考来源。


Java 是一种广泛使用的面向对象编程语言,但对于值传递(pass by value)和引用传递(pass by reference)的理解,很多开发者往往会混淆。在这篇文章中,我将详细解释 Java 的传递机制,并引入对象克隆、深浅拷贝和不可变类的概念。

值传递还是引用传递?

首先,我们必须明确一点:Java 只有值传递。这是什么意思呢?每次我们在方法中传递参数时,实际上传递的是值的副本。无论是基本类型还是对象引用,传递的都是副本。

Java 的参数传递机制是值传递,无论是基本类型还是对象类型。引用类型传递时,传递的是引用的副本,也就是地址的副本。

基本类型的值传递

对于基本类型(如 intfloat 等),传递的是变量的值副本。我们来看一个简单的例子:

public class ValueDemo {
    public static void main(String[] args) {
        int a = 10;
        changeValue(a);
        System.out.println(a);  // 输出仍然是 10
    }

    public static void changeValue(int x) {
        x = 20;
    }
}

在上面的代码中,a 的值并没有发生改变。这是因为 Java 将 a 的值复制给了参数 x,所以 x 的修改不会影响原来的 a

对象类型的值传递

对于对象类型(如 StringArrayList 等),传递的依然是引用的副本,而不是引用本身。换句话说,我们传递的是对象的地址副本。这意味着我们可以通过引用修改对象的内部状态,但不能更改引用本身。

看下面的例子:

public class ReferenceDemo {
    public static void main(String[] args) {
        Person person = new Person("Alice");
        changeName(person);
        System.out.println(person.getName());  // 输出是 "Bob"
    }

    public static void changeName(Person p) {
        p.setName("Bob");  // 修改对象的内部状态
    }
}

class Person {
    private String name;

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

    public String getName() {
        return name;
    }

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

在这个例子中,Person 对象的 name 被成功修改为 "Bob",因为我们通过引用修改了对象的内部状态。但要注意,这并不意味着 Java 支持引用传递,只是传递了引用的副本。

深拷贝与浅拷贝

当我们需要复制对象时,可能会遇到浅拷贝(shallow copy)和深拷贝(deep copy)的概念。理解这两个概念对于处理复杂对象非常重要。

浅拷贝

浅拷贝只复制对象的引用,而不复制实际的对象内容。换句话说,浅拷贝后,新旧对象共享相同的内部对象。常见的浅拷贝方式是通过实现 Cloneable 接口的 clone() 方法。

class Person implements Cloneable {
    private String name;

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();  // 浅拷贝
    }

    public String getName() {
        return name;
    }
}

public class ShallowCopyDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person("Alice");
        Person person2 = (Person) person1.clone();

        System.out.println(person1 == person2);  // 输出 false
        System.out.println(person1.getName() == person2.getName());  // 输出 true
    }
}

上例中,person1person2 是两个不同的对象,但它们内部的 name 字符串引用了相同的对象。这就是浅拷贝。

深拷贝

深拷贝则不同,它不仅复制对象本身,还会复制所有引用的对象。实现深拷贝通常需要手动编写复制逻辑,或使用序列化机制。

class Person implements Cloneable {
    private String name;

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person cloned = (Person) super.clone();
        cloned.name = new String(this.name);  // 深拷贝,创建新字符串对象
        return cloned;
    }

    public String getName() {
        return name;
    }
}

public class DeepCopyDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person("Alice");
        Person person2 = (Person) person1.clone();

        System.out.println(person1 == person2);  // 输出 false
        System.out.println(person1.getName() == person2.getName());  // 输出 false
    }
}

在深拷贝中,新对象 person2name 是一个全新的对象,和 person1name 没有任何关联。

不可变类

在讨论值传递和引用传递时,不可变类(immutable class)是另一个重要的概念。不可变类一旦创建,内部状态就不能改变。不可变类的经典例子是 String 类。由于不可变性,我们无需担心对象被其他方法意外修改

要创建一个不可变类,我们可以遵循以下规则:

  1. 将类声明为 final,防止子类修改。
  2. 所有字段都声明为 final,防止字段被修改。
  3. 提供深拷贝的 getter 方法,避免返回可变对象的引用。
final class ImmutablePerson {
    private final String name;

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

    public String getName() {
        return name;
    }
}

public class ImmutableDemo {
    public static void main(String[] args) {
        ImmutablePerson person = new ImmutablePerson("Alice");
        // 无法修改 person 的状态,因为它是不可变的
    }
}

不可变类的设计能确保对象的状态安全,尤其是在多线程环境下,它们天生具有线程安全性

总结

  • Java 只有值传递,无论是基本类型还是对象类型,传递的都是副本 。
  • 对于对象类型,传递的是引用的副本,这使得可以通过引用修改对象的内部状态。
  • 浅拷贝只复制对象的引用,而深拷贝会复制对象本身及其引用的对象。
  • 不可变类是一种特殊的类,它的状态一旦初始化就不能再改变,提供了更高的安全性。

通过理解这些概念,我们可以更好地控制 Java 中的对象传递和状态管理,避免出现意外的修改和不必要的对象共享。


参考文献

  1. 《Java 编程思想》(Thinking in Java:

    “Java passes everything by value. When you pass a primitive, you get a copy of the primitive. When you pass a handle, you get a copy of the handle.”

  2. Java 官方文档(Java Language Specification, JLS):

    “When an object is passed to a method, the reference to the object is passed by value.”

  3. 《Effective Java》(Effective Java:

    “Java is strictly pass-by-value. When you pass a reference to an object, you’re passing the value of the reference, which is the address of the object.”

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2144942.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

只有公网IP地址可以申请SSL证书吗?

是的,只有公网IP地址可以申请SSL证书。这是因为SSL证书主要用于加密互联网上的数据传输,确保通信的安全性和数据的完整性。而公网IP地址是互联网通信的核心,具有全球唯一性,允许互联网上的用户通过它们访问互联网上的资源。 具体…

北森笔试测评之言语理解到底难不难

前篇笔记我提到过,言语理解是最难的,有同学质疑了。言语我都会做呀,甚至有的可以搜到,而图标和图形我有的不会。这里需要指出,会做不等于作对,可以回顾到高中甚至初中的时候,感觉做的好的一般都…

dcmtk的自动输入数据纠错模式对DICOMDIR读取的影响

软件版本 dcmtk 3.6.7 自动纠错的全局变量 输入数据的自动纠错是一个全局变量,定义在dcmtk/dcmdata/dcobject.h中,如下所示: /** This flags defines whether automatic correction should be applied to input* data (e.g.\ stripping …

【多视图学习】基于多视图信息瓶颈的鲁棒表示学习

论文链接 代码链接 0.论文摘要和信息 摘要 信息瓶颈原理为表示学习提供了一种信息论方法,通过训练编码器来保留与预测标签相关的所有信息,同时最小化表示中的其他过量信息的量。然而,原始配方需要标记数据来识别多余的信息。在这项工作中&…

【C++ Primer Plus习题】16.8

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream> #include <set> #includ…

Android 15 正式发布至 AOSP

Google官方宣布&#xff0c;将于近期发布了 Android 15&#xff0c;而在早些时候&#xff0c;Google已经将其源代码推送至 Android 开源项目 (AOSP)。未来几周内&#xff0c;Android 15 将在受支持的 Pixel 设备上正式推出&#xff0c;并将于今年晚些时候在三星、Honor、iQOO、…

easy_cloudantivirus

0x00前言 必须安装在virtualbox 攻击机&#xff1a;kali 靶机 easy_cloudantivirus 链接&#xff1a; https://www.vulnhub.com/entry/boredhackerblog-cloud-av,453/ 0x01信息搜集 经过测试发现靶场IP为192.168.56.106 进一部对IP搜集信息 发现8080端口youhttp服务。…

MySQL系列—12.Undo log

1、概念 DML 操作导致数据变化 , 将变化前的记录写入 Undo 日志。 作用 用于记录更改前的一份 copy &#xff0c;在操作出错时&#xff0c;可以用于回滚、撤销还原&#xff0c;只将数据库 逻辑地恢复到原来的样子 你 插入一条记录时&#xff0c;至少要把这条记录的主键值记下来…

上汽集团社招入职SHL测评:语言理解及数字推理高分攻略、真题题库

上汽集团社招待遇 上汽集团作为国内领先的汽车制造企业&#xff0c;其社招待遇和面试问题一直是求职者关注的焦点。以下是根据最新信息整理的上汽集团社招待遇及面试问题概览&#xff1a; 工资待遇&#xff1a;上汽集团的工资待遇在国内汽车行业中属于较高水平。根据不同职位和…

【C++二叉树】236.二叉树的最近公共祖先

236. 二叉树的最近公共祖先 - 力扣&#xff08;LeetCode&#xff09; 思路分析&#xff1a; 公共祖先满足的特征&#xff1a; p是q的孩子&#xff0c;则q是祖先&#xff0c;反之亦然。p和q是“我”的左子树和右子树中的节点&#xff0c;则“我”是祖先。&#xff08;如题目中给…

物联网——USART协议

接口 串口通信 硬件电路 电平标准 串口参数、时序 USART USART主要框图 TXE: 判断发送寄存器是否为空 RXNE: 判断接收寄存器是否非空 RTS为输出信号&#xff0c;用于表示MCU串口是否准备好接收数据&#xff0c;若输出信号为低电平&#xff0c;则说明MCU串口可以接收数据&#…

springboot实训学习笔记(5)(用户登录接口的主逻辑)

接着上篇博客学习。上篇博客是已经基本完成用户模块的注册接口的开发以及注册时的参数合法性校验。具体往回看了解的链接如下。 springboot实训学习笔记&#xff08;4&#xff09;(Spring Validation参数校验框架、全局异常处理器)-CSDN博客文章浏览阅读576次&#xff0c;点赞7…

NANO 9K玩转RISCV之ARDUINO开发环境

一、前言 在从0-1探索RISCV指令集的路上&#xff0c;我们用百元不到的NANO 9K开发板一步步的实现&#xff1a;  &#xff11;&#xff09;最小的内核架构 &#xff12;&#xff09;取值&#xff0c;译码和执行的过程&#xff08;电路实现ISA指令集&#xff09; &#xff1…

使用神经网络拟合6项参数

使用神经网络拟合6项参数 1. 数据预处理1.1 添加参数解析1.2 数据预处理逻辑1.3 数据归一化及划分1.4 数据标签处理逻辑1.5 数据转torch 2. 定义model2.1 CNN_LSTM2.2 Transformer 3. 定义train脚本3.1 loss和optimizer3.2 train3.3 predict 1. 数据预处理 1.1 添加参数解析 …

Vue+nodejs+express汽车配件商城销售管理系统 i9cgz

目录 技术栈具体实现截图系统设计思路技术可行性nodejs类核心代码部分展示可行性论证研究方法解决的思路Express框架介绍源码获取/联系我 技术栈 该系统将采用B/S结构模式&#xff0c;开发软件有很多种可以用&#xff0c;本次开发用到的软件是vscode&#xff0c;用到的数据库是…

动态分析基础

实验一 Lab03-01.exe文件中发现的恶意代码 问题&#xff1a; 1.找出这个恶意代码的导入函数与字符串列表? 2.这个恶意代码在主机上的感染迹象特征是什么? 3.这个恶意代码是否存在一些有用的网络特征码?如果存在&#xff0c;它们是什么? 解答&#xff1a; 1.找出这个恶意代…

上调铁矿石产量预期后,淡水河谷股价能否重振?

猛兽财经的核心观点&#xff1a; &#xff08;1&#xff09;尽管市场面临挑战&#xff0c;但淡水河谷(VALE)还是上调了2024年的铁矿石产量预期。 &#xff08;2&#xff09;第二季度业绩喜忧参半;收入减少&#xff0c;但铁矿石出货量却很强劲。 &#xff08;3&#xff09;投资者…

【渗透测试】-vulnhub源码框架漏洞-Os-hackNos-1

vulnhub源码框架漏洞中的CVE-2018-7600-Drupal 7.57 文章目录  前言 1.靶场搭建&#xff1a; 2.信息搜集&#xff1a; 主机探测&#xff1a; 端口扫描&#xff1a; 目录扫描&#xff1a; 3.分析&#xff1a; 4.步骤&#xff1a; 1.下载CVE-2018-7600的exp 2.执行exp: 3.写入木…

QCustomPlot笔记(一)

文章目录 简介将帮助文档添加到Qt Creator中编译共享库cmake工程编译提示ui_mainwindow.h找不到qcustomplot.h文件 环境:windowsQt Creator 10.0.1cmake 简介 QT中用于绘制曲线的第三方工具 下载地址&#xff1a;https://www.qcustomplot.com/index.php/download 第一个压缩…

心觉:不能成事的根本原因

很多人一直都很努力&#xff0c;每天都很忙 每天都学习很多东西&#xff0c;学习各种道&#xff0c;各种方法论 但是许多年过去了依然一事无成 自己的目标没有达成&#xff0c;梦想没有实现 为什么呢 关键是没有开悟 那么什么是开悟呢 现在很多人都在讲开悟 貌似开悟很…