Java向下轉型的意義

來源:互聯網
上載者:User

標籤:誤區   rgs   過程   blog   main   boot   說明   完成   執行個體   

一開始學習 Java 時不重視向下轉型。一直搞不清楚向下轉型的意義和用途,不清楚其實就是不會,那開發的過程肯定也想不到用向下轉型。

其實向上轉型和向下轉型都是很重要的,可能我們平時見向上轉型多一點,向上轉型也比較好理解。 
但是向下轉型,會不會覺得很傻,我是要用子類執行個體對象,先是產生子類執行個體賦值給父類引用,在將父類引用向下強轉給子類引用,這不是多此一舉嗎?我不向上轉型也不向下轉型,直接用子類執行個體就行了。 
我開始學習Java時也是這麼想的,這誤區導致我覺得向下轉型就是沒用的。 
隨著技術的提升,我在看開源的項目學習,發現很多地方都用了向下轉型的技術,這就讓我重視了起來,想要重新來複習(學習)這個知識點。也是搜尋了許多部落格文章,但都沒具體說明向下轉型,只是給了例子示範怎麼使用,反而是向上轉型講了一堆(可能是我沒找到)。

這篇部落格就是講向下轉型的,那我們就來學習下向下轉型,瞭解下這種特性的意義和使用情境

建立一個電子產品介面,如下:

public interface Electronics{}

很簡單,什麼方法都沒有。

建立一個Thinkpad筆記本類,並實現電子產品介面:

