泛型、異常岛都、lambda表達式

泛型

可以在類和方法中預(yù)支地使用未知的類型律姨,一般在創(chuàng)建對象時,將位置類型確定為具體類型臼疫,當(dāng)沒有指定泛型時候择份, 默認(rèn)類型是Obj類型。

使用泛型的好處

  • 將運行時時期的異常烫堤,轉(zhuǎn)移到了編譯時期變成了編譯失敗
  • 避免了類型強轉(zhuǎn)的麻煩
public class GenericDemo {
    public static void main(String[] args) {
        Collection<String> list = new ArrayList<>();
        list.add("abc");
        list.add("def");
        // list.add(5); 集合已經(jīng)明確了具體元素存放的類型
        // 已經(jīng)明確了類型荣赶,在使用迭代器的時候,迭代器也同樣知道遍歷元素的具體類型
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            String str = iterator.next();
            // 使用iterator()在這里可以直接獲取String類型
            System.out.println(str.length());
        }

        System.out.println(list);

    }
}

泛型的定義與使用

泛型鸽斟,用來靈活的將數(shù)據(jù)類型應(yīng)用到不同類讯壶、方法、接口當(dāng)中湾盗。將數(shù)據(jù)類型作為參數(shù)進行傳遞。
格式

修飾符  class 類名<代表泛型的變量>{
}

使用泛型:在創(chuàng)建對象的時候確定泛型
自定義泛型

public class MyGenericClass<MVP> {
    // 沒有MVP類型立轧, 在這里代表未知的一種數(shù)據(jù)類型
    // 未來傳遞什么就是什么類型
    private MVP mvp;

    public MVP getMvp() {
        return mvp;
    }

    public void setMvp(MVP mvp) {
        this.mvp = mvp;
    }
}

測試

public class TestGenericDemo {
    public static void main(String[] args) {
        // 創(chuàng)建一個泛型為String類
        MyGenericClass<String> my = new MyGenericClass<>();
        my.setMvp("哈登哥");
        String mvp = my.getMvp();
        System.out.println(mvp);

        MyGenericClass<Integer> my2 = new MyGenericClass<>();
        my2.setMvp(13);
        Integer mvp2 = my2.getMvp();
        System.out.println(mvp2);

    }
}

含有泛型的方法

格式:

修飾符 <代表泛型的變量> 返回值類型 方法名(參數(shù)列表){
}

舉個栗子

public class MyGenericMethod {
    public <MVP>void show(MVP mvp){
        System.out.println(mvp.getClass());
    }
    public <MVP>  MVP show2(MVP mvp){
        return mvp;
    }
}

測試

public class TestGenericDemo2 {
    public static void main(String[] args) {
        MyGenericMethod mgm = new MyGenericMethod();
        // 在調(diào)用方法時格粪, 確定泛型的類型
        mgm.show("aaa");
        mgm.show(123);
        mgm.show(12.45);

    }
}

含有泛型的接口

格式

修飾符  interface 接口名<泛型>{
}

舉個栗子

public interface MyGenericInterface<E> {
    public abstract void add(E e);
    public abstract E getE();

}

實現(xiàn)類在定義類的時候確定泛型的類型

public class MyGenericImpl implements MyGenericInterface<String> {

    @Override
    public void add(String s) {

    }

    @Override
    public String getE() {
        return null;
    }
}

上面泛型 E 的值就是String類型

始終不確定泛型的類型,直到創(chuàng)建對象的時候氛改,確定泛型的類型

public class MyGenericImpl2<E> implements MyGenericInterface<E> {
    @Override
    public void add(E e) {

    }

    @Override
    public E getE() {
        return null;
    }
}

確定泛型

public class TestGenericDemo2 {
    public static void main(String[] args) {
        MyGenericImpl2<String> impl2 = new MyGenericImpl2<>();
        ArrayList<Object> list = new ArrayList<>();
        impl2.add("hehe");

    }
}

泛型通配符

常用的通配符含義

  • E Element(在集合中使用)
  • T Type(Java類)
  • K Key(鍵)
  • V Value (值)
  • N Number(數(shù)值類型)
  • 帐萎? 表示不確定的Java類型
    <?> 表示不確定的Java類型胜卤, 一旦使用<疆导?> 只能使用Object類中的共性方法
基本使用

<?> 不知道到使用什么類型來接受的時候

