Java基础Day15泛型、异常、λ(lambda)表达式

泛型、异常、λ(lambda)表达式

泛型

可以在类和方法中预支的使用未知的类型,一般在创建对象时,将位置类型确定为具体类型,当没有指定泛型的时候,默认类型是Obj类型。

使用泛型的好处

  • 将运行时时期的异常,转移到了编译时期,变成了编译失败
  • 避免了类型强转的麻烦
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class GenericDemo {
    public static void main(String[] args) {
        Collection list=new ArrayList<>();
        list.add("nishi");
        list.add("shabi");
//        list.add(666);集合已经明确了具体元素存放的类型
//        已经明确了类型,在使用迭代器的时候,迭代器也同样知道遍历元素的具体类型
        Iterator <String>iterator = list.iterator();
        while (iterator.hasNext()){
            String str = iterator.next();
            System.out.println(str.length());
        }
        System.out.println(list);
    }
}

泛型的定义与使用

泛型,用来灵活的将数据类型应用到不同类,方法,接口当中。将数据类型作为参数进行传递。
格式

修饰符 class 类名<代表泛型的变量>{
}

使用泛型:在创建对象的时候确定泛型

自定义泛型
package Day15.myGemeric;

public class MyGenericClass<MVP> {
    //没有MVP类型,在这里代表未知的一种数据类型
    private MVP mvp;

    public MVP getMvp() {
        return mvp;
    }

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

public class TestGenericDemo {
    public static void main(String[] args) {
        //创建一个泛型为String类
        MyGenericClass<String> my = new MyGenericClass<>();
        my.setMvp("Faker");
        String mvp = my.getMvp();
        System.out.println(mvp);

        MyGenericClass<Integer> my2 = new MyGenericClass<>();
        my2.setMvp(111);

        Integer mvp2=my2.getMvp();
        System.out.println(mvp2);
    }
}

含有泛型的方法

格式

修饰符 <代表泛型的变量>返回值类型 方法名(参数列表){
        
}

例:

package Day15.myGemeric;

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

    public <MVP> MVP show2(MVP mvp) {
        return mvp;
    }
}
package Day15.myGemeric;

public class TestGenericDemo2 {
    public static void main(String[] args) {
        MyGenericMethod mgm=new MyGenericMethod();
        mgm.show("Uzi");
        mgm.show(123);
        mgm.show(123.123);
    }
}

含有泛型的接口

格式

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

package Day15.myGemeric;

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

实现类在定义类的时候确定泛型的类型

package Day15.myGemeric;

public class MyGenericImpl implements MygenericInterface<String>{

    @Override
    public void add(String s) {

    }

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


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

确定泛型
import java.util.ArrayList;


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 (数值类型)
  • ?表示不确定的Java类型
    <?>表示不确定的Java类型,一旦使用,<?>只能使用Object类中的共性方法
基本使用

<?>不知道到使用什么Java类型

package Day15.myGemeric;

import java.util.ArrayList;
import java.util.Collection;

public class TestGenericDemo3 {
    public static void main(String[] args) {
        Collection<Integer> list1=new ArrayList<>();
        Collection<Integer> list2=new ArrayList<>();
        getElement(list1);
        getElement(list2);
    }

    public static void getElement (Collection<?>coll) {
        // <?>代表可以接受任意类型

    }
}

高级应用——受限类型

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

格式:类型名称<? extends类 >对象名称
意义:只能接受该类型及其父类

例:已知Object类、String类、Number类、Integer类,其中Number类是Integer类的父类

package Day15.myGemeric;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
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);//会报错
    }
        //泛型的上限 此时泛型?必须是Number类型或者Number类型子类
    public static void getElement1(Collection<? extends Number>coll){
        //泛型的下限 此时泛型?必须是Number类型或者Number类型父类
    }
    public static void getElement2(Collection<? super Number>coll){
    }
}
image.png

异常

异常:指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM虚拟机的非正常停止,在Java中异常本身是一个类,产生异常就是创建异常对象并且抛出一个异常对象。Java处理异常的方式是中断处理

异常不是语法错误,语法错误是无法通过编译

异常体系

异常的根类是Java.lang.Throwable,两个子类java.lang.Error和java.lang.Exception 平时所说的异常是java.lang.Exception
Throwable体系:

  • Error:严重错误,无法通过处理的错误,好比绝症
  • Exception:表示异常 异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必要处理的。好比感冒发烧
常用方法
  • public void printStackTrace();打印异常的详细信息
image.png

异常的分类

  • 编译时期异常:如果没有处理,编译失败(如日期格式)format
  • 运行时期异常:在运行时期检查异常(如数学异常)


    image.png

异常处理

Java中异常处理的五个关键字:try、catch、finally、throw、throws

抛出异常处理throw
  • 创建一个异常对象。封装一些提示信息(信息可以自己编写)
  • 通过throw将这个异常对象告知调用者,throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。
  • 格式