public class Thinkpad implements Electronics{    //Thinkpad引導方法    public void boot(){        System.out.println("welcome,I am Thinkpad");            }    //使用Thinkpad編程      public void program(){        System.out.println("using Thinkpad program");    }}

建立一個Mouse滑鼠類,並實現電子產品介面:

public class Mouse implements Electronics{    //滑鼠移動    public void move(){        System.out.println("move the mouse");           }    //滑鼠點擊      public void onClick(){        System.out.println("a click of the mouse");    }}

建立一個Keyboard鍵盤類,並實現電子產品介面:

public class Keyboard implements Electronics{    //使用鍵盤輸入        public void input(){        System.out.println("using Keyboard input");    }}

這裡子類比較多,是為了更好的理解。每個類的方法的邏輯實現也很簡單。列印了一行資訊

接下來,我們想象一個情景:我們去商城買電子產品,電子產品很多吧,比如膝上型電腦,滑鼠,鍵盤,步步高點讀機哪裡不會點哪裡,我們用的手機,等等,這些都屬於電子產品。電子產品是抽象的。好,那麼我們決定買一台Thinkpad,一個滑鼠和一個鍵盤。 
這時,我們需要一個購物車來裝這些電子產品吧。我們可以添加進購物車,然後通過購物車還能知道存放的電子產品數量,能拿到對應的電子產品。 
那麼,一個購物車類就出來了,如下:

import java.util.ArrayList;import java.util.List;public class ShopCar{    private List<Electronics> mlist = new ArrayList<Electronics>();    public void add(Electronics electronics){        mlist.add(electronics);    }    public int getSize(){        return mlist.size();    }    public Electronics getListItem(int position){        return mlist.get(position);    }}

List 集合是用來存放電子產品的,add 方法用來添加電子產品到購物車,getSize 方法用來擷取存放的電子產品數量,getListItem 方法用來擷取相應的電子產品。

可以看到 List<Electronics> 用了泛型的知識,至於為什麼要用泛型?這個不做介紹了,泛型很重要的。 
而我覺得比較疑惑的是為什麼是放 Electronics 的泛型,而不是放Thinkpad,Mouse,Keyboard,Phone等? 
那麼如果是List<Thinkpad>,肯定是放不進滑鼠Mouse的吧,難道要產生3個集合?這裡是定義了3個電子產品類,但是我如果有100種電子產品呢,要定義100個集合? 
這太可怕了。所以之前,我們寫了一個Electronics介面,提供了一個Electronics的標準,然後讓每一個Electronics子類都去實現這個介面。

實際上這裡又涉及到了向上轉型的知識點,我們雖然在add 方法將子類執行個體傳了進來存放,但子類執行個體在傳進去的過程中也進行了向上轉型 
所以,此時購物車裡存放的子類執行個體對象,由於向上轉型成Electronics,已經丟失了子類專屬的方法,以上述例子來分析,Thinkpad執行個體就是丟失了boot() 和program() 這兩個方法,而Mouse執行個體就是丟失了move()和onClick()這兩個方法

但是實際使用Thinkpad或Mouse或Keyboard時,這種情況肯定不是我們想要的

接著我們寫一個測試類別 Test 去測試購物車裡的電子產品。

測試類別 Test 如下:

public class Test{    public static final int THINKPAD = 0;    public static final int MOUSE = 1;    public static final int KEYBOARD = 2;    public static void main(String[] args){        //添加進購物車        ShopCar shopcar = new ShopCar();        shopcar.add(new Thinkpad());        shopcar.add(new Mouse());        shopcar.add(new Keyboard());        //擷取大小        System.out.println("購物車存放的電子產品數量為 ——> "+shopcar.getSize());        //開始測試thinkpad電腦        Thinkpad thinkpad = (Thinkpad)shopcar.getListItem(THINKPAD);        thinkpad.boot();        thinkpad.program();        System.out.println("-------------------");        //開始測試Mouse滑鼠        Mouse mouse = (Mouse)shopcar.getListItem(MOUSE);        mouse.move();        mouse.onClick();        System.out.println("-------------------");        //開始測試Keyboard鍵盤        Keyboard keyboard = (Keyboard)shopcar.getListItem(KEYBOARD);        keyboard.input();    }}

運行: 


 

舉個例子分析就好

 

//開始測試thinkpad電腦Thinkpad thinkpad = (Thinkpad)shopcar.getListItem(THINKPAD);thinkpad.boot();thinkpad.program();

shopcar.getListItem(THINKPAD)這句代碼是擷取到Electronics類型的執行個體。不是Thinkpad的執行個體

通過向下轉型,賦值給子類引用

Thinkpad thinkpad = (Thinkpad)shopcar.getListItem(THINKPAD);

 

這樣子類執行個體又重新獲得了因為向上轉型而丟失的方法(boot 和program)

總結一下吧,很多時候,我們需要把很多種類的執行個體對象,全部扔到一個集合。(這句話很重要) 
在這個例子裡就是把Thinkpad筆記本,Mouse滑鼠,KeyBoard鍵盤等執行個體對象,全部扔到一個Shopcar購物車集合。 
但是肯定不可能給他們每個種類都用一個獨立的集合去存放吧,這個時候我們應該尋找到一個標準,介面就是一個標準。這些都是各種電子產品,抽象成電子產品。然後一個Electronics介面就出來了。 
在回到剛才,我們把很多種類的執行個體對象全部扔到一個集合。或許這樣比較好理解:把很多種類的子類執行個體對象全部扔到存放父類執行個體的集合。 
經過了這個過程,子類執行個體已經賦值給了父類引用(即完成了向上轉型),但很遺憾的丟失了子類擴充的方法。 
很好的是Java語言有個向下轉型的特性,讓我們可以重新獲得丟失的方法,即強轉回子類 
所以我們需要用到子類執行個體的時候,就從那個父類集合裡拿出來向下轉型就可以了,一樣可以使用子類執行個體對象

……

我在搜尋java向下轉型的意義時,得到一個比較好的答案是這樣的: 
最大的用處是java的泛型程式設計,用處很大,Java的集合類都是這樣的。

而在Android開發中,我們在Layout檔案夾,用xml寫的控制項。為什麼能在Activity等組件中通過 findViewById() 方法找到呢?為什麼 findViewById(R.id.textview) 方法傳入TextView的id後,還要轉型為TextView呢?這就是 Java 向下轉型的一個應用

Java向下轉型的意義

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.