Java当中,有一个基本概念:“值传递”和“引用传递”。
对于方法的参数通常有两种传送方式,值传递和引用传递。通俗的来讲,值传递就是把变量的内容(值)复制了一份传入传入方法并进行执行,引用传递是指把对象的引用(因为Java没有指针的概念,引用其实就是指针,指向内存中的某个位置)传递入方法并进行执行。
Java中基础变量(primary variable)都通过值传递,对象(Object)通过引用传递
Primary Variable int,double,float,boolean,byte,char… Value pass Object Reference pass String 特殊,使用value pass
为了进一步理解什么是值传递,什么是引用传递,有下面这个例子:
引用传递和值传递的不同 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package leo.test;
* 测试类用来显示引用传递(Reference pass)和值传递(Value pass)的不同
*
* @author LeoDong
* @version 1.0
*
*/
public class ReferenceValue {
* 对一个int变量进行加一
*/
public static void add (int x) {
x = x + 1 ;
}
* 对一个Num对象的成员变量a进行加一
*/
public static void add (Num x) {
x.a = x.a + 1 ;
}
* 内部类Num,只包含一个成员变量int a
*/
static class Num {
private int a;
* 构造函数
*
* @param n
* a的初始值
*/
public Num (int n) {
a = n;
}
}
* 主方法
*/
public static void main (String[] args) {
int INT = 5 ;
System.out.println("调用add方法之前" );
System.out.println("INTt = " + INT);
add(INT);
System.out.println("调用add方法之后" );
System.out.println("INTt = " + INT);
Num NUM = new Num(5 );
System.out.println("调用add方法之前" );
System.out.println("NUM.at = " + NUM.a);
add(NUM);
System.out.println("调用add方法之后" );
System.out.println("NUM.at = " + NUM.a);
}
}
程序运行结果为:
运行结果 1
2
3
4
5
6
7
8
调用add方法之前
INT = 5
调用add方法之后
INT = 5
调用add方法之前
NUM.a = 5
调用add方法之后
NUM.a = 6
也就是说,对于一个int变量,调用add方法后,值并没有增加,但对于一个Num的对象,调用add方法后,成员变量的值进行了增加。
重点关注一下这两个methods:引用传递和值传递的不同 1
2
3
4
5
6
7
8
9
10
11
12
13
* 对一个int变量进行加一
*/
public static void add (int x) {
x = x + 1 ;
}
* 对一个Num对象的成员变量a进行加一
*/
public static void add (Num x) {
x.a = x.a + 1 ;
}
首先,对于一个int a = 5,在调用add(a)的时候,内存中会拿出一块新的地方(不同于a的位置),来存放a = 5的值,我们暂且把这个新位置记为x ,然后将x+1存到x的位置里(x = 6),之后,方法结束跳出,a的位置上的内容依然不变(a=5)。这就是值传递的过程,在传递中,变量被拷贝,并在一块新的位置里进行操作。
然后对于一个Num的对象NUM及一个成员变量a=5, 在调用add(NUM)的时候,会将NUM的引用传入方法,也就是说此时x和NUM同时指向内存里的同一块地方(一块Num对象大小的地方,且成员变量a=5),之后将这块位置内的成员变量a+1,然后方法结束跳出。此时,内存里这块地方已经存了6.这就是引用传递的过程,在传递中,一个指向同一块内存区域的引用被生成,所有操作都是在目标内存区域内进行的。 值传递及引用传递,作为Java非常重要的基础概念,在应用中有非常重要的地位,有一些bug可能就出现在这个问题上
另外这个sample code里面有一个内部类(inner class)Num,但Num里面的私有成员(private int a)可以直接在主类的其他方法里调用。这在java里是合法的。这一点可以这样理解,在主类中所有成员都是公平的,也就是说,即使是内部类,也和其他的private,public方法是同一等级的,所以,即使a是Num的私有成员,对于属于同大类的其他方法,都是公平的,所以a的有效区域就是整个主类。