Java基础之java8新特性(1)Lambda

一、接口的默认方法、static方法、default方法。

  1、接口的默认方法

  在Java8之前,Java中接口里面的默认方法都是public abstract 修饰的抽象方法,抽象方法并没有方法实体。

public class Test_interface {
    public static void main(String[] args) {
        pubInterface ts = new MyInterface();
        ts.fun1();
    }
}

//测试接口
interface pubInterface{
    public void fun1();//抽象方法
}

//接口的实现类
class MyInterface implements pubInterface{
    @Override
    public void fun1() {
        System.out.println("你好我是TestStatic的实现类");
    }
}
View Code

  2、static方法

  在Java8中,接口里面可以用static修饰有方法实体的方法。

  (1)、使用static修饰的接口中的方法必须要有实体。

  (2)、接口的static方法只能够被接口本身调用:接口名.方法名(…)。

  (3)、接口的static方法不能够被子接口继承。

  (4)、接口的static方法不能够被实现类重写或者调用。

public class Test_interface {
    public static void main(String[] args) {
        //该接口直接可以调用static方法,但是不能够调用普通抽象方法。
        StaInterface.fun2();
        //报错可以得知,static方法是不能够被继承的
        SonInterface.fun2();
    }
}

//测试接口
interface StaInterface{
    public void fun1();//抽象方法
    static void fun2(){
        System.out.println("我是static方法……");
    }
}

//接口的实现类
class MyInterface implements StaInterface{
    /**只能够重写抽象方法,不能重写static修饰的方法*/
    @Override
    public void fun1() {

    }
}

//子接口
interface SonInterface extends StaInterface{
    
}
View Code

 

  3、default方法:

  接口的default方法必须有主体

  接口的default方法不能被本身接口调用,

  接口的default方法可以被子接口继承

  接口的default方法可以被实现类复写以及调用

 

public class Test_interface {
    public static void main(String[] args) {
        //该接口直接可以调用static方法,但是不能够调用普通抽象方法。
        StaInterface.fun2();
        //报错可以得知,static方法是不能够被继承的
        SonInterface.fun2();

        //default方法与普通抽象方法是可以
        StaInterface sf = new MyInterface();
        sf.fun1();
        sf.fun3();
    }
}

//测试接口
interface StaInterface{
    public void fun1();//抽象方法
    //static 方法
    static void fun2(){
        System.out.println("我是static方法……");
    }
    //default方法
    default void fun3(){
        System.out.println("我是default方法……");
    }
}

//接口的实现类
class MyInterface implements StaInterface{
    /**只能够重写抽象方法,不能重写static修饰的方法*/
    @Override
    public void fun1() {

    }

    //是可以重写default方法的。
    @Override
    public void fun3() {

    }

}

//子接口
interface SonInterface extends StaInterface{

}
View Code

二、函数式接口

   1、什么是函数式接口:

  函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为lambda表达式。

  接口注解:@FunctionalInterface

 

  初体验:

  (1)、两个参数,有返回值

public class Lambda_one {
    public static void main(String[] args) {
        //匿名内部类的方式
       StaInterface se = new StaInterface() {
           @Override
           public int sum(int num1, int num2) {
               return num1 +num2;
           }
       };
       System.out.println(se.sum(1,3));

       //lambda表达式写法
        StaInterface seLa1 = (int num1, int num2) -> {
            return num1 + num2;
        };
        System.out.println("Lambda表达式一:" + seLa1.sum(1,3));

        /**
         * lambda表达式简写
         * 1、形参列表中的表达式可以不写,会自行推断
         * 2、如果方法体中的代码只有一句,可以省略{},如果return返回的是数据,可以省略return
         */
        StaInterface seLa2 = (num1, num2) -> num1 + num2;
        System.out.println("Lambda表达式二:" +  seLa2.sum(1,2));

    }
}

//测试接口
@FunctionalInterface
interface StaInterface{
    public int sum(int num1,int num2);//抽象方法
}
View Code

  (2)、一个参数,无返回值

