首頁/ 汽車/ 正文

「Java SE」抽象類和介面

什麼是抽象類?

在面向物件的概念中,所有的物件都是透過類來描繪的,但是反過來,並不是所有的類都是用來描繪物件的,如果一個類中沒有包含足夠的資訊來描繪一個具體的物件,那麼這樣的類稱為抽象類。

如何構造出一個抽象類?

在Java中,一個類如果被 abstract 修飾稱為抽象類,抽象類中被 abstract 修飾 的方法稱為抽象方法,抽象方法不用給出具體的實現體。

//抽象類public abstract class Shape { protected double area; abstract public void draw();//抽象方法 public double getarea(){//普通方法 return area; }}

注:抽象類也是類,內部可以包含普通方法和屬性,甚至構造方法。

抽象類有哪些特性?

1。 抽象類不能直接例項化物件

2。抽象方法不能是 private 的

注意:抽象方法沒有加訪問限定符時,預設是public。

3。 抽象方法不能被final和static修飾,因為抽象方法要被子類重寫

4。 抽象類必須被繼承,並且繼承後子類要重寫父類中的抽象方法,否則子類也是抽象類,必須要使用 abstract 修飾

5。 抽象類中不一定包含抽象方法,但是有抽象方法的類一定是抽象類

6。 抽象類中可以有構造方法,供子類建立物件時,初始化父類的成員變數

7。抽象類本身不能被例項化, 要想使用, 只能建立該抽象類的子類。,然後讓子類重寫抽象類中的抽象方法。

問題:普通類也能被繼承,普通方法也能被重寫,為什麼要用抽象類和抽象方法呢?

通常在使用抽象類的場景中實際工作不應該由父類完成, 而應由子類完成。 那麼此時如果不小心誤用成父類了, 使用普通類編譯器是不會報錯的。但是父類是抽象類由於抽象類不能例項化就會報錯, 讓我們儘早發現問題。

什麼是介面?

Java介面是一系列方法的宣告,是一些方法特徵的集合 ,一個介面只有方法的特徵沒有方法的實現 ,因此這些方法可以在不同的地方被不同的類實現,而這些實現可以具有不同的行為(功能)。

介面可以理解為一種特殊的類,裡面全部是由全域性常量和公共的抽象方法所組成。 介面是解決Java無法使用多繼承的一種手段 ,但是介面在實際中更多的作用是制定標準的。或者我們可以直接把介面理解為100%的抽象類, 即介面中的方法必須全部是抽象方法。(jdk1。8前)

如何實現一個介面?

介面的定義格式與定義類的格式基本相同,將class關鍵字換成 interface 關鍵字 ,就定義了一個介面。

//介面的定義格式與定義類的格式基本相同,將class關鍵字換成 interface 關鍵字,就定義了一個介面。public interface USB { public abstract void method1();// public abstract 是固定搭配,可以不寫 void method2();// public abstract 是固定搭配,可以不寫}

注意:介面不能直接使用,必須要有一個“實現類”來“實現”該介面,實現介面中的所有抽象方法

