◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。
当谈到方法参数时,java 编程中最容易被误解的主题之一是“按值传递”和“按引用传递”之间的区别。在这篇博文中,我们将深入探讨这些概念,包括 java 如何实际处理方法参数,并提供说明性代码示例来阐明幕后发生的事情。
在“按值传递”中,方法接收传递给它的参数的实际值的副本。对方法内参数所做的任何修改都不会影响原始参数。
在“按引用传递”中,方法接收对参数实际内存位置的引用(或地址)。对参数的修改直接影响原始对象,因为该方法在同一内存上操作。
在java中,所有参数都是按值传递的。但是,此语句可能会产生误导,因为根据参数是基本类型还是对象引用,按值传递的内容会有所不同。
立即学习“Java免费学习笔记(深入)”;
这种区别可能会造成混乱,导致一些开发人员错误地认为 java 支持“按引用传递”。让我们用代码示例来分解它。
当您将基本类型传递给方法时,java 会创建实际值的副本。方法内参数的更改不会影响原始变量。
public class passbyvaluedemo { public static void main(string[] args) { int num = 10; system.out.println("before method call: " + num); // output: 10 modifyprimitive(num); system.out.println("after method call: " + num); // output: 10 } public static void modifyprimitive(int n) { n = 20; // changes the copy, not the original system.out.println("inside method: " + n); // output: 20 } }
说明:
• num 的值被复制并传递给modifyprimitive 方法。
• 在方法内部,对本地副本(n)进行了更改,但主方法中的 num 保持不变。
对于对象来说,引用(内存地址)是按值传递的。这意味着该方法对引用指向的同一个对象进行操作,但引用本身是一个副本。让我们来说明一下:
示例1:修改对象状态
class person { string name; person(string name) { this.name = name; } } public class passbyvalueobject { public static void main(string[] args) { person person = new person("alice"); system.out.println("before method call: " + person.name); // output: alice modifyobject(person); system.out.println("after method call: " + person.name); // output: bob } public static void modifyobject(person p) { p.name = "bob"; // modifies the same object system.out.println("inside method: " + p.name); // output: bob } }
说明:
• 复制对 person 对象的引用并将其传递给modifyobject 方法。
• 原始引用和复制引用都指向内存中的同一对象,因此对象状态的更改在方法外部可见。
示例 2:重新分配对象引用
现在让我们看看如果您尝试在方法内重新分配引用本身会发生什么。
public class passbyvaluereassign { public static void main(string[] args) { person person = new person("alice"); system.out.println("before method call: " + person.name); // output: alice reassignobject(person); system.out.println("after method call: " + person.name); // output: alice } public static void reassignobject(person p) { p = new person("charlie"); // reassigns the local copy of the reference system.out.println("inside method: " + p.name); // output: charlie } }
说明:
• 引用人员被复制并传递给 reassignobject 方法。
• 在方法内部,本地副本 (p) 被重新分配以指向新对象 (new person("charlie")),但这不会影响 main 方法中的原始引用。
• 主静态中的原始人物引用指向“alice”对象。
原始类型:
• 该值直接存储在与变量关联的内存位置。
• 当传递给方法时,该值将被复制到参数的新内存位置。
对象引用:
• 对象的引用(内存地址)存储在变量中。
• 当传递给方法时,引用会被复制,因此原始引用和复制的引用都指向堆内存中的同一个对象。
示例:对象引用
Person person = new Person("Alice"); // Memory layout // Stack (local variables): // person -> address: 0x1234 // Heap (objects): // 0x1234 -> Person{name="Alice"}
当传递给方法时:
• 创建一个新引用(例如 p),它也指向 0x1234。
通过理解这些细微差别,您将能够更好地推理 java 方法调用并避免程序中的常见陷阱。
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。