1. 程式人生 > >解惑真小白的苦惱 | 類的物件,物件引用,物件例項,引用變數

解惑真小白的苦惱 | 類的物件,物件引用,物件例項,引用變數

對於剛接觸不久面向物件的真小白童鞋來說,類的物件,物件的例項,物件的引用,引用變數的問題以及莫過於沒得物件~雖然博主也沒得物件~,本文將逐個逐個講解!

1.何謂物件?

  在Java中有一句比較流行的話,叫做“萬物皆物件”,這是Java語言設計之初的理念之一。要理解什麼是物件,需要跟類一起結合起來理解。下面這段話引自《Java程式設計思想》中的一段原話:
  

“按照通俗的說法,每個物件都是某個類(class)的一個例項(instance),這裡,‘類’就是‘型別’的同義詞。”

  從這一句話就可以理解到物件的本質,簡而言之,它就是類的例項,比如所有的人統稱為“人類”,這裡的“人類”就是一個類(物種的一種型別),而具體到每個人,比如張三這個人,它就是物件,就是“人類”的例項。
  

2.何謂物件引用?

我們先看一段話,這段話同樣來自於《Java程式設計思想》:
 

 “每種程式語言都有自己的資料處理方式。有些時候,程式設計師必須注意將要處理的資料是什麼型別。你是直接操縱元素,還是用某種基於特殊語法的間接表示(例如C/C++裡的指標)來操作物件。所有這些在
Java
裡都得到了簡化,一切都被視為物件。因此,我們可採用一種統一的語法。儘管將一切都“看作”物件,但操縱的識別符號實際是指向一個物件的“引用”(reference)。”

  很顯然,從這段話可以看出物件和物件引用不是一回事,是兩個完全不同的概念。舉個例子,我們通常會用下面這一行程式碼來建立一個物件:

 

 Person per = new Person("張三");

有小白童鞋會說,這裡的per是一個物件,是Person類的一個例項。也有小白童鞋會說,這裡的per並不是真正的物件,而是指向所建立的物件的引用。到底哪種說法是對的?我們先不急著糾結哪種說法是對的,再看兩行程式碼:
 

 Person person;
  person = new Person("張三");

  這兩行程式碼實現的功能和上面的一行程式碼是完全一樣的。大家都知道,在Java中new是用來在堆上建立物件用的,如果per是一個物件的話,那麼第二行為何還要通過new來建立物件呢?

由此可見,per並不是所建立的物件,是什麼?上面的一段話說的很清楚,“操縱的識別符號實際是指向一個物件的引用”,也就是說per

是一個引用,是指向一個可以指向Person類的物件的引用。真正建立物件的語句是右邊的new Person("張三");因此這裡的per是一個引用,是指向一個可以指向Person類的物件的引用。

簡單來說,物件的引用意思是“定義一個變數,這個變數指向的是一個物件“

Object  obj=new Object();
//Object:類
//obj:物件的引用
//new Object():物件

3.何謂物件例項?

首先,沒有“物件的例項”這一說法,只有類的例項,而類的例項,指的就是類的物件,說白了就是物件。
但是還是有很多人這樣叫,那怎麼理解物件例項呢?比如說人類中有個叫宜春的程式設計師,宜春就是人類的一個例項

String s = new String("YiChun");

s 就是 String類中的一個例項

關於物件例項官方沒有給其概念,其實有很多概念官方都沒有給的,什麼父類宣告指向子類物件、方法簽名等概念都是沒有的 ,只是人們經常這麼用這麼說就習慣了。因此關於例項物件大體可以理解為物件引用的意思...

4.何謂引用變數?

引用變數就是用引用型別宣告的變數,這種變數叫引用型別變數。如:

People people;  //其中people就是引用變數,People是一個類屬於引用型別

5、物件與物件引用碰撞火花

從物件引用出發:

一個物件引用可以指向零個或一個物件

從物件出發:

一個物件可以被一個或多個物件引用

怎麼理解捏?~小白童鞋腦殼逐漸變大...~

5、1. 從物件引用出發:一個物件引用可以指向零個或一個物件

首先先來理解第一句話:從物件引用出發:一個物件引用可以指向零個或一個物件

public static void main(String[] args) {
      Two t; //一個物件引用可以指向零個物件
      t=new Two();//一個物件引用可以指向一個物件
      t=new String();//一個物件引用不可以指向 >1個物件
    }

試想一下這樣的程式碼會出現啥情況?是的,它會編譯失敗

看完上面這個例子就能說明了麼?我們接著看下面這個程式碼:

 public static void main(String[] args) {
        String str;
        str=new String("string1");
        str=new String("string2");
    }

