0x01.介面
什麼是介面?
介面是Java語言中的一種引用型別,是方法的"集合",所以介面的內部主要就是定義方法,包含常量,抽象方法(JDK 7及以前),預設方法和靜態方法(JDK 8),私有方法(jdk9)
。
介面的定義,它與定義類方式相似,但是使用 interface 關鍵字。它也會被編譯成.class檔案,但一定要明確它並不是類,而是另外一種引用資料型別。
public class 類名.java-->.class
public interface 介面名.java-->.class
引用資料型別:陣列,類,介面。
介面的使用,它不能建立物件,但是可以被實現( implements ,類似於被繼承)。一個實現介面的類(可以看做是介面的子類),需要實現介面中所有的抽象方法,建立該類物件,就可以呼叫方法了,否則它必須是一個抽象類。
例項:
public interface IA {
// 常量 預設修飾符是 public static final 這3個修飾符可以省略不寫
public static final int NUM = 10;
int NUM1 = 20;
// 抽象方法 預設修飾符是 public abstract 這2個修飾符可以省略不寫
public abstract void method1();
void method2();
// 預設方法 預設修飾符是 public default public可以省略,default不可以省略
public default void method3(){
System.out.println("IA 介面預設方法");
}
// 靜態方法 預設修飾符 public static public可以省略,static不可以省略
public static void method4(){
System.out.println("靜態方法");
}
// 私有方法 修飾符 private private不可以省略
private void method5(){
System.out.println("私有非靜態方法");
}
private static void method6(){
System.out.println("私有靜態方法");
}
}
public class Test {
public static void main(String[] args) {
/*
介面的定義:
public interface 介面名{
jdk7及其以前: 常量,抽象方法
jdk8: 額外增加預設方法和靜態方法
jdk9及其以上: 額外增加了私有方法
}
*/
System.out.println(IA.NUM1);// 10
}
// 類中的預設方法,使用預設許可權修飾符(空)
void method(){
}
}
實現概述
類與介面的關係為實現關係,即類實現介面,該類可以稱為介面的實現類,也可以稱為介面的子類。實現的動作類似繼承,格式相仿,只是關鍵字不同,實現使用 implements
關鍵字。
實現格式
-
類可以實現一個介面,也可以同時實現多個介面。
-
類實現介面後,必須重寫介面中所有的抽象方法,否則該類必須是一個“抽象類”。
public interface IA{
public void show1();
}
public interface IB{
public void show2();
}
public class Zi implements IA ,IB{
public void show1(){
}
public void show2(){
}
}
- 類可以在“繼承一個類”的同時,實現一個、多個介面;
public class Fu{}
public interface IA{}
public interface IB{}
public class Zi extends Fu implements IA,IB{//一定要先繼承,後實現
}
介面中成員訪問特點概述
介面中成員的訪問特點:
介面中的常量: 主要是供介面直接使用
介面中的抽象方法: 供實現類重寫的
介面中的預設方法: 供實現類繼承的(實現類中可以直接呼叫,實現類物件也可以直接呼叫)
介面中的靜態方法: 只供介面直接呼叫,實現類繼承不了
介面中的私有方法: 只能在介面中直接呼叫,實現類繼承不了
案例演示
/*
介面
*/
public interface IA {
// 介面中的常量: 主要是供介面直接使用
public static final int NUM = 10;
// 介面中的抽象方法: 供實現類重寫的
public abstract void method1();
// 介面中的預設方法: 供實現類繼承使用(實現類中可以直接呼叫,實現類物件也可以直接呼叫)
public default void method2(){
System.out.println("預設方法method2");
method4();
method5();
}
// 介面中的靜態方法: 只供介面直接呼叫,實現類繼承不了
public static void method3(){
System.out.println("靜態方法method3");
method5();
}
// 介面中的私有方法: 只能在介面中直接呼叫,實現類繼承不了
private void method4(){// 只能在介面的預設方法中呼叫
// 方法體
method5();
}
private static void method5(){//
// 方法體
}
}
實現類:
public class ImpA implements IA{
/* @Override
public void method2() {
}*/
@Override
public void method1() {
System.out.println("重寫介面中的method1抽象方法");
}
}
測試類:
public class Test {
public static void main(String[] args) {
/*
介面中成員的訪問特點:
介面中的常量: 主要是供介面直接使用
介面中的抽象方法: 供實現類重寫的
介面中的預設方法: 供實現類繼承的(實現類中可以直接呼叫,實現類物件也可以直接呼叫)
介面中的靜態方法: 只供介面直接呼叫,實現類繼承不了
介面中的私有方法: 只能在介面中直接呼叫,實現類繼承不了
*/
System.out.println(IA.NUM);// 10
// 建立實現類物件,訪問NUM常量
ImpA ia = new ImpA();
System.out.println(ia.NUM);// 10
// 呼叫method2方法
ia.method2();
// 通過介面名呼叫介面中的靜態方法
IA.method3();
//ia.method3();// 編譯報錯,
}
}
介面和介面的關係
- 公有靜態常量的衝突
- 公有抽象方法的衝突
- 公有預設方法的衝突
- 公有靜態方法的衝突
- 私有方法的衝突
講解
公有靜態常量的衝突
- 實現類不繼承衝突的變數
interface IA{
public static final int a = 10;
public static final int b= 20;
}
interface IB{
public static final int a = 30;
}
class Zi implements IA,IB{
//只繼承了b,沒有繼承a,因為a衝突了
}
public class Demo {
public static void main(String[] args) {
Zi z = new Zi();
// System.out.println(z.a);//編譯錯誤
System.out.println(z.b);
}
}
公有抽象方法的衝突
- 實現類只需要重寫一個
interface IA{
public void show();
}
interface IB{
public void show();
}
class Zi implements IA,IB{
@Override
public void show() {//子類只需要重寫一個show()即可
System.out.println("子類的show()...");
}
}
public class Demo {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
公有預設方法的衝突
- 實現類必須重寫一次最終版本
interface IA{
public default void show(){
System.out.println("IA");
}
}
interface IB{
public default void show(){
System.out.println("IB");
}
}
class Zi implements IA,IB{
@Override
public void show() {//必須重寫一次的show()
System.out.println("Zi的show()....");
}
}
public class Demo {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
公有靜態方法的衝突
-
靜態方法是直接屬於介面的,不能被繼承,所以不存在衝突
interface IA{ public static void show(){ System.out.println("IA"); } } interface IB{ public static void show(){ System.out.println("IB"); } } class Zi implements IA,IB{ } public class Demo { public static void main(String[] args) { Zi z = new Zi(); z.show();//編譯錯誤,show()不能被繼承。 } }
私有方法的衝突
- 私有方法只能在本介面中直接使用,不存在衝突
介面與介面之間的關係
- 介面多繼承時的衝突情況
- 公有靜態常量的衝突
- 公有抽象方法的衝突
- 公有預設方法的衝突
- 公有靜態方法和私有方法的衝突
講解
介面與介面之間的關係
-
介面可以“繼承”自另一個“介面”,而且可以“多繼承”。
interface IA{} interface IB{} interface IC extends IA,IB{//是“繼承”,而且可以“多繼承” }
介面繼承介面的衝突情況
公有靜態常量的衝突
interface IA{
public static final int a = 10;
public static final int b = 30;
}
interface IB{
public static final int a = 20;
}
interface IC extends IA,IB{//沒有繼承a
}
//測試:
main(){
System.out.println(IC.a);//錯誤的
}
公有抽象方法衝突
interface IA{
public void show();
}
interface IB{
public void show();
}
interface IC extends IA,IB{//IC只繼承了一個show()
}
class Zi implements IC{
//重寫一次show()
public void show(){
}
}
公有預設方法的衝突
interface IA{
public default void d1(){
}
}
interface IB{
public default void d1(){
}
}
interface IC extends IA,IB{//必須重寫一次d1()
public default void d1(){
}
}
公有靜態方法和私有方法
- 不衝突,因為靜態方法是直接屬於介面的,只能使用介面直接訪問,而私有方法只能在介面中訪問,也沒有衝突
實現類繼承父類又實現介面時的衝突
- 公有靜態常量的衝突
- 公有抽象方法的衝突
- 公有預設方法的衝突
- 公有靜態方法
- 私有方法的衝突
講解
父類和介面的公有靜態常量的衝突
class Fu{
public static final int a = 10;
}
interface IA{
public static final int a = 20;
}
class Zi extends Fu implements IA{//沒有繼承a變數
}
public class Demo {
public static void main(String[] args) {
System.out.println(Zi.a);//編譯錯誤
}
}
父類和介面的抽象方法衝突
abstract class Fu{
public abstract void show();
}
interface IA{
public void show();
}
class Zi extends Fu implements IA{// 必須重寫
}
//測試:
main(){
Zi z = new Zi();
z.show();//a
}
父類和介面的公有預設方法的衝突
class Fu{
public void show(){
System.out.println("a");
}
}
interface IA{
public default void show(){
System.out.println("b");
}
}
class Zi extends Fu implements IA{
}
//測試:
main(){
Zi z = new Zi();
z.show();//a
}
父類和介面的公有靜態方法
class Fu{
public static void show(){
System.out.println("fu...");
}
}
interface IA{
public static void show(){
System.out.println("IA...");
}
}
class Zi extends Fu implements IA{//只繼承了"父類"的靜態方法,沒有繼承介面的靜態方法
}
public class Demo {
public static void main(String[] args) {
Zi.show();//fu…
}
}
父類和介面的私有方法
- 不存在衝突
實操--抽象類和介面的練習
需求:
通過例項進行分析和程式碼演示抽象類和介面的用法。
1、舉例:
犬: --->父類 抽象類
行為:吼叫;吃飯; ----- 抽象類
緝毒犬: ---> 繼承犬類
行為:吼叫;吃飯;緝毒;
緝毒介面:
緝毒的功能(抽象方法)
- 如果所有子類都有的功能: 通用功能(非抽象方法),非通用功能(抽象方法),定義到父類中
- 如果某個功能是一個類額外增加的,那麼就可以把這個額外的功能定義到介面中,再這個類去實現
分析:
由於犬分為很多種類,他們吼叫和吃飯的方式不一樣,在描述的時候不能具體化,也就是吼叫和吃飯的行為不能明確。當描述行為時,行為的具體動作不能明確,這時,可以將這個行為寫為抽象行為,那麼這個類也就是抽象類。
可是有的犬還有其他額外功能,而這個功能並不在這個事物的體系中 , 例如 : 緝毒犬。緝毒的這個功能有好多種動物都有 , 例如 : 緝毒豬 , 緝毒鼠。我們可以將這個額外功能定義介面中 ,讓緝毒犬繼承犬且實現緝毒介面 , 這樣緝毒犬既具備犬科自身特點也有緝毒功能。
- 額外的功能---> 在介面中定義,讓實現類實現
- 共性的功能---> 在父類中定義,讓子類繼承
實現:
//定義緝毒介面 緝毒的片語(anti-Narcotics)比較長,在此使用拼音替代
interface JiDu{
//緝毒
public abstract void jiDu();
}
//定義犬科,存放共性功能
abstract class Dog{
//吃飯
public abstract void eat();
//吼叫
public abstract void roar();
}
//緝毒犬屬於犬科一種,讓其繼承犬科,獲取的犬科的特性,
//由於緝毒犬具有緝毒功能,那麼它只要實現緝毒介面即可,這樣即保證緝毒犬具備犬科的特性,也擁有了緝毒的功能
class JiDuQuan extends Dog implements JiDu{
public void jiDu() {
}
void eat() {
}
void roar() {
}
}
//緝毒豬
class JiDuZhu implements JiDu{
public void jiDu() {
}
}
小結:
- 額外的功能---> 在介面中定義,讓實現類實現
- 如果可以確定的通用功能,使用預設方法
- 如果不能確定的功能,使用抽象方法
- 共性的功能---> 在父類中定義,讓子類繼承
- 如果可以確定的通用功能,使用預設方法
- 如果不能確定的功能,使用抽象方法