先上源碼
public class TestRef {
public int id = 1;
public static void main(String[] args) {
int a = 10;
String b = "a";
TestRef c = new TestRef();
change(a);
change(b);
change(c);
changeRef(c);
}
public static void change(int a) {
a = 20;
}
public static void change(String b) {
b = "c";
}
public static void change(TestRef c) {
c = new TestRef();
}
public static void changeRef(TestRef c) {
c.id = 10;
}
}
再上字節(jié)碼:
public class TestRef {
public int id;
public TestRef();
Code:
0: aload_0 //將this載入棧頂
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0 //再次將this載入棧頂,因?yàn)樯厦婺切衖nvokespecial已經(jīng)消耗掉第一行的this去實(shí)例化對(duì)象了
5: iconst_1 //將常量值1推入棧頂
6: putfield #2 // Field id:I //設(shè)置偏移4那行推入的this的#2變量的值為偏移5那行所推入的值
9: return
public static void main(java.lang.String[]);
Code:
0: bipush 10
2: istore_1
3: ldc #3 // String a
5: astore_2
6: new #4 // class TestRef
9: dup
10: invokespecial #5 // Method "<init>":()V
13: astore_3
14: iload_1
15: invokestatic #6 // Method change:(I)V
18: aload_2
19: invokestatic #7 // Method change:(Ljava/lang/String;)V
22: aload_3
23: invokestatic #8 // Method change:(LTestRef;)V
26: aload_3
27: invokestatic #9 // Method changeRef:(LTestRef;)V
30: return
public static void change(int);
Code:
0: bipush 20
2: istore_0
3: return
public static void change(java.lang.String);
Code:
0: ldc #10 // String c
2: astore_0
3: return
public static void change(TestRef);
Code:
0: new #4 // class TestRef
3: dup
4: invokespecial #5 // Method "<init>":()V
7: astore_0
8: return
public static void changeRef(TestRef);
Code:
0: aload_0 //將參數(shù)載入棧
1: bipush 10 //推入一個(gè)10
3: putfield #2 // Field id:I //設(shè)置參數(shù)的#2實(shí)例變量的值為10
6: return
}
3個(gè)change(T)方法都是錯(cuò)誤的使用例子,從字節(jié)碼可以看到基本都是在操作方法自身的局部變量表,方法的參數(shù)都是一個(gè)對(duì)象引用(或者說指向?qū)ο髢?nèi)容的指針副本) 修改也只是將指針的值改變,而非指針指向的值
changeRef方法第一行就是 aload_0這個(gè)和構(gòu)造函數(shù)第一行一樣,都是將this載入棧頂
而this是一個(gè)指向?qū)ο蟮囊?指針)。
在main方法偏移26那行,aload_3 是將局部變量表slot 3 的的對(duì)象引用復(fù)制到棧頂,這樣從旁證明了,java傳遞對(duì)象的時(shí)候傳遞的是對(duì)象的引用的副本 對(duì)象的引用是4個(gè)字節(jié)(操作數(shù)棧和局部變量表 都是一個(gè)單位等于4個(gè)字節(jié) 基本類型除了 double long之外其他都是一個(gè)單位)這也從旁佐證 方法調(diào)用傳遞的是對(duì)象引用副本