Java對象的引用機理

我們都知道Java是一個面向對象的編程語言,那麼java對象究竟是如何創建和操作的呢?

Demo demo=new Demo();

首先我們看上面這一段代碼,雖然很簡單卻有着其內部的一些機理。前面的Demo demo是一個引用的創建,而後面new Demo();則是一個對象的創建。如果把對象當作一個電視的話,引用實際上相當於一個遙控器。
爲了弄清楚其中發生了什麼,我們首先要知道兩者存儲位置的一些差別。對象存儲在堆中,因爲其內存和生命週期都是不確定的,需要動態分配並且不能確定其佔用內存需要回收的時間。而引用實際上是一小段指向對象所在堆地址的確切的地址數值,其大小是確定的,並且擁有可以確定的生命週期,所以引用在棧中。知道了這些我們再看第一句代碼,new在堆中創建了一個Demo對象,然後在棧中創建了一個Demo引用,最後用等號給引用賦值,讓引用指向Demo對象的地址,這句話就完整的執行完了。

class Demo{
	public void hello() {
		System.out.println("hello!");
	}
}
public class test {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Demo demo=new Demo();		
}
}

我們看上面這段代碼,當程序運行完時,demo這個引用變量由於其生命週期結束,分配的棧內存會立即被會回收,但是在堆中的對象卻不會,而是等待虛擬機在一個不確定的時間對它進行回收,這是兩者在生命週期上的差別。

Demo demo=new Demo();
Demo demo2=demo;

我們再看上面這段代碼,這樣執行的結果是demo和demo2實際表示的是同一個對象,他們都記載着同一個Demo對象所在堆地址,所以如果使用其中一個更改,整個對象都會被更改。

class Demo{
	int a;
	public void add() {
		a++;
	}
}
public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Demo demo=new Demo();
		Demo demo2=demo;
		demo2.add();
		System.out.print(demo.a);
		
}
}

上面這段代碼最終輸出的結果就是1。由於堆中的數值會自動初始化,所以a的初值會自動設爲0,對demo2引用的對象進行a++,實際上也就是對demo所引用的對象進行a++,從中我們就很好看出兩者的關係。一個對象可以被多個引用指向,而一個引用只能指向一個對象。
在c++中我們同樣學過對象相關的內容,對比來看,c++中的對象和Java中有什麼不同呢?
首先,在c++中,Demo demo;就意味着創建了一個Demo的對象,而Java中這麼做則是創建了一個引用。其次,Java中沒有指針這個概念,使用引用來操作對象,而c++中則需要通過指針來操作對象。

//c++
Demo *demo=new Demo();
    demo->add();
    demo->say();

對比Java來說指針的使用很容易出錯,而且難度也很大,所以Java取消指針而採用引用可以說方便了不少。當然引用和指針有諸多區別,比如指針可以計算而引用並不能。指針可以計算直接的問題就在於指針可能會指向一些奇怪的地方,一些不應該由本程序操作的地方,這是非常危險的,對於我們程序員來說也是不好控制的。而引用則永遠不會作用在程序意外的地方。所以對比來看引用安全,沒有大小且不可計算。但是使用指針也有指針的好處,因爲指針的使用更加靈活高效,直接在地址上進行運算使得c++的數組存取效率高於Java。綜合來說兩者各有優略,雖然本質上都是想指向要操作的東西,但使用時要注意區分,不能混爲一談。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章