我們知道,凡是new都能創建出一個物件,我們發現上面程式碼String物件引用str一個new了兩次,而且上面程式碼編譯也不報錯,的的確確是建立了兩個物件,那這怎麼說?小白童鞋說完感覺把博主按在馬桶蓋上...

別急,我們再看看上面程式碼輸出啥

  public static void main(String[] args) {
        String str; 
        str=new String("string1");
        str=new String("string2");
        System.out.println(str);
    }
    
 執行結果: string2

這說明啥?說明現在str是下一個物件的引用。上一個物件被垃圾回收了,因為上一個物件(也就是string1)不能被再次使用了。因此上面這個程式可以這樣理解:

 public static void main(String[] args) {
   String str;//一個物件引用str指向零個物件
   str=new String("string1");//一個物件引用str指向一個物件string1
   str=new String("string2");//注意:這裡物件引用str並不是指向第二個物件string2,而是將之前指向第一個物件string1的引用重新指向了另一個物件string2
}

物件引用str並不是指向第二個物件string2,而是將之前指向第一個物件string1的引用重新指向了另一個物件string2,因此從物件引用出發:一個物件引用可以指向零個或一個物件!

這個時候,小白童鞋漸漸鬆開了把博主按在馬桶蓋上的雙手...

5、2. 從物件出發:一個物件可以被一個或多個物件引用

我們再來理解一下第二句話:從物件出發,一個物件可以被一個或多個物件引用

小白童鞋同樣不解,於是又用雙手把博主按在馬桶蓋上...

看下面這個程式:

   Demo demo1,demo2,demo3;
   demo1=new Demo();
   demo2=demo1;
   demo3=demo2;

怎麼理解?看的有點暈?會不會感覺後面兩句程式碼就是物件引用=物件引用...

其實要弄清除這個,首先你得弄清楚java虛擬機器記憶體,弄清楚變數(物件引用)和物件是如何儲存的,物件引用是儲存在棧記憶體中,而物件是儲存在堆記憶體中。分析如下:

Demo demo1,demo2,demo3;//建立多個物件引用,都儲存在棧中
demo1=new Demo();//建立一個Demo物件,儲存在堆中,並將demo1指向這個物件,相當於加了一個鏈
demo2=demo1;//demo2與demo1一樣,都指向堆中Demo物件
demo3=demo2;//demo3與demo2一樣,都指向堆中Demo物件

首先,每個物件只有一個地址值,new Demo()是建立了一個物件,demo1是這個物件的地址值,用來找到這個物件,demo2=demo1是把new Demo()這個物件的地址值由demo1改為了demo2,後面的demo3=demo2也是隻改變了物件的地址值,物件本身的空間大小都沒有變化,變的,是這個物件的地址值,也就是c裡面所謂的指標。

這個時候,小白童鞋漸漸鬆開了把博主按在馬桶蓋上的雙手...

最後,我們再看看一個網上關於物件與物件引用很流行的程式與分析,程式碼如下:

UserType ut = new UserType();  // ut是引用,實際的物件在記憶體裡。
ut = new UserType(); /*現在ut是另一個物件的引用,先前的物件被垃圾回收了(因為先前的物件不能被再次使用了)。*/
UserType ut2;  // 定義了一個引用ut2,他不引用任何物件,不能使用。。。。
ut2 = new UserType(); // 然ut2成為一個物件的引用。
UserType ut3 = new UserType();
UserType ut4 = new UserType();
ut3 = ut4;   // 現在ut3引用ut4的物件,這裡不是賦值。。。
int a = 5;
int b = 4;
a = b;  // 這裡是賦值。 a b 依然引用不同的物件

6、最後要相信的真理

對於面嚮物件語言,如java,首先,請小白童鞋相信一句話:一切皆為物件。然後相信另一句話:變數只是一個零時的儲存地點。引用型別的變數只是一個普通變數,儲存了引用型別的地址。物件的建立是直接在記憶體中分配一個記憶體。

最後再梳理一下

引用型別變數 就 相當於 電腦上的快捷方式; 物件就相當於 你 磁盤裡面 安裝的遊戲,它 實實在在 佔用你的空間記憶體; 而變數 只是快捷方式

說白了基本資料型別變數就像是直接放在櫃子裡的東西,而引用資料型別變數就是這個櫃子對應編碼的鑰匙。鑰匙號和櫃子對應。

到這裡文章就結束了喔,小白童鞋,你何識著咩啊~

最後,若有不足或者不正之處,歡迎指正批評,感激不盡!

歡迎各位關注我的公眾號,一起探討技術,嚮往技術,追求技術...


小白童鞋關注了我的公眾號之後,又用雙手把博主按在馬桶蓋蓋上.