理解JAVA的传值方式

简介:

问题: Java的参数传递的是值还是引用?

我们经常会被问到这样的问题,当我调用某个方法时,通过参数传递过去的是变量本身,还是一个变量的复制品?问题的答案留到讨论后给出。


首先,你需要了解下java变量的分类:java中的变量分为

  1. 基本类型
  2. 接口类型
  3. 类类型
  4. 数组类型

其中后面三种统称为引用类型,而基本类型分为三种,

  1. 数字类型
  2. boolean
  3. returnAddress

数字类型又分为

  1. 浮点类型
  2. 整数类型
  3. 浮点

整数又有具体的内容,这里不再展开说明。其中,returnAddress是java虚拟机内部使用的类型,它被用来实现java程序中finally子句。这里主要看引用类型和基本类型数字类型情况(boolean类型的情况和基本类型一致).

先看参数为基本类型的情况:

01 public class Demo1 {
02     public void swap(int a, int b) {
03         a = a ^ b;
04         b = a ^ b;
05         a = a ^ b;
06         System.out.println("swap: a=" + a + ",b=" + b);
07     }
08  
09     public static void main(String[] args) {
10         Demo1 demo1 = new Demo1();
11         int a = 1;
12         int b = 2;
13         demo1.swap(a, b);
14         System.out.println("main: a=" + a + ",b=" + b);
15     }
16 }

输出

1 swap: a=2,b=1
2 main: a=1,b=2

上面的代码想通过swap交互a和b的值,在swap内部,变量a和b已经交换成功了,但在main中a和b的值依然是原来的值.

再看参数为引用的情况:

01 </pre>
02 <pre>public class Demo2 {
03      public void swap(StringBuffer a,StringBuffer b){
04             StringBuffer c = a;
05             a=b;
06             b=c;
07          System.out.println("swap: a="+a+",b="+b);
08      }
09  
10    public static void main(String[] args) {
11       StringBuffer a = new StringBuffer("a");
12       StringBuffer b = new StringBuffer("b");
13       Demo2 demo2 = new Demo2();
14       demo2.swap(a, b);
15       System.out.println("main: a="+a+",b="+b);
16    }
17 }</pre>
18 <pre>

大家可以先思考下,上面的输出是什么?

输出:
swap: a=b,b=a
main: a=a,b=b

和参数为基本类型的情况结果是一致的.
为什么会出现这种情况呢?

我们来分析下上面的参数传递过程,以Demo2为例:

图1是swap未计算前的参数值,

图2是swap计算后的参数值.

从图中可以看出,swap的计算过程只能改变swap内部变量a和b的值,不能改变main中的a和b变量的引用值,换言之,参数的传递只能传值,不存在传引用一说.

请注意,上面我说不能改变a和b变量的引用值,可没说不能改变a和b指向的对象的值.再看下面的例子:

01 </pre>
02 public class Demo3 {
03  public void swap(StringBuffer a,StringBuffer b){
04  a.append(b);
05  StringBuffer c = a;
06  a=b;
07  b=c;
08  System.out.println("swap: a="+a+",b="+b);
09  }
10  public static void main(String[] args) {
11  StringBuffer a = new StringBuffer("a");
12  StringBuffer b = new StringBuffer("b");
13  Demo3 demo3 = new Demo3();
14  demo3.swap(a, b);
15  System.out.println("swap: a="+a+",b="+b);
16  }
17 }
18 这个会输出什么呢?
19  
20 swap: a=b,b=ab
21 swap: a=ab,b=b

这个就是上面所说的,在swap内部的计算过程中,改变了main.a所指向对象的值.

就像下面的图所描述的那样:

但根本上,swap不能改变main中a和b的引用值.

另外贴一句sun公司官方文档上的描述这一问题的原话:

Java is always pass-by-value.when object is passed as a argument, be careful with that it is also the copy of reference

所以,现在你应该知道,java传递的只会是值,没有传递引用.

相关文章
|
存储 Java
Java-参数传值
Java-参数传值
114 4
|
Java 测试技术 数据处理
Java多线程父线程向子线程传值解决方案 2
Java多线程父线程向子线程传值解决方案
313 0
|
Java
Java多线程父线程向子线程传值解决方案 1
Java多线程父线程向子线程传值解决方案
521 0
|
Java
JAVA参数传值机制中值传递和引用传递
JAVA参数传值机制中值传递和引用传递
223 0
|
Java
08 java中方法传参的传值与传址问题
java的值传递与址传递 问题:在java中方法传参到底是值传递还是址传递?
165 0
08 java中方法传参的传值与传址问题
|
存储 Java C++
基于堆栈内存详析 Java函数形参是传值还是引用? | C++指针与Java引用的区别 | C++引用、指针等之间的区别 | C++与Java类的实例化的区别
基于堆栈内存详析 Java函数形参是传值还是引用? | C++指针与Java引用的区别 | C++引用、指针等之间的区别 | C++与Java类的实例化的区别
|
Java
Java - 参数传递(传值、传址/引用)
Java - 参数传递(传值、传址/引用)
539 0
Java - 参数传递(传值、传址/引用)
|
Java C语言
【JavaSE基础】深入了解Java的传值和传引用
【JavaSE基础】深入了解Java的传值和传引用
168 0
【JavaSE基础】深入了解Java的传值和传引用
|
Java Windows
Java是传值还是传引用?
Java是传值还是传引用?
127 0
|
Java
Java 传参传值
Java 传参传值 案例代码 public class PassParamExplain { public static void main(String[] args) { //example A System.
10503 0