面向對象03 10.抽象類 abstract修飾符可以用來修飾方法也可以修飾類,如果修飾方法,那麼該方法就是抽象方法;如果修飾類,那麼該類就是抽象類 抽象類中可以沒有抽象方法,但是有抽象方法的類一定要聲明為抽象類 抽象類,不能使用new關鍵字來創建對象,它是用來讓子類繼承的 抽象方法,只有方法的聲明 ...
面向對象03
10.抽象類
- abstract修飾符可以用來修飾方法也可以修飾類,如果修飾方法,那麼該方法就是抽象方法;如果修飾類,那麼該類就是抽象類
- 抽象類中可以沒有抽象方法,但是有抽象方法的類一定要聲明為抽象類
- 抽象類,不能使用new關鍵字來創建對象,它是用來讓子類繼承的
- 抽象方法,只有方法的聲明,沒有方法的實現,它是用來讓子類實現的
- 子類繼承抽象類,那麼就必須要實現抽象類沒有實現的抽象方法,否則該子類也要聲明為抽象類
例子1:
類A繼承類Action,系統提示類'A'必須被聲明為抽象類或者實現在類'Action'中的doSomething()方法
抽象總結:
- 不能new抽象類,只能靠子類去實現它;約束!
- 抽象類可以寫普通的方法
- 抽象方法必須在抽象類中
抽象的抽象:約束~
思考題:
- 抽象類不能new對象,那麼它存在構造器嗎?
- 抽象類存在的意義是什麼?
答:1. 抽象類一定有而且是必須有構造器,是供子類創建對象時,初始化父類成員使用的。
理解:子類的構造器中,有預設的super()需要訪問父類構造器。
2. 代碼復用,提高開發效率
11.介面
extends 單繼承
介面可以多繼承
-
普通類:只有具體實現
-
抽象類:具體實現和規範(抽象方法)都有!
-
介面類:只有規範,自己無法寫方法--->專業的約束!實現約束和實現分離:面向介面編程
-
介面的本質是契約,就像法律一樣。制定好大家都必須遵守。
-
OO的精髓,是對對象的抽象,最能體現這一點的就是介面。為什麼我們討論涉及模式都只針對具備了抽象能力的語言(比如C++\java\C#等),就是因為涉及模式所研究的實際上就是如何合理地去抽象。
-
聲明類的關鍵字是class,聲明介面的關鍵字是interface
例子
介面中的所有定義其實都是抽象的 ,預設加上public abstract
介面中定義的屬性都是常量,預設加上public static final
package li.oop.demo09;
//interface 定義的關鍵字,介面都需要有實現類
public interface UserService {
//介面中的所有定義其實都是抽象的 ,預設都是public abstract
// void run(String name);在介面類中等同於:public abstract void run(String name);
void run(String name);
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
package li.oop.demo09;
public interface TimeService {
void time();
}
實現類的命名規範是:介面類名+Impl,實現了介面的類,就需要重寫介面中的方法
如下:UserServiceImpl實現類通過介面實現了多繼承(UserService,TimeService)
package li.oop.demo09;
//抽象類:extends
//實現類 可以實現介面 implement :實現介面
//實現了介面的類,就需要重寫介面中的方法
//多繼承~利用介面實現多繼承
public class UserServiceImpl implements UserService,TimeService{
@Override
public void run(String name) {
}
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void time() {
}
}
介面的作用:
- 約束
- 定義一些方法,讓不同的人實現
- 方法都是public abstract
- 屬性都是public static final
- 介面不能被實例化~,介面中沒有構造方法
- 一個implement可以實現多個介面
- 必須重寫介面中的方法
12.N種內部類
- 內部類就是在一個類的內部再定義一個類,比如,A類中定義一個B類,那麼B類對A類來說就稱為內部類,而A類相對B類來說就是外部類了。
內部類:
-
成員內部類
-
靜態內部類
-
局部內部類
-
匿名內部類
例子1:成員內部類
package li.oop.demo10;
public class Outer {
private int id = 10;
private void out(){
System.out.println("這是外部類的方法");
}
public class Inner{
public void in(){
System.out.println("這是內部類的方法");
}
//獲得外部類的私有屬性
public void getID(){
System.out.println(id);
}
}
}
package li.oop;
import li.oop.demo10.Outer;
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
//通過外部類來實例化內部類
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getID();//獲得了外部類的私有屬性
}
}
例子2:靜態內部類
package li.oop.demo10;
public class Outer {
private int id=10;
private void out(){
System.out.println("這是外部類的方法");
}
//靜態內部類
public static class Inner{
public void in(){
System.out.println("這是內部類的方法");
}
}
}
例子3:局部內部類
一個java文件可以有多個class類,但是只能有一個public class在最外層
局部內部類可以在方法中定義
package li.oop.demo10;
public class Outer {
public void method(){
//局部內部類
class Inner{
public void in(){
}
}
}
}
例子4:匿名內部類
package li.oop.demo10;
public class Test {
public static void main(String[] args) {
//正常
Apple apple = new Apple();
//匿名內部類
//沒有名字初始化類,不用將實例保存到變數中~
new Apple().eat();
//在這裡可以直接重寫介面UserService的方法,但是沒有實現類也是沒有名字,也是匿名類
UserService userService = new UserService() {
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
interface UserService{
void hello();
}
異常機制
什麼是異常?
程式運行過程中由外部問題(如硬體錯誤、輸入錯誤)所導致的異常事件,我們稱為異常,英文名是:Exception,意思是例外。
(在Java等面向對象的編程語言中)異常本身是一個對象,產生異常就是產生了一個異常對象。
簡單分類:
-
檢查性異常:最具代表的檢查性異常是用戶錯誤或者問題引起的異常,這是程式員無法預見的
例如要打開一個不存在的文件時,一個異常就發生了,這些異常在編譯時不能被簡單地忽略
-
運行時異常:運行時異常是可能被程式員避免的異常。與檢查性異常相反,運行時異常可以在編譯時被忽略
-
錯誤(Error):錯誤不是異常,而是脫離程式員控制的問題。錯誤在代碼中通常被忽略。例如:當棧溢出時,一個錯誤就發生了,它們在編譯時也檢查不到的
1.異常體繫結構
- Java把異常當做對象來處理,並定義一個基類java.lang.Throwable作為所有異常的超類
- 在Java API中已經定義了許多異常類,這些類分屬兩大類,錯誤
Error
和異常Exception
2.Error
- Error類對象由Java虛擬機生成並拋出,大多數錯誤與代碼編寫者所執行的操作無關
- Java虛擬機運行錯誤(Virtual MachineError),當JVM不再有繼續執行操作所需的記憶體資源時,將出現OutOfMemoryError。這些異常發生時,Java虛擬機(JVM)一般會選擇線程終止。
- 還有發生在虛擬機試圖執行應用時,如類定義錯誤(NoClassDefFoundError)、鏈接錯誤(LinkageError)。這些錯誤都是不可查的,因為它們在應用程式的控制和處理能力之外,而且絕大多數是程式運行時不允許出現的狀況。
3.Exception
-
在Exception分支中有一個重要的子類RuntimeException(運行時異常)
-
ArrayIndexOutOfBoundsException(數組下標越界)
-
NullPointerException(空指針異常)
-
ArithmeticExcption(算數異常)
-
MissingResourceException(丟失資源)
-
ClassNotFoundException(找不到類)
等異常,這些異常是不檢查異常,程式中可以選擇捕獲處理,也可以不處理。
-
-
這些異常一般是由程式邏輯錯誤引起的,程式應該從邏輯角度儘可能避免這類異常的發生
-
Error和Exception的區別:Error通常是災難性的致命性的錯誤,是程式無法控制和處理的,當出現這些異常時,Java虛擬機(JVM)一般會去選擇終止線程;Exception通常情況下是可以被程式處理的,並且在程式中應該儘可能地去處理這些異常。
4.捕獲和拋出異常
- 異常處理五個關鍵字
- try、catch、finally、throw、throws
例子:try catch
package li.exception;
public class Test {
public static void main(String[] args) {
int a = 1;
int b = 0;
//假設要捕獲多個異常,需要從小到大去捕獲
try {//try監控區域
System.out.println(a/b);
}catch (Error e){//catch(想要捕獲的異常類型)
System.out.println("Error");
}catch(Exception e){
System.out.println("Exception");
}catch(Throwable e){
System.out.println("Throwable");
} finally{//無論是否有異常都會執行finally 處理善後工作
System.out.println("finally");
}
//try catch是配套的,finally 可以不要
}
}
快捷鍵:Ctrl+Alt+T
選中代碼語句,點擊快捷鍵Ctrl+Alt+t可以快速生成try catch語句
5.自定義異常及經驗小結
- 使用Java內置的異常類可以描述在編程時出現的大部分異常情況。除此之外,用戶還可以自定義異常。用戶自定義異常類,只需繼承Exception即可。
- 在程式中使用自定義異常類,大體可以分為以下幾個步驟:
- 創建自定義異常類
- 在方法中通過throw關鍵字拋出異常對象
- 如果在當前拋出異常的方法中處理異常,可以使用try-catch語句捕獲並處理;否則在方法的聲明處通過throws關鍵字指明要拋出給方法調用者的異常,繼續進行下一步操作
- 在出現異常方法的調用者中捕獲並處理異常
package li.exception.demo02;
//自定義的異常類 只需繼承Exception類即可
public class MyException extends Exception {
//傳遞數字>10
private int detail;
public MyException(int a){
this.detail = a;
}
//toString:異常的列印信息
@Override
public String toString() {
return "MyException{"+ detail+"}";
}
}
package li.exception.demo02;
public class Test {
//可能會存在異常的方法
static void test(int a) throws MyException {
System.out.println("傳遞的參數為"+a);
if (a >10) {
throw new MyException(a);//拋出異常
}
System.out.println("OK");
}
public static void main(String[] args) {
try {
test(12);
} catch (MyException e) {
System.out.println("MyException=>"+e);
}
}
}
實際應用中的經驗總結:
- 處理運行時異常時,採用邏輯去合理規避同時輔助try-catch處理
- 在多重catch塊後面,可以加上一個catch(Exception)來處理可能會被遺漏的異常
- 對於不確定的代碼,也可以加上try-catch,處理潛在的異常
- 儘量去處理異常,切記只是簡單地調用printStackTrace()去列印輸出
- 具體如何處理異常,應該根據不同的業務需求和異常類型去決定
- 儘量添加finally語句塊去釋放占用的資源