zoukankan      html  css  js  c++  java
  • 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;
        }
    }

    其他接口:

     

  • 相关阅读:
    Android开发 Android Studio2.0 教程从入门到精通Windows版
    SQLSERVER 执行过的语句查询
    通过身份证分析出生年月日、性别、年龄的SQL语句
    SQL 根据日期精确计算年龄
    SQL 语句转换格式函数Cast、Convert
    Delphi 单元
    【转】实现Ribbon风格的窗体
    Delphi的打开文件对话框-TOpenDialog
    Delphi数据类型转换
    深入理解javascript中的立即执行函数(function(){…})()
  • 原文地址:https://www.cnblogs.com/soft2018/p/10342714.html
Copyright © 2011-2022 走看看