public class Lamdba_two {
    public static void main(String[] args) {
        //匿名内部类
        StaInterface1 s1 = new StaInterface1() {
            @Override
            public void getStr(String str) {
                System.out.println(str);
            }
        };
        s1.getStr("HelloWorld!!!");

        //lambda表达式写法
        StaInterface1 s2 = (String str) -> {
            System.out.println(str);
        };
        s2.getStr("Lambda表达式一:"+ "Helloworld一");

        StaInterface1 s3 = str -> System.out.println(str);
        s3.getStr("Lambda表达式二:"+ "Helloworld二");
    }
}

//测试接口
@FunctionalInterface
interface StaInterface1{
    public void getStr(String str);//抽象方法
}
View Code

  (3)、无参数,无返回值

public class Lambda_three {
    public static void main(String[] args) {
        StaInterface2 s1 = new StaInterface2() {
            @Override
            public void getStr() {
                System.out.println("HelloWorld");
            }
        };
        s1.getStr();

        //Lambda表达式
        StaInterface2 s2 = () -> {
            System.out.println("Lamdba表达式一:" + "HelloWorld一");
        };
        s2.getStr();

        //Lamdba表达式简化,我们可以这么写,但是没有实际意义
        StaInterface2 s3 = () -> {};
        s3.getStr();
    }
}

//测试接口
@FunctionalInterface
interface StaInterface2{
    public void getStr();//抽象方法
}
View Code

三、Lambda表达式

  1、什么是Lambda表达式

  简单的说:可以看成是对匿名内部类的简写,使用Lambda表达式时候,接口必须是函数式接口。

   2、Lambda表达式语法

    基本语法:

      <函数式接口>  <变量名> = (参数1,参数2……)->{

          //方法体

      }

  3、特点:

  (1)、=右边的类型会根据左边的函数式接口类型自动推断;

  (2)、如果形参列表为空,只需要保留()

  (3)、如果形参只有一个,()可以省略,只需要参数名称即可;

  (4)、如果执行语句只有一句,且并没有返回值,{}可以省略,如果有返回值,若想省去{},则必须同时省略return,并且执行语句也保证只有一句。

  (5)、形参列表的数据类型会自动推断。

  (6)、Lamdba不会生成一个单独的内部类文件。

  (7)、lambda表达式如果访问了局部变量,则局部变量必须是final的,若是局部变量没有加final关键字,系统会自动添加,此后在修改局部变量,会报错。

  4、Lambda作用域

    在Lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似(我们在学习匿名内部类时候,匿名内部类在访问局部变量的时候,局部变量是被final修饰的),你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量,但是如果访问局部变量,要求局部变量必须是final修饰的。

  注意:我们Java8新特性里面,匿名内部类访问局部变量,局部变量不需要再用final修饰了,因为Java8已经帮我们写过了,所以我们可以省略。

   (1)、匿名内部类举例

public class Lambda_four {
    public static void main(String[] args) {
        int age = 9;
        StaInterface3 s1 = new StaInterface3() {
            @Override
            public void getStr() {
                System.out.println(age);
                //注意,当我们在下面对age重新赋值时候,这里的age就报错了,
                // 因为,Java8隐式的对age加上final了
            }
        };
        s1.getStr();
        age = 10;
    }
}

interface StaInterface3{
    public void getStr();//抽象方法
}
View Code

  (2)、Lambda表达式举例

public class Lambda_four {
    public static void main(String[] args) {
        int age = 9;
        StaInterface3 s2 = () ->{
            System.out.println(age);
            //注意,当我们在下面对age重新赋值时候,这里的age就报错了,
            // 因为,Java8隐式的对age加上final了
        };
        age = 10;
    }
}

interface StaInterface3{
    public void getStr();//抽象方法
}
View Code

四、方法的引用

  1、构造方法的引用

