1. 程式人生 > >說一下Java中抽象類和介面存在的意義與價值

說一下Java中抽象類和介面存在的意義與價值

首先簡單的介紹一下抽象類:

定義是很簡單的,我們這裡不寫官方的語言,我自己看著都煩,我們就用白話介紹,抽象類本質是一個類,沒問題,那麼類裡面一般都是有方法的,方法包括方法名和方法體,這是常識對不對,那麼什麼是抽象類呢?如果一個類裡面有一種方法只有方法名卻沒有方法體,這樣的類就是抽象類!

舉個例子:

public abstract class TestAbstract {
	//這是一個抽象方法,
	public abstract void run(); 
	//當然這裡面也可以是普通的方法
	public void eat() {
		System.out.println("我是一個在抽象類裡面的普通方法");
	}
}

這裡為了區別普通的類,我們一般加abstract這個關鍵字,我們就認為他是一個抽象類。既然是一個類,那麼普通類的屬性他都有,它也可以寫普通的方法。

這裡就有人說了,那這個有什麼用呢?沒有實現體,就是呼叫也沒用啊,JDK也想到這個了,所以呢他是不讓你直接例項化呼叫的,因為沒用啊,對吧,這也是為什麼抽象類不可以直接例項化自己,這裡說例項化自己有些人不明白,說人話就是不可以自己建立一個自己的物件出來,他只能是子類的引用來建立父類的物件。

舉個例子:

	public static void main(String[] args) {
		/**
		 * 抽象類是不可以自己例項化自己的,只能例項化自己的子類,因為只有子類才有方法的實現,自己例項化自己是沒有意義的。況且就是自己
		 * 裡面有普通方法的實現,他的子類都是可以使用的。
		 */
		TestAbstract t = new TestA01();
		
	}

回到之前的話題,既然有些方法不可以實現,寫了做什麼呢?難道就為了那幾個可以實現的方法?當然不是的,這裡的抽象類是為了子類更好的實現。

我們舉個簡單的例子:我們有一個動物的類,裡面有一個Run的方法,這個時候我們需要繼承他,一隻狗說我會跑,老虎說我也會跑,孔雀說我也會跑,這個時候每一個子類都要繼承他,而且由於Run方法已經被父類實現了,所以每一個都要重寫方法體,是不是很麻煩,這個時候JDK就說了,既然那麼多類需要繼承他,我直接不實現這個方法,你們誰用誰實現算了。這個就是抽象類存在的意義!

說的比較官方一些的話,就是抽象類可以將設計和實現分離,你寫你的抽象類,我寫我的實現方法。這也是為什麼說抽象方法必須被繼承才有意義!

舉個例子:

class TestA01 extends TestAbstract{
	/**
	 * @Override 是註解,JDK5.0以後的新特性,重寫的意思,也就是說,如果是註解了的話,就是重寫的方法,名字是不可以改的, 如果去掉註解,說明不是重寫的方法
	 * 名字是可以改掉的。
	 */
	@Override
	public void run() {
		System.out.println("我是子類的run()");
	}
	
}

總結一下:

 有抽象方法的類必然是抽象類
 抽象類不可以被例項化,不能被new來例項化抽象類
 抽象類可以包含屬性,方法,構造方法,但是構造方法不能用來new例項,只能被子類呼叫
 抽象類只能用來繼承
 抽象類的抽象方法必須被子類繼承

下面我們說一下介面:

介面是我覺得Java裡面相當偉大的一個發明,為什麼呢?聽我說完,介面我們可以認為本質也是一個類,只是修飾符改為了interface,類的修飾符是Class而已,那麼介面是幹嘛呢?前面講了抽象類的使用,介面就是一個比抽象類還要抽象的類,前面說抽象類裡面可以寫普通的方法,說明還不夠抽象,抽象的不夠徹底,介面說乾脆一不做二不休,規定只能寫抽象方法算了,所以說介面是比抽象方法更抽象的類。

舉個例子:

public interface MyIinterface {
	/**
	 * 接口裡面只有常量和抽象方法
	 */
	/*public static final   介面中常量定義時都有這個,寫不寫都是這樣*/String MAX_GREAD = "BOSS";
	int MAX_SPEED = 120;
	/*public abstatic  這裡一樣寫不寫都是public,因為不用public的話沒有意義*/ void test01();
	public int test02(int a, int b);
	
}

有的人說不能被繼承,不是和抽象類一樣嗎?為什麼不寫abstract關鍵字呢?不能被普通方法呼叫,不是靜態變數嗎?是的,說的都對,所以JDK這裡不管你寫不寫,都是預設前面有這些修飾詞的,上面我寫的很明白!