public class TestGenericDemo3 {
    public static void main(String[] args) {
        Collection<Integer> list1 = new ArrayList<>();
        Collection<String> list2 = new ArrayList<>();
        getElement(list1);
        getElement(list2);
    }
    public static void getElement(Collection<?> coll){
        // <?>代表可以接受任意類型
    }
}

高級應(yīng)用— 受限類型

在Java中的泛型可以指定一個泛型的上限和下限

泛型的上限:

格式  : 類型名稱<葛躏? extends 類 > 對象名稱
意義 : 只能接受該類型及其子類

泛型的下限:

格式  : 類型名稱<澈段? super 類 > 對象名稱
意義 : 只能接受該類型及其父類

舉個栗子:現(xiàn)在已知Object類、String類舰攒、Number類败富、Integer類,其中Number類是Integer類的父類

public class TestGenericDemo4 {
    public static void main(String[] args) {
        Collection<Integer> list1 = new ArrayList<>();
        Collection<String> list2 = new ArrayList<>();
        Collection<Number> list3 = new ArrayList<>();
        Collection<Object> list4 = new ArrayList<>();
        getElement1(list1);
        getElement1(list2);// 報錯
        getElement1(list3);
        getElement1(list4); // 報錯

        getElement2(list1)// 報錯
        getElement2(list2)// 報錯
        getElement2(list3)// 報錯
        getElement2(list4)// 報錯
    }
    // 泛型的上限 此時泛型摩窃?必須是Number類型或者Number類型子類
    public static void getElement1(Collection<? extends Number> coll){
    }
    // 泛型的下限 此時泛型兽叮?必須是Number類型或者Number類型父類
    public static void getElement2(Collection<? super Number> coll){
    }
}

異常

異常: 指的是程序在執(zhí)行過程中,出現(xiàn)的非正常的情況,最終會導(dǎo)致JVM的非正常停止
在Java中異常本身是一個類鹦聪, 產(chǎn)生異常就是創(chuàng)建異常對象并且拋出了一個異常對象账阻。Java處理異常的方式是中斷處理

異常不是語法錯誤, 語法錯誤是無法通過編譯

異常體系

異常的根類是 java.lang.Throwable泽本,兩個子類 java.lang.Error和 java.lang.Exception
平時所說的異常是java.lang.Exception
Throwable體系:

  • Error: 嚴(yán)重錯誤淘太,無法通過處理的錯誤,好比絕癥
  • Exception表示異常观挎, 異常產(chǎn)生后程序員可以通過代碼的方式糾正琴儿,使程序繼續(xù)運行,是必須處理的嘁捷。好比感冒發(fā)燒
常用方法
  • public void printStackTrace()造成; 打印異常的詳細信息并且輸出到控制臺中
  • public String getMessage(); 獲取發(fā)生異常的原因

舉個栗子

public class Demo1 {
    public static void main(String[] args) {
        int[] arr = {1, 2, 4};
        System.out.println(arr[3]);
    }
}

image

異常的分類

  • 編譯時期異常: 如果沒有處理,編譯失斝巯(如日期格式化異常)
  • 運行時期異常: 在運行時期檢查異常 (如數(shù)學(xué)異常)


    image

異常處理

Java中異常處理的五個關(guān)鍵字:try晒屎、catch、finally缓升、throw鼓鲁、throws

拋出異常throw

  • 創(chuàng)建一個異常對象。封裝一些提示信息(信息可以自己編寫)
  • 通過throw將這個異常對象告知調(diào)用者港谊,throw用在方法內(nèi)骇吭,用來拋出一個異常對象,將這個異常對象傳遞到調(diào)用者處歧寺,并結(jié)束當(dāng)前方法的執(zhí)行燥狰。
  • 格式
throw new 異常類名(參數(shù));

舉個栗子

throw new NullPointerException("要訪問的arr數(shù)組不存在");
throw new ArrayIndexOutOfBoundsException("數(shù)組越界了斜筐,兄弟");

public class Demo2 {
    public static void main(String[] args) {
        int[] arr = {1, 2, 4, 5};
        int index = 4;
        int element = getElement(arr, index);
        System.out.println(element);
    }
    public static int getElement(int[] arr, int index){
        // 判斷
        if (index < 0 || index> arr.length-1){
            throw new ArrayIndexOutOfBoundsException("數(shù)組越界了龙致,兄弟");
        }
       return arr[index];
    }
}

聲明異常throws

