zoukankan      html  css  js  c++  java
  • JDK8的新特性

    一、接口的默认方法-default

    Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法,示例如下:

    interface Formula {
        double calculate(int a);
    
        default double sqrt(int a) {
            return Math.sqrt(a);
        }
    }

    Formula接口在拥有calculate方法之外同时还定义了sqrt方法,实现了Formula接口的子类只需要实现一个calculate方法,默认方法sqrt将在子类上可以直接使用。

    Formula formula = new Formula() {
        @Override
        public double calculate(int a) {
            return sqrt(a * 100);
        }
    };
    
    formula.calculate(100);     // 100.0
    formula.sqrt(16);           // 4.0

    二、Lambda 表达式

    首先看看在老版本的Java中是如何排列字符串的:

    List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
    
    Collections.sort(names, new Comparator<String>() {
        @Override
        public int compare(String a, String b) {
            return b.compareTo(a);
        }
    });

    使用lanbda表达式:

    Collections.sort(names, (String a, String b) -> {
        return b.compareTo(a);
    });
    button.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.print("Helllo Lambda in actionPerformed");
        }
    });
    
    下面是使用 Lambda 表达式后:
    button.addActionListener(
        //actionPerformed 有一个参数 e 传入,所以用 (ActionEvent e)
        (ActionEvent e)-> 
        System.out.print("Helllo Lambda in actionPerformed")
    );
    
    
    Thread t = new Thread(
    \run 没有参数传入,所以用 (), 后面用 {} 包起方法体
    () -> {
     System.out.println("Hello from a thread in run");
    }
    );
    
    
    通过上面两个代码的比较可以发现使用 Lambda 表达式可以简化代码,并提高代码的可读性。
    为了进一步简化 Lambda 表达式,可以使用方法引用。例如,下面三种分别是使用内部类,使用 Lambda 表示式和使用方法引用方式的比较:
    //1. 使用内部类
    Function<Integer, String> f = new Function<Integer,String>(){
        @Override
        public String apply(Integer t) {
            return null;
        }
    };
    //2. 使用 Lambda 表达式
    Function<Integer, String> f2 = (t)->String.valueOf(t); 
    //3. 使用方法引用的方式
    Function<Integer, String> f1 = String::valueOf;

    三、函数式接口

    每一个lambda表达式都对应一个类型,通常是接口类型。而“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。

    @FunctionalInterface
    interface Converter<F, T> {
        T convert(F from);
    }
    //下面这句话可以理解为方法的实现 Converter
    <String, Integer> converter = (from) -> Integer.valueOf(from); Integer converted = converter.convert("123"); System.out.println(converted); // 123

    需要注意如果@FunctionalInterface如果没有指定,上面的代码也是对的。

    四、方法与构造函数引用

      方法

    前一节中的代码还可以通过静态方法引用来表示:

    Converter<String, Integer> converter = Integer::valueOf;
    Integer converted = converter.convert("123");
    System.out.println(converted);   // 123

    Java 8 允许你使用 :: 关键字来传递方法或者构造函数引用,上面的代码展示了如何引用一个静态方法,我们也可以引用一个对象的方法:

    converter = something::startsWith;
    String converted = converter.convert("Java");
    System.out.println(converted);    // "J"

      构造函数

    接下来看看构造函数是如何使用::关键字来引用的,首先我们定义一个包含多个构造函数的简单类:

    class Person {
        String firstName;
        String lastName;
    
        Person() {}
    
        Person(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }
    }

    接下来我们指定一个用来创建Person对象的对象工厂接口:

    interface PersonFactory<P extends Person> {
        P create(String firstName, String lastName);
    }
    PersonFactory<Person> personFactory = Person::new;
    Person person = personFactory.create("Peter", "Parker");

    我们只需要使用 Person::new 来获取Person类构造函数的引用,Java编译器会自动根据PersonFactory.create方法的签名来选择合适的构造函数。

    五、Lambda 作用域

    在lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似。你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量。

      访问局部变量

    我们可以直接在lambda表达式中访问外层的局部变量:

    final int num = 1;     // 不用final也可以
    Converter<Integer, String> stringConverter =
            (from) -> String.valueOf(from + num);
    
    stringConverter.convert(2);     // 3

    不过这里的num必须不可被后面的代码修改(即隐性的具有final的语义),例如下面的就无法编译:

    int num = 1;
    Converter<Integer, String> stringConverter =
            (from) -> String.valueOf(from + num);
    num = 3;

    六、几种默认方法:

    Predicate接口

    Predicate 接口只有一个参数,返回boolean类型。该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非):

    Predicate<String> predicate = (s) -> s.length() > 0;
    
    predicate.test("foo");              // true
    predicate.negate().test("foo");     // false
    
    Predicate<Boolean> nonNull = Objects::nonNull;
    Predicate<Boolean> isNull = Objects::isNull;
    
    Predicate<String> isEmpty = String::isEmpty;
    Predicate<String> isNotEmpty = isEmpty.negate();

    Function 接口

    Function 接口有一个参数并且返回一个结果,并附带了一些可以和其他函数组合的默认方法(compose, andThen):

    Function<String, Integer> toInteger = Integer::valueOf;
    Function<String, String> backToString = toInteger.andThen(String::valueOf);
    
    backToString.apply("123");     // "123"

    Supplier 接口

    Supplier 接口返回一个任意范型的值,和Function接口不同的是该接口没有任何参数

    Supplier<Person> personSupplier = Person::new;
    personSupplier.get();   // new Person

    Consumer 接口

    Consumer 接口表示执行在单个参数上的操作。

    Consumer<Person> greeter = (p) -> System.out.println("Hello, " + p.firstName);
    greeter.accept(new Person("Luke", "Skywalker"));

    Comparator 接口

    Comparator 是老Java中的经典接口, Java 8在此之上添加了多种默认方法:

    Comparator<Person> comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName);
    
    Person p1 = new Person("John", "Doe");
    Person p2 = new Person("Alice", "Wonderland");
    
    comparator.compare(p1, p2);             // > 0
    comparator.reversed().compare(p1, p2);  // < 0

    Optional 接口

    Optional 不是函数是接口,这是个用来防止NullPointerException异常的辅助类型,这是下一届中将要用到的重要概念,现在先简单的看看这个接口能干什么:

    Optional 被定义为一个简单的容器,其值可能是null或者不是null。在Java 8之前一般某个函数应该返回非空对象但是偶尔却可能返回了null,而在Java 8中,不推荐你返回null而是返回Optional。

    Optional<String> optional = Optional.of("bam");
    
    optional.isPresent();           // true
    optional.get();                 // "bam"
    optional.orElse("fallback");    // "bam"
    
    optional.ifPresent((s) -> System.out.println(s.charAt(0)));     // "b"

    转载自:https://www.jianshu.com/p/0bf8fe0f153b

  • 相关阅读:
    AJAX传输图片文件
    和内嵌的iframe进行通讯
    ts的特殊数据类型
    Angular RxJs:针对异步数据流编程工具
    Angular路由使用
    RBAC基于角色的权限管理模型
    Java中的实体类--Serializable接口、transient 关键字
    字符串问题----将整数字符串转换成整数值
    字符串问题----判断两个字符串是否互为旋转词
    字符串问题----去掉字符串中连续出现K个0的子串
  • 原文地址:https://www.cnblogs.com/linhongwenBlog/p/12560032.html
Copyright © 2011-2022 走看看