• <JAVA8新增内容>关于匿名内部集合和lambda表达式



    
    

    要想说清楚JAVA中的Lambda表达式,必须想讲一下匿名内部类来帮助理解本质。

    一.匿名内部类

      匿名内部类适合创建那种只需要一次使用的类,例如前面介绍命令模式时所需要的Command对象,匿名内部类的语法有点奇怪,创建匿名内部类时会立即创建一个该类的实例,这个类的定义立即消失,匿名内部类不能重复使用。

    语法格式一般如下:

    new 实现接口() | 父类构造器 (实参列表){

      //匿名内部类的类体部分

    }

    从上面可以看出,匿名内部类必须继承一个父类,或者实现一个接口,但最多只能继承一个父类,或者实现一个接口。

    关于匿名内部类还有如下两条规则:

    1.匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象,因此不允许将匿名内部类定义为抽象类。

    2.匿名内部类不能定义构造器(Constructor),由于匿名内部类没有类名,所以无法定义构造器,但匿名构造类可以定义初始化块,可以通过实例初始化块来完成构造函数需要完成的部分。

    Example 1:

    interface MyInter{
        public String getName();
    }
    
    public class AnonymousTest{
        public void test(MyInter i){
            System.out.println("The Content of this function is "+i.getName());
        }
    
        public static void main(String[] args){
            AnonymousTest ta;
            ta.test(new MyInter(){
                public String getName(){
                     return "Anonymous Content";
                }
        });
    }

    以上的代码等价的实现类对象的代码是:

    class AnonymousEqual implements MyInter{
        public String getName(){
            return "Anonymous Class Content";
        }
    }

    Example 2:

    abstract class MyUpperClass{
        private String name;
        public abstract String getName();
        public MyUpperClass(){}
        public MyUpperClass(String s){ name=s; }
    }////Abstract instead of Interface
    
    public class AnonymousTest{
        public void test(MyUpperClass m){
            System.out.println("The Content of This Method is "+m.getName());
        }
        //////////////
        public static void main(String[] args){
            AnonymousTest at;
            at.test(new MyUpperClass("Abstract Class Derived Content"){
                public String getName(){
                    return "AnonymousClass Derived Content";
                }
            });
        }
    }


    二.Lambda表达式

      Lambda表达式是Java8的重要更新,也是一个被广大开发者期待已久的新特性。Lambda表达式支持将代码块作为参数,Lambda表达式允许使用更简洁的代码来创建只有一个抽象方法的接口(这种接口被称为函数式接口)的实例。

    Lambda表达式完全可以用于简化创建匿名内部类对象,因此可将上面中的Example 1中的代码改写成如下的形式。

    public class AnonymousTest{
        public void test(MyInter i){
            System.out.println("The Content of This Method is "+i.getName());
        }
        //////////////////
        public static void main(String []args){
            AnonymousTest at;
            at.test(()->new String("Lambda Content"));
        }
    }

      从上面的程序之中可以看出,这段代码之中Lambda表达式所实现的test方法和匿名内部类所实现的test方法是完全等价的,只是不再需要一个繁琐的代码块重新声明一个匿名类,不需要重新指出所重写的方法的名字,也不需要给出重写的方法的返回值类型。
    从上面的方法之中可以看出,lambda表达式代替匿名内部类的时候,lambda代码块将会实现代替实现抽象类的方法体,lambda表达式的语法主要由三部分构成:

    (1)形参列表,如果只有一个参数可以省略括号,当无参数类型时可以使用()或者obj来代替。

    (2)箭头(->)

    (3)代码块部分,如果代码只有一行则可以省略掉花括号,不然使用花括号将lambda表达式的代码部分标记出来。

      Lambda表达式的类型,也被称为“目标类型(target type)”,lambda表达式的目标类型必须是“函数式接口(functional interface)”。函数式接口代表只包含一个抽象方法的接口。函数式接口可以包含多个默认方法,类方法,但只能声明一个抽象方法。如果采用匿名类型内部类来创建函数式接口的实例,则只需要实现一个抽象方法,在这种情况下即可采用lambda表达式来创建对象,该表达式创建出来的对象目标就是这个函数接口。(可以用@FunctionalInterface注解来对函数接口实行限制)

    ##表达式的目标类型必须是明确的函数式接口

    ##lambda表达式只能为函数式接口创建对象,lambda表达式只能实现一个方法,因此他它只能为只有一个抽象方法的借口(函数式接口)创建对象。

    另外需要注意的一点是: Object不是函数式接口

    为了保证lambda表达式的目标类型是一个明确的函数式接口,可以有如下三种常见的方法:

    ##将lambda表达式赋值给函数式接口类型的变量

    ##将lambda表达式当作参数传递给需要函数式接口类型的参数的调用方法

    ##使用函数式接口对lambda表达式进行强制的类型转换

    附:

    在java.util.function包预定下了大量函数式接口,典型的包含如下4类接口。

    ***Function:这类接口通常包含一个apply抽象方法,对参数进行处理转换,然后返回一个新的值。

    ***Consumer:这类接口通常包含一个accept抽象方法,用于对参数进行处理,但是不返回一个新的值。

    ***Predicate:这类接口通常包含一个test抽象方方法,通过对参数的处理计算,然后返回一个boolean值

    ***Supplier:这类接口通常包含一个getAs***抽象方法,这种方法无参数,按照某种逻辑运算返回一个数据值。

  • 相关阅读:
    String类的substring方法
    postman绕过登录,进行接口测试的方法
    Dubbo
    那些吊炸天的互联网名词
    版本控制工具git
    Ubunto20.04 sudo apt-get update 出现目标被重置多次!
    ubuntu环境下搭建Hadoop集群中必须需要注意的问题
    Python作业---内置数据类型
    python作业完成简单的文件操作
    python3实现计算器
  • 原文地址:https://www.cnblogs.com/guguli/p/4394676.html
Copyright © 2020-2023  润新知