public class Lambda_five {
    /*需求:
     * 1、有一个Person类
     * 2、有一个获得Person对象的接口工厂
     * 3、想通过工厂获得一个Person对象
     * 4、需要现有一个实际的工厂对象
     */
    public static void main(String[] args) {
        //使用匿名内部类
        PersonFactory py = new PersonFactory() {
            @Override
            public Person createPerson(String firstName, String lastName) {
                return new Person(firstName,lastName);
            }
        };
        Person person1 = py.createPerson("du", "yahui");
        System.out.println(person1);

        //使用Lambda表达式
        PersonFactory py1 = (firstName,lastName) ->{
            return new Person(firstName,lastName);
        };
        Person person2 = py1.createPerson("mi", "li");
        System.out.println(person2);

        //简写Lambda表达式
        PersonFactory py2 = (firstName,lastName) -> new Person(firstName,lastName);
        Person person3 = py2.createPerson("haha","gaga");
        System.out.println(person3);
    }
}
View Code

  2、静态方法的引用,把String转成num

public class Lambda_six {
    public static void main(String[] args) {
        ParseLambda pa = new ParseLambda() {
            @Override
            public int parseInteger(String num) {
                return Integer.parseInt(num);
            }
        };
        int i1 = pa.parseInteger("12");
        System.out.println(i1);

        //使用Lambda表达式
//        ParseLambda p = (String num) ->{
//            return Integer.parseInt(num);
//        };
        ParseLambda pa1 = num -> Integer.parseInt(num);
        int i2 = pa1.parseInteger("123");
        System.out.println(i2);

        //Lambda简写
        ParseLambda pa3 = Integer :: parseInt;
        int i3 = pa3.parseInteger("777");
        System.out.println(i3);
    }
}

interface ParseLambda{
    int parseInteger(String num);
}
View Code

 五、四大核心函数式接口

/*
 * Java8 内置的四大核心函数式接口
 *
 * Consumer<T> : 消费型接口
 *         void accept(T t);
 *
 * Supplier<T> : 供给型接口
 *         T get();
 *
 * Function<T, R> : 函数型接口
 *         R apply(T t);
 *
 * Predicate<T> : 断言型接口
 *         boolean test(T t);
 *
 */
public class Lambda_One {
    //Consumer<T> 消费型接口 :也就是,给一个参数,操作这个参数
    @Test
    public void test1(){
        happy(1000,(money) -> System.out.println("出去共消费了" + money + "元"));
    }
    public void happy(double money, Consumer<Double> con){
        con.accept(money);
    }

    //Supplier<T> 供给型接口 :产生一些对象
    @Test
    public void test2(){
        List<Integer> listNum = getListNum(10,() -> (int)(Math.random() * 100));
        for (Integer integer : listNum) {
            System.out.println(integer);
        }
    }
    //需求:产生指定个数的整数,并放入集合中
    public List<Integer> getListNum(int num, Supplier<Integer> sup){
        List<Integer> list = new ArrayList<Integer>();
        for(int i = 0; i < num; i++){
            list.add(sup.get());
        }
        return list;
    }

    //Function<T, R> 函数型接口:传入一个T,返回一个R
    @Test
    public void test3(){
        String s1 = stringHander("    Helloworld  !!!",(str) -> str.trim());
        System.out.println(s1);
        String s2 = stringHander("    Helloworld  !!!",(str) -> str.substring(7));
        System.out.println(s2);
    }
    //需求:处理字符串
    public String stringHander(String str, Function<String,String> fun){
        return fun.apply(str);
    }

    //Predicate<T> 断言型接口:用于做一下判断
    @Test
    public void test4(){
        List<String> list = Arrays.asList("Hello", "atguigu", "Lambda", "www", "ok");
        List<String> listStr = filterStr(list,(str) -> str.length() > 3);
        for (String s : listStr) {
            System.out.println(s);
        }
    }
    //需求:将满足条件的字符串,放入集合中
    public List<String> filterStr(List<String> list, Predicate<String> pre){
        List<String> strList = new ArrayList<>();

        for (String str : list) {
            if(pre.test(str)){
                strList.add(str);
            }
        }

        return strList;
    }
}

其他接口:

 

 

posted @ 2019-02-13 11:20  杜大帅-Rebirth  阅读(188)  评论(0编辑  收藏  举报