1 回答

TA貢獻1998條經驗 獲得超6個贊
這個問題要分具體的情況的,我下面列舉了三種情況,基本上就都包括了,剩下都可以通過這三種情況類似,先看一下我寫了一段測試結果用的代碼,先看結果,之后我再解釋原因
public class Student { private String name; private int age; public Student() { super (); } public Student(String name, int age) { super (); this .name = name; this .age = age; } public String getName() { return name; } public void setName(String name) { this .name = name; } public int getAge() { return age; } public void setAge( int age) { this .age = age; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]" ; } } public class TestRef { public static void main(String[] args) { List<Student> list = new ArrayList<>(); list.add( new Student( "zhang" , 12 )); list.add( new Student( "liu" , 13 )); System.out.println( "list中是普通對象時,修改前" ); System.out.println(list); Student stu = list.get( 0 ); stu.setAge( 22 ); System.out.println( "list中是普通對象時,修改后" ); System.out.println(list); List<Integer> list1 = new ArrayList<>(); list1.add( 1 ); list1.add( 2 ); System.out.println( "list1中裝入基本類型時,修改前" ); System.out.println(list1); Integer a = list1.get( 0 ); a = new Integer( 11 ); System.out.println( "list1中裝入基本類型時,修改后" ); System.out.println(list1); List<String> list2 = new ArrayList<>(); list2.add( "abc" ); list2.add( "def" ); System.out.println( "list2中裝入String時,修改前" ); System.out.println(list2); String s = list2.get( 0 ); s = new String( "abc_abc" ); System.out.println( "list2中裝入String時,修改后" ); System.out.println(list2); } } |
下面是運行的結果:
list中是普通對象時,修改前 [Student [name=zhang, age=12], Student [name=liu, age=13]] list中是普通對象時,修改后 [Student [name=zhang, age=22], Student [name=liu, age=13]] list1中裝入基本類型時,修改前 [1, 2] list1中裝入基本類型時,修改后 [1, 2] list2中裝入String時,修改前 [abc, def] list2中裝入String時,修改后 [abc, def] |
通過上面的例子我們就會發現,我們在修改Student實例中的年齡是可以修改的,但是在修改基本類型(int,long,short,byte,char,float,double,boolean)和String的時候是不變的。這個是直觀的感受,真是是后面這一半是正確的。
我寫Student這個類的目的就是為了來描述我們自己定義的類會不會變,通過上面的例子我們發現變了,那么什么情況下不變呢,看下面這段代碼:
List<Student> list = new ArrayList<>(); list.add( new Student( "zhang" , 12 )); list.add( new Student( "liu" , 13 )); System.out.println( "list中是普通對象時,修改前" ); System.out.println(list); Student stu = list.get( 0 ); //stu.setAge(22); stu = new Student( "song" , 24 ); System.out.println( "list中是普通對象時,修改后" ); System.out.println(list); |
這段代碼是沒有修改list中的內容,其實到這里所有的情況就都包括了,很簡單,在Java中傳遞引用,大家經常會把它理解為傳遞C語言中的指針,其實不然,你更應該把他理解為C語言中的傳遞值,這樣就容易解釋一些現象。
以Student這段代碼為例,list.get(0)拿到的是第一個Student實例的值,當我們直接修改這個實例的時候,是不會影響到list中的內容的,如
Student stu = list.get( 0 ); stu = new Student( "song" , 24 ); |
這種是沒有影響的,但是我們修改返回的這個實例中的屬性的時候的,也就是修改Student中的年齡,姓名等的時候,這個時候是會改變list中的內容的(list中Student的引用的值沒變,但是引用所指向堆中對象具體的屬性改變了)。
也就是下面這種形式會改變的:
Student stu = list.get( 0 ); stu.setAge( 22 ); |
通過這種方式,我們就可以理解基本類型和String的時候為什么不會變了。
添加回答
舉報