在阅读本文之前,根据自己的经验和理解,大家可以先思考并选择一下Java函数的参数传递方式:
A. 是按值传递的?
B. 按引用传递的?
C. 部分按值部分按引用?
此处暂不宣布正确答案,我们通过一个简单的例子让大家自己找答案:
1. 先定义一个类型Value
public static class Value {
private String value = "value";
public String getValue() { return value; }
public void setValue(String value) { this.value = value; }
}
2. 写两个函数newValue和modifyValue:newValue会将入参指向一个新的对象,modifyValue会调用入参的setValue方法修改对象的value值。
public static void newValue(Value value) {
value = new Value();
value.setValue("new value");
System.out.println("In newValue, HashCode = " + value.hashCode() + ", value = " + value.getValue());
}
public static void modifyValue(Value value) {
value.setValue("new value");
System.out.println("In modifyValue, HashCode = " + value.hashCode() + ", value = " + value.getValue());
}
3. 简单的测试代码
public static void main(String[] args) {
Value value1 = new Value();
System.out.println("Before modify, HashCode = " + value1.hashCode() + ", value = " + value1.getValue());
// 将value1指向新的Value对象
newValue(value1);
System.out.println("After modify, HashCode = " + value1.hashCode() + ", value = " + value1.getValue() + "\n");
Value value2 = new Value();
System.out.println("Before modify, HashCode = " + value2.hashCode() + ", value = " + value2.getValue());
// 使用object的set方法,修改对象的内部值
modifyValue(value2);
System.out.println("After modify, HashCode = " + value2.hashCode() + ", value = " + value2.getValue());
}
4. 执行结果日志:
Before modify, HashCode = 12677476, value = value
In newValue, HashCode = 33263331, value = new value
After modify, HashCode = 12677476, value = value
Before modify, HashCode = 6413875, value = value
In modifyValue, HashCode = 6413875, value = new value
After modify, HashCode = 6413875, value = new value
5. 结果分析:
上述代码这是非常常见的一种编程模式:在外围定义|保存|获取一个值或对象,将这个对象作为参数传入一个方法,在方法中修改对象的属性、行为。但两个方法newValue和modifyValue的修改方式不一样,在方法调用之后,该对象在外围看来也有很大的差别!如何理解这种差异呢?先温故一下按值传递、按引用传递的概念:
* 按值传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的一个副本。因此,如果函数修改了该参数,仅改变副本,而原始值保持不变。
* 按引用传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的内存地址,而不是值的副本。因此,如果函数修改了该参数,参数的原始值(函数块之外的调用代码中)也随之改变。
正确的答案:A——Java函数是按值传递参数的!
分析一下日志:
* 第一段日志输出,value1参数在newValue方法内部被改为指向新对象,并输出了新对象的hashCode和value值,但跳出newValue方法域之后,在main方法中的value1没有发生任何变化,这符合按值传递的定义和特点;如果是按引用传递,value1在调用newValue(Value value)方法之后,应该是发生变化的。
* 第二段日志输出,value2在modifyValue方法内部进行了setValue操作,hashCode不变而value被修改,离开modifyValue方法域之后,在main方法中value2确实发生了变更。使用过C++的人容易将这种现象理解为:按引用传递函数参数!因为这跟C++中的按引用传递像极了!但这里恰恰是最容易陷入误区的地方!
两段日志的不同现象背后所隐藏的是原理是:Java语言是按值传递参数,按引用传递对象的;Java中所操作的对象其实都是操作对象的引用,object本身保存在“堆”中,而对象的“引用“保存在寄存器或“栈”中。
伪代码描述一下newValue方法和modifyValue方法的不同之处:
newValue{
Value_ref2 = value_ref1; // 按值传入引用value_ref1,得到value_ref1的副本
value_obj2 = new Value(); // value_obj2被创建、初始化在“堆“中
value_ref2 -> value_obj2; // value_ref2 指向value_obj2
value_ref2 ->value_obj2.setValue(“xxx”); // value_obj2 的value被修改
printValueObj2(); // 此处打印的是obj2的值
}
modifyValue{
Value_ref2 = value_ref1; // 按值传入引用value_ref1,得到value_ref1的副本
value_ref2 ->value_obj1.setValue(“xxx”); // value_obj1 的value被修改
printValueObj1(); // 此处打印的是obj1的值
}
够清楚了吧!value1_ref1在作为参数传入函数的时候,首先被复制了一份副本value1_ref2供函数域使用,此时这两个ref都是指向同一个value_obj; newObject函数中的代码[ value = new Value(); ] 其实是将value1_ref1指向了一个新的对象value_obj2;在这之后的set操作都是对新对象的操作;modifyValue函数是通过set方法直接操作value_obj1,这是跟newValue函数的不同之处。
如果还是不太明白,请先确定是否已经理解 “引用”、“对象”的概念,可以Google、百度相应的文章学习一下:)
分享到:
相关推荐
### Java的引用与函数参数传递详解 #### 一、Java中的引用基础 在Java中,对象的引用扮演着类似于其他编程语言(如C/C++)中指针的角色,但是Java的引用比传统的指针更加安全且易于管理。这是因为Java的设计者们...
Java中参数传递方式详解 Java 中参数传递方式详解是 Java 新手入门面临的一个经典的话题。本文意在终结这个话题,Java 中有说法:Java 里面参数传递都是按值传递,怎么理解这句话? 按值传递和按引用传递是来自 ...
### 浅析Java引用类型和方法参数传递 #### 一、引言 在Java编程语言中,理解数据类型的处理方式对于编写高效、可维护的代码至关重要。本文将深入探讨Java中的引用类型及其如何影响方法参数的传递机制。通过具体实例...
在Java中,方法(或称为函数)可以通过参数来接收外部的数据,并且能够返回处理后的结果。参数的传递方式主要有两种:值传递(Pass-by-value)和引用传递(Pass-by-reference)。Java主要采用值传递的方式。 ##### ...
### 关于Java中的传递方式详解 #### 一、引言 在Java编程中,了解数据是如何在函数间传递的是至关重要的。这对于理解程序的行为、调试以及优化代码都非常关键。Java支持两种基本的数据传递方式:值传递和引用传递...
### Java函数详解 #### 一、函数的基本概念 在Java编程语言中,函数通常被称为**方法**。函数是一段可重用的代码块,它在类的定义中被声明,并且能够实现特定的功能。通过使用函数,我们可以将复杂的任务分解为更...
### Java中的按值传递与按引用传递详解 #### 一、引言 在Java编程语言中,关于参数传递的方式一直存在两种观点:一种认为Java仅支持按值传递,另一种则指出Java同时支持按值传递和按引用传递。实际上,这两种观点...
Java中的函数参数传递主要有两种方式:值传递和引用传递。这两种方式在处理不同类型的参数时有不同的行为。 1. 值传递:对于基本数据类型(如int、char、float等),参数传递时会创建该变量的一个副本,函数内部对...
在Java编程语言中,函数参数的传递方式有两种:值传递和引用传递。理解这两种机制对于编写高效、无误的代码至关重要。以下是对这两种传递方式的详细解析。 首先,值传递是指函数调用时,实际参数的值被复制一份传给...
JavaScript中的函数参数传递机制一直以来都是开发者讨论的热点。在传统观念中,JavaScript的参数传递常被误解为引用传递,即类似C++或C中的指针传递。然而,JavaScript的实现其实更为复杂,它包含了值传递和引用传递...
标题提到的"Java行为参数化功能详解"着重介绍了这一技术。 描述中提到了性能优化的重要性,特别是对于数组和HashMap的使用,以及如何通过分析CPU使用率、I/O延迟和系统吞吐量来识别性能瓶颈。虽然这段描述没有直接...
### JNI中C和Java参数传递详解 #### 一、引言 Java Native Interface (JNI) 是Java平台标准的一部分,用于让Java代码与其他语言写的代码进行交互。本文将深入探讨在JNI环境中,C/C++和Java之间如何进行参数传递,...
### Java零基础-参数传递详解 #### 内容概要 本文旨在深入解析Java语言中的参数传递机制。作为一门广泛使用的编程语言,Java提供了多种处理数据的方法,其中参数传递是函数(方法)间数据交互的基础。本文将重点...
例如,我们可以定义一个`DiskInfo`类,包含一个字符串`name`和一个整型`serial`,然后声明一些本地方法来处理参数传递: ```java public class DiskInfo { public String name; public int serial; // 声明本地...
本主题将深入探讨如何实现Java与JS之间的通信,包括互相调用函数以及传递参数。以下是一份详细的指南: 1. **WebView**: 为了在Android应用中执行JS代码,我们通常使用`WebView`组件。`WebView`不仅能够加载网页,...
Java中的参数传递方式主要有两种:值传递和引用传递。理解这两种机制是编程中至关重要的,因为它们直接影响到函数内部如何改变或操作传入的数据。 **值传递**在Java中是基本数据类型(如int, double, char等)的...
Java函数式编程是一种高效、简洁的编程风格,它在Java 8中得到了广泛支持。函数式编程的核心思想是将计算视为函数的组合,避免副作用,提高代码的可读性和可测试性。在Java中,我们可以利用Lambda表达式、高阶函数、...
Java向Runnable线程传递参数方法实例解析 Java是一种支持多线程编程的语言,线程是Java程序中最基本的执行单元。在线程编程中,线程之间的数据传递是一种非常常见的需求。在Java中,Runnable接口是实现多线程的关键...
JAVA内存分配与参数传递详解 JAVA内存分配是JAVA编程语言中的一项重要机制,决定了程序在内存中的存储方式和数据交换方式。JAVA参数传递是JAVA编程语言中的一种函数调用机制,决定了函数参数的传递方式。下面对JAVA...
### multipart/form-data 参数传递 在Web开发中,`multipart/form-data`是一种用于发送表单数据的编码类型,尤其适用于处理文件上传。此编码方式能够使客户端浏览器将表单中的普通文本字段与文件字段一起发送到...