package Virtual;
class Stan{
String mm = "hello";
}
class Virtual {
public static void main(String[] args)
{
Stan s=new Stan();
System.out.println(s.mm);
change(s);
System.out.println(s.mm);
}
public static void change(Stan s)
{
s.mm="say";//其實是改變了mm指向字符串的地址,從指向hello的地址改成指向say的地址,hello還是存在,只是沒有指向它
}
}
mm剛開始指向的是hello那一片內存,當傳入change函數里,對象是原對象的引用,可以直接指向原對象mm的地址,此時如果將s.mm改成say,由於String類型是不可改變的,只能為say重新分配一片內存空間,並且將mm的值指向say的內存,所以輸出會改變,
其實是改變了String對象 mm指向字符串的地址,從指向hello的地址改成指向say的地址,hello還是存在,只是沒有指向它
再看下一個例子
package Virtual;
class Stan{
String mm = "hello";
}
class Virtual {
public static void main(String[] args)
{
String s="123";
System.out.println(s);
change(s);
System.out.println(s);
}
public static void change(String s)
{
s="say";
}
}
此時s並沒有被更改,這是為什么呢?因為傳入函數時,是復制了一個String對象副本,這個String對象指向了say的內存空間,但是原String對象指向的還是123的內存空間,所以s並沒有發生更改。String類型可以被認為是傳值,即另外創建一個String對象,與原對象無關
package Virtual;
class Stan{
int temp=10;
}
class Virtual {
public static void main(String[] args)
{
Stan s=new Stan();
System.out.println(s.temp);
change(s);
System.out.println(s);
}
public static void change(Stan s)
{
s.temp=30;
}
}
這個跟例子1是一樣的,也是傳遞對象的引用,即地址,並且temp是int型,可以被更改,所以直接改變temp所在的堆區的值為30
另外關於String類型的賦值還有對象的賦值還要說明,
String s1 = "hello"; String s2 = s1;//賦值在棧中,還是指向同一片內存,new在堆中自然指向不同內存 String s3 = new String(s1);new在堆中自然指向不同內存 System.out.println(s1==s2); //返回值為true,說明指向的是同一片內存,因為hello儲存在棧中,所以定義s2在棧中指向了同一片內存也就是hello的內存 System.out.println(s1==s3); //返回值為false,說明指向的是兩片內存,因為new是在堆中分配內存,重新為hello在堆中分配了內存,原來的hello內存儲存在棧中為改變
那么對象呢,對象的賦值就是引用
MyObject myObject = new MyObject();
myObject.setName("Hello");
System.out.println(myObject.getName());//輸出Hello
MyObject hisObject = myObject;//賦值初始化hisobject對象
hisObject.setName("World");//改變了對象的名字屬性
System.out.println(myObject.getName());//輸出World
這說明了在對象賦值中是直接賦值了引用,改變hisObject的名字屬性,相當於改變myObject的名字屬性,相當於hisObject是MyObject的引用,兩個對象指向的是同一片內存空間。
MyObject myObject = new MyObject();
myObject.setName("Hello");
System.out.println(myObject.getName());//輸出Hello
MyObject hisObject = new MyObject();
hisObject.setName("World");
System.out.println(myObject.getName());//輸出hello
new對象,這個不用多說,其實是兩個完全不相干的對象。