聲明異常:將為題標(biāo)識出來, 報告給調(diào)用者顷链, 如果方法內(nèi)通過throw 拋出了編譯時異常目代, 而沒有捕獲處理,那么必須通過throws進行聲明嗤练,讓調(diào)用者去處理

修飾符 <代表泛型的變量> 返回值類型 方法名(參數(shù)列表) throws 異常類1榛了, 異常類2 {
}

舉個栗子

public class Demo3 {
    public static void main(String[] args) throws ParseException {
        String s = "1994-12";
        timeFormat(s);

    }
    public static void timeFormat(String str) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Date date = sdf.parse(str);
        System.out.println(date);
    }
}

捕獲異常try catch

如果異常出現(xiàn)會立刻終止程序, 所以我們得處理異常

  1. 聲明拋出, 由調(diào)用者來處理(throws)
  2. 使用try catch語句塊來處理異常
    try catch的方式就是捕獲異常
    格式:
try {
    編寫可能會出現(xiàn)異常的地方
}catch(異常類型 e){
    // 處理異常的代碼
    // 記錄日志潭苞、打印異常信息忽冻、繼續(xù)拋出異常
}

  • try 編寫可能會出現(xiàn)異常的代碼
  • catch 異常的捕獲進行處理
  • try catch不能單獨使用, 必須連用
public class Demo4 {
    public static void main(String[] args) {
        try {
            read("xiaomiMi.txt");
        } catch (Exception e) {
            // 在try中拋出什么異常此疹,在括號中就捕獲什么異常類型
//            e.printStackTrace();
            System.out.println("++++++++");
            System.out.println(e);
        }
        System.out.println("end");
    }
    public static void read(String path) throws FileNotFoundException {
        if (!path.equals("xiaomimi.txt")){
            throw new FileNotFoundException("你的文件怎么消失了呢");
        }
    }
}

finally 代碼塊

finally: 有一些特定的代碼僧诚,無論是否發(fā)生異常都要執(zhí)行遮婶,另外,因為異常會引發(fā)程序跳轉(zhuǎn)湖笨,導(dǎo)致有些語句執(zhí)行不到旗扑, 而finally就解決了這個問題。

  • finally不能單獨使用
public class Demo4 {
    public static void main(String[] args) {
        try {
            read("xiaomiMi.txt");
        } catch (Exception e) {
            // 在try中拋出什么異常慈省,在括號中就捕獲什么異常類型
//            e.printStackTrace();
            System.out.println("++++++++");
            System.out.println(e);
        }finally {
            System.out.println("不管try和catch執(zhí)行啥了臀防,我這里都會執(zhí)行");
            System.out.println("我是接盤俠");
        }
        System.out.println("end");
    }
    public static void read(String path) throws FileNotFoundException {
        if (!path.equals("xiaomimi.txt")){
            throw new FileNotFoundException("你的文件怎么消失了呢");
        }
    }
}

ambda表達式

是JDK1.8版本的新特性, lambda 省去面向?qū)ο蟮臈l條框框边败,格式由3部分組成

  • 一些參數(shù)
  • 一個箭頭
  • 一段代碼
    標(biāo)準(zhǔn)格式:
(參數(shù)類型  參數(shù)名) -> { 代碼語句 }

說明

  • 小括號就是傳統(tǒng)的參數(shù)列表袱衷,多個用逗號分隔
  • -> 代表指向動作
  • 大括號和原來一樣寫方法體
無參無返回
public interface Cook {
    void makeFood();
}

public class Demo2 {
    public static void main(String[] args) {
        invoke(()->{
            System.out.println("lambda表達式做的飯好了");
        });
    }
    public static void invoke(Cook cook){
        cook.makeFood();
    }
}

小括號代表Cook接口的makeFood方法參數(shù)為空, 大括號代表makeFood的方法體

有參有返回值

需求:使用數(shù)組存儲多個Person對象笑窜,對數(shù)組中的Person對象使用Arrays的sort方法通過年齡排序致燥;
代碼分析

  • 為了排序, Arrays.sort需要排序規(guī)則排截, Comparator接口的實例嫌蚤,實現(xiàn)compare方法
  • 為了實現(xiàn)compare方法,不得不寫一個Comparator的實現(xiàn)類
  • 為了省略Comparator的實現(xiàn)類ComparatorImpl断傲,不得不使用匿名內(nèi)部類
  • 必須覆蓋compare方法脱吱,所有的聲明都需要重寫一遍
  • 實際上, 只有參數(shù)和方法體是關(guān)鍵部分

