如何理解这三种定义方式
Collection arr1 = new ArrayList();
List arr2 = new ArrayList();
ArrayList arr3 = new ArrayList();
大家讲道理2017-04-17 16:46:08
更新回答:
其實不是三種情況,是兩種情況。
我給你舉個實際開發中經常碰到的場景的例子,你就明白為什麼「我們經常要把一個物件轉型成它的父類或介面來使用了」。
通常我們在使用清單的時候都是這樣寫的:
List list = new ArrayList();
而不是
ArrayList list = new ArrayList();
第一種為什麼比第二種好?
假設你用了二種方式聲明一個列表,然後被其他人引用了(或者被你自己在其他地方用了)。
突然有一天,你發現用ArrayList不好,需要換成LinkedList,那你一定要把聲明改成:
LinkedList list = new LinkedList();
這樣以來,用到你的list的地方都得更改類型聲明。更重要的是,用到你的list的人,他們寫自己的程式碼的時候是基於「你的這個list是一個ArrayList 」這樣的前提來寫的,你突然把它改成了LinkedList,很可能導致他們的程式出錯或需要重寫。
但是如果你一開始就用第一種聲明方式,就不會有這個問題。你隨時可以更換list的,引用你的list的其他人或其他地方不需要任何修改。例如:
List list = new LinkedList();
所以說,當你宣告一個變數的時候,把它的類型聲明得越籠統越好,越具體越糟糕。前者對修改是友善的,後者對修改不友善。
類似的,確定一個方法的可訪問性(即public、protected、預設的、private)時,在可能的情況下,越小越好。
PHP中文网2017-04-17 16:46:08
ArrayList實作了List接口,因此ArrayList肯定是List類型,同理List實作了Collection接口,因此List肯定是Collection類型。也可以理解為ArrayList的向上轉型。
PHP中文网2017-04-17 16:46:08
例如你是個酒神,對酒情有獨鍾。某日回家發現桌上有幾個杯子裡面都裝了白酒,從外面看我們是不可能知道這是些什麼酒,只有喝了之後才能夠猜出來是何種酒。你一喝,這是劍南春、再喝這是五糧液、再喝這是酒鬼酒….在這裡我們可以描述成如下:
酒 a = 剑南春
酒 b = 五粮液
酒 c = 酒鬼酒
…
这里所表现的的就是多态。剑南春、五粮液、酒鬼酒都是酒的子类,我们只是通过酒这一个父类就能够引用不同的子类,这就是多态——我们只有在运行的时候才会知道引用变量所指向的具体实例对象。
诚然,要理解多态我们就必须要明白什么是“向上转型”。在继承中我们简单介绍了向上转型,这里就在啰嗦下:在上面的喝酒例子中,酒(Win)是父类,剑南春(JNC)、五粮液(WLY)、酒鬼酒(JGJ)是子类。我们定义如下代码:
JNC a = new JNC();
对于这个代码我们非常容易理解无非就是实例化了一个剑南春的对象嘛!但是这样呢?
Wine a = new JNC();
在这里我们这样理解,这里定义了一个Wine 类型的a,它指向JNC对象实例。由于JNC是继承与Wine,所以JNC可以自动向上转型为Wine,所以a是可以指向JNC实例对象的。这样做存在一个非常大的好处,在继承中我们知道子类是父类的扩展,它可以提供比父类更加强大的功能,如果我们定义了一个指向子类的父类引用类型,那么它除了能够引用父类的共性外,还可以使用子类强大的功能。