throw new异常类名()

例:


image.png
throw new NullPointerException("要访问的arr数组不存在");
throw new ArrayIndexOutOfBoundsException("数组越界");

声明异常throws

声明异常:将问题标识出来,报告给调用者,如果方法内通过throw抛出了编译时异常,而没有捕获处理,那么必须通过throws声明,让调用者处理

package Day15.exceptionDemo;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo3 {
    public static void main(String[] args) throws ParseException {
        String s = "1999-04";
        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

如果异常出现会立刻终止程序,所以我们得处理异常
1.声明抛出,由调用者来处理(throws)
2.使用try catch语句块来处理异常
try catch的方式就是捕获异常
格式

try{
编写可能会出现异常的地方(如文件读取不到)
}catch(异常类型e){
//处理异常的代码
//记录日志、打印异常信息、继续抛出异常
}
  • try 编写可能出现异常的代码
  • catch 异常的捕获进行处理
  • try catch不能单独使用,必须连用
    例:
package Day15.exceptionDemo;

import java.io.FileNotFoundException;

public class Demo4 {
    public static void main(String[] args) {
        try {
            read("少年阿宾.txt");
        } catch (FileNotFoundException e) {

            e.printStackTrace();
        }
    }
    public static void read(String path) throws FileNotFoundException {
        if(!path.equals("少年阿宾.txt")){
        throw new FileNotFoundException("文件违规消失");
        }
    }
}

finally 代码块(子亮侠)

finally有一些特定的代码无论是否会挂上代码都需要执行,另外异常经常会引发程序跳转导致有些语句执行不到,而finally就解决了这个问题,因为他是接盘子亮。

package Day15.exceptionDemo;

import java.io.FileNotFoundException;

public class Demo4 {
    public static void main(String[] args) {
        try {
            read("少年阿宾.txt");
        } catch (FileNotFoundException e) {
            //在try中抛出什么异常,在括号中就捕获什么异常类型
//            e.printStackTrace();
            System.out.println("++++++++++");
            System.out.println(e);


            }finally{

                System.out.println("不管catch和try执行什么,在这里都会执行");
                System.out.println("何子亮是接盘侠");

            }
            System.out.println("end");
        }
        public static void read (String path) throws FileNotFoundException {
            if (!path.equals("少年阿宾.txt")) {
                throw new FileNotFoundException("文件违规消失");
            }
        }
    }

lambda(λ)表达式
是JDK1.8版本的新特性,lambda 省去面向对象的条条框框,格式由三部分组成

  • 一些参数
  • 一个箭头
  • 一段代码
    标准格式:
    (参数类型 参数名)->{
    代码语句:System.out.println("λ表达式做的饭好了");
    }

说明

  • 小括号就是传统的参数列表,用多个逗号分隔
  • ->代表指向动作
  • 大括号和原来一样写方法体
无参无返回
package Day15.lambdaDemo;

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

小括号代表Cook接口的makeFood方法参数为空,大括号代表makeFood的方法体

有参有返回值

需求:使用数组存储多个Person对象,对数组中的Person对象使用Arrays的sort方法通过年龄排序;
代码分析

  • 为了排序,Arrays.sort需要排序规则,Compareator接口的实例,实现compare方法
  • 为了实现compare方法,不得不写一个Comparator的实现类
  • 为了省略Comparator的实现类ComparatorImpl,不得不使用匿名内部类
  • 必须覆盖compare方法,所有的声明都需要重写一遍。
  • 实际上
package Day15.lambdaDemo;

import sun.plugin.javascript.navig.Array;

import java.util.Arrays;

public class Demo4 {
    public static void main(String[] args) {
        Person[] array = {
                new Person("貂蝉", 2013),
                new Person("西施", 3011),
                new Person("杨玉环", 1400),
                new Person("赵飞燕", 1000),
        };
        Arrays.sort(array, (Person a, Person b) -> {
            return a.getAge() - b.getAge();
        });
        for (Person person : array) {
            System.out.println(person);
        }
    }
}
需求:给定一个计算器Calculator接口,内含抽象方法calc可以将连个int类型的数组相加得到和的值。

Lambda使用前提

1.使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法(无论是Runable、Comparator接口还是自己定义的接口,都得是抽象方法唯一)
2.使用Lambda必须得有上下推断;也就是方法的参数或者局部变量类型必须为lambda对应的接口类型,才能使用Lambda作为该接口的实例。
有且只有一个抽象方法的接口叫做函数式接口

package Day15.exceptionDemo;

public class Demo5 {
    public static void main(String[] args) {
        //使用lambda
        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 );
    }
    }

省略模式:


省略规则:

  • 小括号内参谋书可以省略;
  • 如果小括号内有且仅有一个参,则小括号可以省略;
  • 如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号甚至return语句。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355