Lambda寫法

public class Demo4 {
    public static void main(String[] args) {
        Person[] array = {
                new Person("貂蟬", 223),
                new Person("孫尚香", 18),
                new Person("妲己", 300),
                new Person("楊玉環(huán)", 221),
        };
        Arrays.sort(array, (Person a, Person b)->{
            return a.getAge()-b.getAge();
        });
        for (Person person :array){
            System.out.println(person);
        }
    } 
}

需求:給定一個計算器Calculator接口认罩,內(nèi)含抽象方法calc可以將連個int類型的數(shù)組相加得到和的值
public interface Calculator {
    int calc(int a , int b);
}

public class Demo5 {
    public static void main(String[] args) {
        // 使用lambda表達式 調(diào)用測試
        invokeCalc(5,6, (int a, int b)->{
            return a + b;
        });

    }
    public static void invokeCalc(int a, int b, Calculator calculator){
        int res = calculator.calc(a, b);
        System.out.println("res = "+ res);
    }
}

省略格式:

Lambda強調(diào)做什么箱蝠, 而不是怎么做, 凡是可以根據(jù)上下文推導(dǎo)得知的消息垦垂,都可以省略

public class Demo6 {
    public static void main(String[] args) {
        // 使用lambda表達式 調(diào)用測試
        invokeCalc(5,6, (a, b)-> a + b);
    }
    public static void invokeCalc(int a, int b, Calculator calculator){
        int res = calculator.calc(a, b);
        System.out.println("res = "+ res);
    }
}

省略規(guī)則:

  • 小括號內(nèi)參數(shù)可以省略
  • 如果小括號內(nèi)有且僅有一個參抡锈, 小括號可以省略
  • 如果大括號內(nèi)有有且僅有一個語句,則無論是否有返回值乔外,都可以省略大括號、return及語句分號
public class Demo7 {
    public static void main(String[] args) {
        // 使用lambda表達式 調(diào)用測試
        invokeShow(100, a -> a + 100);
    }
    public static void invokeShow(int a, Show show){
       int res = show.showNum(a);
        System.out.println(res);

    }
}

改寫之前廚子

public class Demo8 {
    public static void main(String[] args) {
       invoke(()-> System.out.println("省略在做飯"));

    }
    public static void invoke(Cook cook){
        cook.makeFood();
    }
}

Lambda使用前提

  1. 使用Lambda必須具有接口一罩,且要求接口中有且僅有一個抽象方法(無論是Runable杨幼、Comparator接口還是自己定義的接口,都得是抽象方法唯一)
  2. 使用Lambda必須具有上下文推斷.聂渊;也就是方法的參數(shù)或者局部變量類型必須為Lambda對應(yīng)的接口類型差购,才能使用Lambda作為該接口的實例
    有且只有一個抽象方法的接口叫做函數(shù)式接口
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市汉嗽,隨后出現(xiàn)的幾起案子欲逃,更是在濱河造成了極大的恐慌,老刑警劉巖稳析,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異彰居,居然都是意外死亡,警方通過查閱死者的電腦和手機陈惰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門畦徘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人井辆,你說我怎么就攤上這事”保” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵奈虾,是天一觀的道長夺谁。 經(jīng)常有香客問我,道長肉微,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任勿负,我火速辦了婚禮劳曹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘铁孵。我一直安慰自己,他們只是感情好蜕劝,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布岖沛。 她就那樣靜靜地躺著,像睡著了一般婴削。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嗤朴,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機與錄音播赁,去河邊找鬼。 笑死乓序,一個胖子當(dāng)著我的面吹牛坎背,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播得滤,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼懂更,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了沮协?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤聘殖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后奸腺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體血久,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年绷旗,在試婚紗的時候發(fā)現(xiàn)自己被綠了副砍。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片庄岖。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖心剥,靈堂內(nèi)的尸體忽然破棺而出邦尊,到底是詐尸還是另有隱情优烧,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布又沾,位于F島的核電站熙卡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏滑燃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一表窘、第九天 我趴在偏房一處隱蔽的房頂上張望甜滨。 院中可真熱鬧,春花似錦艳吠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至填物,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間滞磺,已是汗流浹背莱褒。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留广凸,地道東北人蛛枚。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓蹦浦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親盲镶。 傳聞我的和親對象是個殘疾皇子谅摄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348