深入理解java中的介面 (Interface)
概念
我們知道java中是單繼承的,這就有了很多的限制,比如我們需要多繼承的時候但是不能用多繼承,這時候怎麼辦呢?就引入了介面的概念,它彌補了java中單繼承的缺陷,這一點非常的好,如果要約定子類的實現要求並避免單繼承侷限就需要使用介面。
那麼什麼是介面呢?
介面就是抽象方法和全域性常量的集合,使用Interface關鍵字。
定義
介面如何定義?它與類又有什麼區別呢?
我們先來定義一個介面
例如:
Interface IMessage{
public static final String COUNTRY="China";//全域性常量
public abstract void print();//抽象方法
}
上面這樣的程式碼就是一個簡單的介面的定義,我們為了區分介面,一般在介面名稱前加上字母Interface的首字母I並且大寫。
由於介面中的方法都是抽象方法和全域性常量,我們一般可以省略抽象方法前面的修飾public abstract,以及常量前面public static final的修飾,例如:
Interface IMessage{
String COUNTRY="China";//全域性常量
void print();//抽象方法
}
我們會發現接口裡面並沒有一些具體的資訊,那麼我們如何使用介面呢?
介面和抽象類一樣,不能直接例項化,抽象類由繼承它的子類實現它的抽象方法,那麼介面也有自己的實現類,可以通過介面的實現類實現例項化。
對於它的實現類:
介面的實現類必須實現介面中的所有抽象方法,然後實現類可以通過向上轉型為它的任意介面,然後例項化。
例如下面的程式碼:
interface IMessage{
public static final String MSG = "message" ; // 全域性常量
public abstract void print() ; // 抽象方法
}
interface INews {
public abstract String getNews() ;
}
class MessageImpl implements IMessage,INews {
public void print() {
System.out.println(IMessage.MSG) ;
}
public String getNews(){
return IMessage.MSG ; // 訪問常量都建議加上類名稱
}
}
public class Test{
public static void main(String[] args) {
IMessage m = new MessageImpl() ; //子類向上轉型,為父介面例項化物件
m.print() ; // 呼叫被子類覆寫過的方法
INews n = (INews) m ;
System.out.println(n.getNews()) ;
}
}
我們看看上面這段程式碼的轉換關係如下:
介面的使用限制
在上面的定義中我們知道了介面中,不論是屬性還是方法,許可權都是public的,那麼這就決定了子類在實現介面時實現介面抽象方法的許可權只能是public。
有些人實現的時候習慣和介面中一樣許可權什麼都不寫,這樣是錯誤的,因為什麼都不寫預設的許可權是default許可權的,它的許可權低於public,就會容易出錯。
當一個子類既需要繼承父類又需要實現介面時,應該先繼承再實現
例如:
interface IMessage {
public void print() ;
}
abstract class News {
// 抽象類中方法前面的abstract不能省略,否則就是普通方法
public abstract void getNews() ;
}
class MessageImpl extends News implements IMessage {
public void print() {
System.out.println("I am a biter") ;
}
public void getNews() {
System.out.println("I am News") ;
}
}
需要注意的是:一個抽象類可以實現多個介面,但是介面不能繼承類,介面可以繼承介面
看一個抽象類實現介面的例子:
interface IMessage {
public void print() ;
}
abstract class News implements IMessage{
//News為抽象類,可以不實現IMessage中的抽象方法
// 抽象類中方法前面的abstract不能省略,否則就是普通方法
public abstract void getNews() ;
}
class MessageImpl extends News {
public void print() {
System.out.println("I am a biter") ;
}
public void getNews() {
System.out.println("I am News") ;
}
}
當然,在java中,一個介面可以繼承多個父介面,例如:
interface A {
public void printA() ;
}
interface B {
public void printB() ;
}
interface C extends A,B { // 介面多繼承
public void printC() ;
}
class Impl implements C{
public void printA() {}
public void printB() {}
public void printC() {}
}
public class Test{
public static void main(String[] args) {
}
}
總結
- 接口裡定義抽象方法
- 接口裡定義常量
- JDK7-11介面的一些變數(預設方法)
- 介面是無法例項化的,只能通過實現類
- 介面實現類可以向上轉型成它實現的任意一個介面型別
- 在介面中定義的變數實際是常量,並且public static final 修飾的
- 介面中定義的方法是一個抽象方法,預設使用public abstract 修飾的