众所周知Java的参数传递也分为值传递和引用传递
值传递
public class MethodAndParam { static void swap(int a,int b){ int c = a; a = b; b =c; } /** * @param args */ public static void main(String[] args) { int a = 1 ,b =2; swap(a, b); System.out.println(a+","+b); } }
其结果大家都知道,a、b的值没有交换成功。
引用传递
static void addA(StringBuffer sBuf){ sBuf.append("A"); } /** * @param args */ public static void main(String[] args) { StringBuffer sBuf = new StringBuffer(); addA(sBuf); System.out.println(sBuf.toString()); }
因为是引用传递,能找到对象的真实地址从而改变对象的值,其输出结果为A。
static void addA(String str){ str = str + "A"; } /** * @param args */ public static void main(String[] args) { String str = ""; addA(str); System.out.println(str); }
问题一:同样是引用传递,但结果并没有输出A,而是输出了空串,这是为什么呢?
我们将StringBuffer的例子改造如下:
static void addAByNew(StringBuffer sBuf){ sBuf = new StringBuffer(); sBuf.append("A"); } /** * @param args */ public static void main(String[] args) { StringBuffer sBuf = new StringBuffer(); addAByNew(sBuf); System.out.println(sBuf.toString()); }
同样上面的运行结果也没有输出A,而是输出了空串。如果传递的是引用,方法内部的代码sBuf = new StringBuffer()将引用指向了新的地址空间,在新的地址空间里append("A")。
问题二:在方法内部对引用的改变为什么没有影响到外部的对象?
对于问题一,大家可以看一下String对象的源码
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; /** The offset is the first index of the storage that is used. */ private final int offset; /** The count is the number of characters in the String. */ private final int count;
String类是final修饰的,表示不能被继承。对于被final修饰的属性的赋值有如下几种方式:
1. 如果有static修饰的属性,可以在static{}块里赋值
2. 如果没有static修饰,可以在代码块{}里赋值
3. 在定义变量时赋值
4. 在构造方法里赋值
即一旦一个对象创建,其final修饰的属性值将不可改变,而String对象中存放值的value数组则是final修饰的,我们可以理解为:一个String对象的值改变后,它已经不是原来的它了。理解了String对象的不变性后可知问题一和问题二背后是同一个原因。
从JVM出发来看方法的调用
栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,每一个方法从调用开始到执行完成的过程,就对应着一个栈帧在虚拟机栈里面从入栈到出栈的过程。
栈帧包括了局部变量表、方法返回地址等信息。其中局部变量表是一组变量值空间,用于存放方法参数和方法内部定义的局部变量。
现在可以回答问题二了:参数的引用传递不是单纯的将对象的引用传递给一个方法,而是将对象引用的地址传递给局部变量表里的参数引用,当在方法内部改变引用的地址时,只会影响方法内部的引用,而不会影响到方法外部的变量。但如果改变的是引用地址的值,方法内外的引用都会受影响。
相关推荐
本文将深入探讨Java中的参数传递机制,并通过具体的代码示例和内存分配图解来帮助读者理解按值传递和按引用传递的概念。 #### 二、按值传递的概念与特点 按值传递是指在函数或方法调用过程中,传递给函数或方法的...
了解这些基础知识后,我们可以进一步研究源码和使用工具来深入理解方法调用和参数传递。例如,使用IDEA的调试功能,可以观察方法调用前后变量的变化,或者通过JIT编译器优化看到方法调用的实际运行效果。 总结来说...
在Java编程语言中,了解值传递和引用传递的概念至关重要,因为它们直接影响到函数参数的处理方式。下面将详细探讨这两个概念及其区别。 首先,我们来理解什么是值传递。在Java中,基本数据类型(如int、double、...
在Java编程语言中,函数参数的传递方式有两种:值传递和引用传递。理解这两种机制对于编写高效、无误的代码至关重要。以下是对这两种传递方式的详细解析。 首先,值传递是指函数调用时,实际参数的值被复制一份传给...
本文将详细介绍值传递和引用传递的概念、用法以及它们之间的区别,并通过Java语言中的具体示例来加深理解。 #### 二、值传递 **值传递**是指在函数或方法调用时,传递给函数的实际参数的值被复制一份到形参,即形参...
关于标签“源码”和“工具”,它们暗示了更深入的探讨可能涉及Java虚拟机(JVM)如何处理对象引用以及开发者工具如何帮助理解这一过程。例如,可以使用Java的`System.identityHashCode()`方法来验证不同引用是否指向...
此外,学生还了解了 Java 中的基本概念,例如,方法的声明、方法的调用、基本类型和引用类型等。 六、教师评语 本实验报告总的来说是优秀的,学生掌握了方法的声明和调用、值传递和 Math 类的使用。但是,学生需要...
Java编程语言中,参数传递的方式主要有两种:值传递和引用传递。然而,由于Java不支持指针,所以严格意义上的引用传递并不存在。但是,通过对象的传递,Java实现了类似引用传递的效果。 值传递是Java中基本类型的...
Java编程语言中有两种参数传递方式:按值传递和按引用传递。理解这两种方式对于编写高效、无误的代码至关重要。 1. **按值传递(Pass by Value)** - Java中的基本类型(如int, double, char等)是按值传递的。这...
本文将深入探讨Java与C++这两种广泛使用的编程语言中参数传递的方式,包括值传递、引用传递以及C++中的指针传递,并通过具体的代码示例来帮助理解这些概念。 #### 值传递 值传递是最简单的参数传递方式之一,它指...
在编程语言中,值传递和引用传递是函数参数传递的两种基本方式,它们涉及到内存管理、数据安全以及程序效率等多个重要方面。这篇文章将深入探讨这两种传递方式,并通过内存解析来帮助理解它们的工作原理。 首先,...
我们先看一下值传递和引用传递的概念和区别 值传递:是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。 引用传递:是指在调用函数时将实际参数的地址直接...
Visio是一种流程图和矢量图形软件,这些图形文件将帮助开发者以视觉化的方式理解Java中的值传递和引用传递。"方法传入对象类型参数,对象引用不能被修改"的示例可能显示了即使在方法内部改变了对象引用,外部的引用...
总结来说,值传递和引用传递是Java中处理参数传递的两种机制。理解这两者的差异对于正确处理方法调用和对象状态至关重要。值传递适用于基本数据类型,而引用传递则适用于对象类型,允许方法直接修改对象的状态。在...
java通过实例了解值传递和引用传递 Java语言中有两种基本的参数传递方式:值传递和引用传递。值传递是指在方法调用时,传递的参数是按值的拷贝传递。引用传递是指在方法调用时,传递的参数是按引用进行传递,其实...
这是因为java中的对象参数传递也是值传递的,在调用`SChange`方法时,我们将`name`变量的引用传递给`str`参数,而不是传递`name`变量的地址或值。因此,在`SChange`方法中修改`str`参数的值,会影响到`name`变量的值...
对于值传递的理解,是深入Java语言机制的关键一环。 首先,让我们明确Java的内存分配。在Java中,内存主要分为三个部分:栈内存、堆内存以及方法区内存。栈内存是存储基本类型变量和对象引用的地方,其特点是在方法...