public class 類名稱 implements 介面名稱{//……。}

注意:子類和父類之間是 extends 繼承關係,類與介面之間是 implements 實現關係。

下面實現一個簡單的USB介面:

public interface USB { void OpenDevice(); void CloseDevice();}public class Mouse implements USB{ @Override public void OpenDevice() { System。out。println(“開啟滑鼠”); } @Override public void CloseDevice() { System。out。println(“關閉滑鼠”); } public void Click(){ System。out。println(“滑鼠點選”); }}public class KeyBoard implements USB{ @Override public void OpenDevice() { System。out。println(“開啟鍵盤”); } @Override public void CloseDevice() { System。out。println(“關閉鍵盤”); } public void Input(){ System。out。println(“鍵盤輸入”); }}public class Computer implements USB{ @Override public void OpenDevice() { System。out。println(“開啟電腦”); } @Override public void CloseDevice() { System。out。println(“關閉電腦”); } public void UseDevice(USB usb){ usb。OpenDevice(); if(usb instanceof Mouse){ Mouse mouse=(Mouse) usb; mouse。Click(); } else if (usb instanceof KeyBoard) { KeyBoard keyBoard=(KeyBoard) usb; keyBoard。Input(); } usb。CloseDevice(); }}

「Java SE」抽象類和介面

介面有哪些特性?

1。 介面型別是一種引用型別,但是不能直接new介面的物件。

2。 介面中每一個方法都是public的抽象方法, 即介面中的方法會被隱式的指定為 public abstract(只能是public abstract,其他修飾符都會報錯。

3。 介面中的方法是不能在介面中實現的,只能由實現介面的類來實現。

4。 重寫介面中方法時,不能使用default訪問許可權修飾。

5。 介面中可以含有變數,但是介面中的變數會被隱式的指定為 public static final 變數。

6。 介面中不能有靜態程式碼塊和例項程式碼塊和構造方法。

7。 介面雖然不是類,但是介面編譯完成後位元組碼檔案的字尾格式也是。class

8。 如果類沒有實現介面中的 所有的抽象方法 ,則類必須設定為抽象類

9。 jdk8中:介面中還可以包含default方法

在Java中,類和類之間是單繼承的,一個類只能有一個父類,即Java中不支援多繼承,但是一個類可以實現多個介面。

如何去實現多個介面?

//定義一個動物類class Animal{ protected String name; public Animal(String name){ this。name=name; }}//下面提供一些有關動物的介面interface IRunning{ void run();}interface ISwimming{ void swim();}interface Iflying{ void fly();}//貓會跑class Cat extends Animal implements IRunning{ public Cat(String name) { super(name); } @Override public void run() { System。out。println(name+“正在跑”); }}//魚會游泳class Fish extends Animal implements ISwimming{ public Fish(String name) { super(name); } @Override public void swim() { System。out。println(name+“正在游泳”); }}//天鵝會跑,會游泳,會飛class Swan extends Animal implements IRunning,ISwimming,Iflying{ public Swan(String name) { super(name); } @Override public void run() { System。out。println(name+“正在跑”); } @Override public void swim() { System。out。println(name+“正在游泳”); } @Override public void fly() { System。out。println(name+“正在飛”); }}

注意:一個類實現多個介面時,每個介面中的抽象方法都要實現,否則類必須設定為抽象類。

上面的程式碼展示了 Java 面向物件程式設計中最常見的用法: 一個類繼承一個父類, 同時實現多種介面。

時刻牢記多型的好處, 讓程式猿忘記型別。 有了介面之後, 類的使用者就不必關注具體型別,

而只關注某個類是否具備某種能力。

public static void walk(IRunning running){ running。run(); }

在這個 walk 方法內部, 我們並不關注到底是哪種動物, 只要引數是會跑的, 就行

public class Test { public static void walk(IRunning running){ running。run(); } public static void main(String[] args) { Cat cat=new Cat(“咪咪”); walk(cat); }}

「Java SE」抽象類和介面

class Robot extends Animal implements IRunning{ public Robot(String name){ super(name); } @Override public void run() { System。out。println(name + “正在跑”); }}public class Test { public static void walk(IRunning running){ running。run(); } public static void main(String[] args) { Cat cat=new Cat(“咪咪”); walk(cat); walk(new Robot(“大白”)); }}

「Java SE」抽象類和介面

在Java中,類和類之間是單繼承的,一個類可以實現多個介面,介面與介面之間可以多繼承。即:用介面可以達到多繼承的目的。

如何實現介面間的繼承

//把IRunning,ISwimming,Iflying全部繼承到IAction上interface IAction extends IRunning,ISwimming,Iflying{}class Swan extends Animal implements IAction { public Swan(String name) { super(name); } @Override public void run() { System。out。println(name + “正在跑”); } @Override public void swim() { System。out。println(name + “正在游泳”); } @Override public void fly() { System。out。println(name + “正在飛”); }}public class Test { public static void main(String[] args) { Swan swan=new Swan(“白白”); swan。run(); swan。swim(); swan。fly(); }}

「Java SE」抽象類和介面

介面間的繼承相當於把多個介面合併在一起。

抽象類和介面的區別:

(1)抽象類可以有構造方法,介面中不能有構造方法。

(2)抽象類中可以有普通成員變數,介面中沒有普通成員變數。

(3)抽象類中可以包含靜態方法,介面中不能包含靜態方法。

(4) 一個類可以實現多個介面,但只能繼承一個抽象類。

(5)介面可以被多重實現,抽象類只能被單一繼承。

(6)如果抽象類實現介面,則可以把介面中方法對映到抽象類中作為抽象方法而不必實現,而在抽象類的子類中實現介面中方法。

介面和抽象類的相同點:

(1) 都可以被繼承。

(2) 都不能被例項化。

(3) 都可以包含方法宣告。

(4) 派生類必須實現未實現的方法。

何為Object類?

Object是Java預設提供的一個類。Java裡面除了Object類,所有的類都是存在繼承關係的。預設會繼承Object父類。即所有類的物件都可以使用Object的引用進行接收。

public class Test2 { public static void main(String[] args) { fun1(new A()); fun1(new B()); } public static void fun1(Object object){ System。out。println(object); }}class A{}class B{}

「Java SE」抽象類和介面

利用Object類獲取物件資訊

如果要列印物件中的內容,可以直接 重寫Object類中的toString()方法

class Animal{ protected String name; public Animal(String name){ this。name=name; } @Override public String toString() { return “Animal{” + “name=‘” + name + ’\‘’ +//可以修改 ‘}’; }}

利用Object類進行物件比較

在Java中,==進行比較時:

a。如果==左右兩側是基本型別變數,比較的是變數中值是否相同

b。如果==左右兩側是引用型別變數,比較的是引用變數地址是否相同

c。如果要比較物件中內容,必須

重寫Object中的equals方法 ,因為 equals方法 預設也是按照地址比較的

//Object類中的equals方法public boolean equals(Object obj) {return (this == obj); // 使用引用中的地址直接來進行比較}public class Test { public static void main(String[] args) { Cat cat1=new Cat(“小白”,5); Cat cat2=new Cat(“小白”,5); int a=10; int b=10; System。out。println(a==b); System。out。println(cat1==cat2); System。out。println(cat1。equals(cat2)); }}class Cat{ private String name; private int age; public Cat(String name,int age){ this。name=name; this。age=age; }}

「Java SE」抽象類和介面

重寫equals方法後,然後比較:

@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o。getClass()) return false; Cat cat = (Cat) o; return age == cat。age && name。equals(cat。name); }

「Java SE」抽象類和介面

結論:比較物件中內容是否相同的時候,一定要重寫equals方法。

hashcode方法

hashcode方法用來確定物件在記憶體中儲存的位置是否相同

事實上hashCode() 在散列表中才有用,在其它情況下沒用。在散列表中hashCode() 的作用是獲取物件的雜湊碼,進而確定該物件在散列表中的位置。

我們認為兩個名字相同,年齡相同的物件,將儲存在同一個位置,如果不重寫hashcode()方法

public class Test { public static void main(String[] args) { Cat cat1=new Cat(“小白”,5); Cat cat2=new Cat(“小白”,5); System。out。println(cat1。hashCode()); System。out。println(cat2。hashCode()); }}class Cat{ private String name; private int age; public Cat(String name,int age){ this。name=name; this。age=age; }}

「Java SE」抽象類和介面

注意事項:兩個物件的hash值不一樣

像重寫equals方法一樣,我們也可以重寫hashcode()方法。此時我們再來看看。

import java。util。Objects;public class Test { public static void main(String[] args) { Cat cat1=new Cat(“小白”,5); Cat cat2=new Cat(“小白”,5); System。out。println(cat1。hashCode()); System。out。println(cat2。hashCode()); }}class Cat{ private String name; private int age; public Cat(String name,int age){ this。name=name; this。age=age; } @Override public int hashCode() { return Objects。hash(name, age); }}

「Java SE」抽象類和介面

雜湊值一樣。

所以必要情況下我們也要 重寫hashcode()方法。

相關文章

頂部