笔友城堡 - 可定义的个人主页

前言

Java面试中常见的问题就是关于「值拷贝」和「地址拷贝」,简单记录于此,方便自己查阅和学习。

正文

先说结论:

Java 只有「值拷贝」,没有「地址拷贝」

Java 永远是 pass-by-value(值传递

基本类型

基本类型拷贝的就是「值本身」

int a = 10;
int b = a;
b = 20;

System.out.println(a); // 10
  • a的值是 10
  • b得到的是 10的副本
  • 互不影响

完完全全的值拷贝

引用类型

引用类型拷贝的「引用的值」

Person p1 = new Person("Tom");
Person p2 = p1;
p2.setName("Jerry");

System.out.println(p1.getName()); // Jerry

发生了什么:

栈:
p1 ──┐
      ├──► 堆中的 Person 对象
p2 ──┘
  • p1存的是 对象在堆中的地址值
  • p2 = p1拷贝的是 这个地址值
  • 两个引用指向 同一个对象

仍然是值拷贝,只是值是“地址”

方法传参

Java 是值传递

基本类型
void change(int x) {
    x = 100;
}

int a = 10;
change(a);
System.out.println(a); // 10

方法里改的是 形参的副本

引用类型
void change(Person p) {
    p.setName("Changed");
}

Person person = new Person("Tom");
change(person);
System.out.println(person.getName()); // Changed

关键点:

  • pperson的 引用值拷贝
  • 指向的是 同一个对象
  • 所以对象内容会变
传对象
void change(Person p) {
    p = new Person("New");
}

Person person = new Person("Tom");
change(person);
System.out.println(person.getName()); // Tom

原因:

  • p只是引用的副本
  • p指向新对象,不影响原引用

再次证明:Java 是值传递

匿名类中的拷贝

当你在匿名类中访问局部变量:

int x = 10;
Runnable r = () -> System.out.println(x);

本质是:

class Inner {
    private int val$x;
    Inner(int x) {
        this.val$x = x;
    }
}
  1. 拷贝的是值,不是变量本身
  2. 所以变量不能再改(final / effectively final)

小结

场景拷贝的是什么
基本类型数值本身
引用类型引用的值(地址值)
方法参数永远都是值拷贝
Java 整体只有值传递

Java 没有地址拷贝,只有“值拷贝 + 引用的值”

参考文章

AI

相关网址

笔友城堡 - 可定义的个人主页

暂无评论

评论审核已启用。您的评论可能需要一段时间后才能被显示。

none
暂无评论...