惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 聂微东
S
Schneier on Security
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Latest news
Latest news
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
T
The Exploit Database - CXSecurity.com
T
Tenable Blog
I
Intezer
T
Threat Research - Cisco Blogs
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cybersecurity and Infrastructure Security Agency CISA
P
Privacy International News Feed
P
Palo Alto Networks Blog
The Register - Security
The Register - Security
IT之家
IT之家
Google DeepMind News
Google DeepMind News
C
Cyber Attacks, Cyber Crime and Cyber Security
L
LINUX DO - 最新话题
S
Securelist
WordPress大学
WordPress大学
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Hugging Face - Blog
Hugging Face - Blog
N
News and Events Feed by Topic
H
Help Net Security
Project Zero
Project Zero
K
Kaspersky official blog
博客园 - 三生石上(FineUI控件)
L
LINUX DO - 热门话题
大猫的无限游戏
大猫的无限游戏
G
GRAHAM CLULEY
F
Full Disclosure
博客园 - 叶小钗
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
TaoSecurity Blog
TaoSecurity Blog
N
News | PayPal Newsroom
Forbes - Security
Forbes - Security
博客园 - 司徒正美
I
InfoQ
Recent Announcements
Recent Announcements
Attack and Defense Labs
Attack and Defense Labs
P
Privacy & Cybersecurity Law Blog
S
Security @ Cisco Blogs
人人都是产品经理
人人都是产品经理
The GitHub Blog
The GitHub Blog
Simon Willison's Weblog
Simon Willison's Weblog
G
Google Developers Blog
N
Netflix TechBlog - Medium
U
Unit 42
阮一峰的网络日志
阮一峰的网络日志

博客园 - 有点懒惰的大青年

用一个实际业务场景演示ON和WHERE的正确使用方式 idea中查看源码 异或运算 使用Hutool对时间的花式操作 合并K个升序列表 比较器 枚举类的设计模式 spring boot中使用RedissonClient实现分布式锁 idea同时启动application,启用不同端口 @PostConstruct用法 ApplicationContext 事件发布与监听机制详解 java自带命令jps介绍 关于maven中标签的说明 mysql的跨库查询 linux命令ll显示结果的含义 Files类的使用 java环境变量设置 kafka的集群与可靠性 kafka的消费全流程 关于kafka 达梦数据库执行计划介绍 关于MQ 用位运算实现加减乘除(3)
java值传递和引用传递
有点懒惰的大青年 · 2025-07-24 · via 博客园 - 有点懒惰的大青年

参考:

https://cloud.tencent.com/developer/article/1450963

https://blog.csdn.net/Flying_Fish_roe/article/details/143103367

1.引用传递  

在Java中,引用传递(Reference Passing)是一个概念,它指的是当一个方法接收一个对象引用作为参数时,对这个对象所做的任何修改都会影响到原始对象本身。这与值传递(Value Passing)相对,后者在传递基本数据类型时发生,此时传递给方法的是数据值的副本,对副本的修改不会影响原始数据值。

引用传递示例

package com.test.reference;

/**
 * java引用传递测试
 */
public class TestReference {

    public static void main(String[] args) {
        Person person = new Person("Alice");
        System.out.println("Before: " + person.getName()); // 输出 Before: Alice
        changeName(person);
        System.out.println("After: " + person.getName()); // 输出 After: 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;
    }
}

在这个例子中,changeName 方法接收一个 Person 对象的引用。当我们调用 p.setName("Bob") 时,我们实际上修改了传递给 changeName 方法的对象实例本身。因此,当我们再次访问 person 对象时,它的名字已经变成了 "Bob"。这证明了引用传递的概念:通过对象引用的修改影响了原始对象。

2.引用传递与值传递的区别

值传递:当你传递基本数据类型(如 intdoublechar 等)时,传递给方法的是这些值的副本。对副本的修改不会影响原始值。在方法被调用时,实参通过形参把它的内容副本传入方法内部,此时形参接收到的内容是实参值的一个拷贝,因此在方法内对形参的任何操作,都仅仅是对这个副本的操作,不影响原始值的内容。值传递传递的是真实内容的一个副本,对副本的操作不影响原内容,也就是形参怎么变化,不会影响实参对应的内容。

public static void main(String[] args) {
    int num = 10;
    System.out.println("Before: " + num); // 输出 Before: 10
    increment(num); // 注意这里传递的是num的副本,num的值不会改变
    System.out.println("After: " + num); // 输出 After: 10
}
 
public static void increment(int number) {
    number = number + 1; // 这里改变的是number的副本,不影响原始的num变量
}

引用传递:当你传递对象(任何非基本数据类型的实例)时,传递给方法的是对象的引用(即内存地址)。对对象的任何修改都会影响原始对象。”引用”也就是指向真实内容的地址值,在方法调用时,实参的地址通过方法调用被传递给相应的形参,在方法体内,形参和实参指向同一块内存地址,对形参的操作会影响的真实内容。

总结

引用传递在Java中主要体现在对象和数组的参数传递上。当你需要修改对象的状态或属性时,使用引用传递是非常有用的。然而,值得注意的是,即使是在引用传递的情况下,如果你试图通过方法改变对象引用的指向(例如将一个对象的引用设置为另一个新对象),那么外部的原始引用并不会改变指向新的对象,除非你显式地将新对象赋值给原始引用。例如:

public static void changeReference(Person p) {
    p = new Person("Charlie"); // 这不会影响原始的person引用,它仍然指向原来的Alice对象
}

在这种情况下,p 在 changeReference 方法内部被重新指向了一个新的 Person 实例,但原始的 person 变量仍然指向原来的实例。要使外部的引用也指向新的对象,你需要这样做:

public static void changeReference(Person p) {
    Person person = new Person("Charlie"); // 这不会影响原始的person引用,除非我们这样做:
    p = person; // 这样原始的person引用也会指向新的Person实例"Charlie"
}

结语

因此可见:在Java中所有的参数传递,不管基本类型还是引用类型,都是值传递,或者说是副本传递。 只是在传递过程中:

如果是对基本数据类型的数据进行操作,由于原始内容和副本都是存储实际值,并且是在不同的栈区,因此形参的操作,不影响原始内容。

如果是对引用类型的数据进行操作,分两种情况,一种是形参和实参保持指向同一个对象地址,则形参的操作,会影响实参指向的对象的内容。一种是形参被改动指向新的对象地址(如重新赋值引用),则形参的操作,不会影响实参指向的对象的内容。

--