上面有句話說不同public的話沒有意義,其實寫到這裡我們可以基本認為介面和抽象類是一種規則了,它規定你這樣用,你只要繼承或者實現,就必須要按照他的來,所以我們對應到現實生活中的話,就是說是一種規則,既然是規則就是給別人看的,你一個公司制定出來了規章制度,不公佈,別人怎麼遵守?一個道理,如果不用public修飾別人引用不到,和不規定是一樣的。所以JDK也明白,所以這裡的方法你寫不寫public他都預設幫你加上!

下面講實現

我們說了,抽象類也好,介面也好,不繼承,不實現都是沒有意義的,但是因為接口裡面只有抽象方法,所以他必須被實現才有意義,不然就會被垃圾回收機制System.gc給回收掉,前面的文章說過了垃圾回收的原理,這裡不做贅述,但是為什麼不繼承呢?有人說了?既然要被實現裡面的方法,直接繼承不行了嗎?是的,但是類的繼承只能是單繼承,所以,如果一個類裡面有很多的介面,怎麼做?所以只能是實現!

但是有人說了,如果很多介面,最後一個繼承了上面的所有介面,那我實現的時候是不是需要實現所有介面的方法?答案是肯定的:

舉個例子:

package com.gaojizu.TestInterface;
/**
 * 測試介面的多繼承
 * @author admin
 *
 */
public interface InterFaceA {

	void aaa();
}
/**
 * 介面B
 * @author admin
 *
 */
interface InterFaceB{
	void bbb();
}
/**
 * 介面C
 * @author admin
 *
 */
interface InterFaceC extends InterFaceA,InterFaceB{
	void ccc();
}
/**
 * 實現類
 * @author admin
 *
 */
class TestClass implements InterFaceC{

	@Override
	public void aaa() {
		System.out.println("TestClass.aaa()");
		
	}

	@Override
	public void bbb() {
		System.out.println("TestClass.bbb()");
		
	}

	@Override
	public void ccc() {
	   System.out.println("TestClass.ccc()");
		
	}
	
}

其實這裡也不難理解,繼承了就是擁有了父介面的抽象方法,自然就必須實現他。

那有人說了,我這裡如果在子類裡面聲明瞭一個變數,那我直接用父介面的物件呼叫行不行呢?

舉個例子:

class Plane implements FlyAble{

	String name;
	@Override
	public void fly() {
		System.out.println("我可以飛");
		
	}
	
}

這裡有一個name,我測試的時候是不是可以直接使用呢?當然不是,需要強制轉換:

看例子:

	public static void main(String[] args) {
		/**
		 * 這裡的介面是不可以自己例項化自己的,原因和抽象類是一樣的,裡面只有抽象方法,沒有實現的,所以是例項化沒有意義的
		 * 那麼直接f是不可以調出子類裡面的屬性的,原因很簡單,他是FlyAble的物件,那麼他就只能找到自己下面的屬性和方法
		 * 是沒有辦法知道子類的屬性和方法的,想知道的話,就強制轉換為子類的物件就行了。下面是例子
		 */
		FlyAble f = new Plane();
		//強制轉換為Plane類
		Plane p = (Plane)f;
		p.name = "test";
	}

其實這裡用我們生活中的例子也是一樣可以理解的,我們有一個會飛的類,他建立了一個天鵝的物件出來,天鵝說我會下蛋,那按照我們程式碼的邏輯來想,會飛的應該都會下蛋,顯然不是,飛機也會飛,但是不會下蛋,怎麼可以下蛋呢?將例項化出來的物件給一個具體使用的類,也就是天鵝!這裡也是多型的一個體現,你給一個籠統的概念,然後具體的使用是什麼就是什麼的思想!

最後一點:實現是可以多實現的!

前面我們說介面的繼承是可以多繼承的,看明白,是介面可以多繼承,類一樣是單繼承,實現是可以多實現的,你說我既可以飛,也可以跑,飛和跑在兩個接口裡面怎麼辦?可以同時實現:

看例子:

public interface FlyAble {

	int MAX_SPEED = 11000;
	int MIN_SPEED = 1;
	void fly();
}
/**
 * 攻擊的介面
 * @author admin
 *
 */
interface Attack{
	void tack();
}

class Plane implements FlyAble{

	String name;
	@Override
	public void fly() {
		System.out.println("我可以飛");
		
	}
	
}
/**
 * 可以實現多個介面
 * @author admin
 *
 */
class men implements FlyAble,Attack{

	@Override
	public void tack() {
		System.out.println("我可以攻擊");
		
	}

	@Override
	public void fly() {
		System.out.println("我可以飛");
	}
	
}

那麼介面存在的意義就不用說了吧,很明顯了,為了更好的將設計與實現分離。

設計師寫完需要的介面,別的不用管了,怎麼實現是下面的事情了,這樣不僅僅可以提高開發效率,也可以更好的維護。當然如果只有一個人開發,那就沒必要分介面和類了!

覺得寫的還行的,關注一下!一起交流!