Java8语法和新功能

来源:互联网 发布:打谱软件overture下载 编辑:程序博客网 时间:2024/05/19 02:26

1- 介绍

从发明JAVA语法到功能升级换代,Java已经通过一些里程碑了:
  • Java 1.0: 最开始的程序语言
  • Java 1.1, 1.2, 1.3, 1.4:  没有语法和功能很多变化
  • Java 1.5 (或Java 5):增加了一些新的概念,并有了一些大的变化。
    • 通用/泛型
    • 自动装箱/拆箱
    • 升级 foreach 功能
    • 类型安全的枚举
    • 可变参数
    • 静态导入
    • 元数据
  • Java 6,7 在语言中没有大的变化
  • Java 8: 语言一个大的变化,增加了一些新的概念和功能:
    • 默认的接口方法
    • Lambda表达式
    • 引用方法
    • 可重复的注解
    • 数据流

2- 默认方法接口

Java8让我们通过利用 default 关键字添加非抽象的方法来实现接口。这一特点也称为扩展方法。这是我们的第一个例子:
  • Formula.java
package com.yiibai.tutorial.j8.itf;public interface Formula {   // Declare an abstract method.   double calculate(int a);   // Declaring a method is not abstract.   // Use the keyword default.   // (return the square root of a number)   default double sqrt(int a) {       return Math.sqrt(a);   }}
FormulaImpl 类实现 Formula 接口
  • FormulaImpl.java
package com.yiibai.tutorial.j8.itf;// Class thi hành Interface Formulapublic class FormulaImpl implements Formula {// implements abstract method@Overridepublic double calculate(int a) {    return a*a - a;}}
  • FormulaTest.java
package com.yiibai.tutorial.j8.itf;public class FormulaTest {    public static void main(String[] args) {        Formula formula = new FormulaImpl();        // ==> 5        double value1 = formula.sqrt(25);        System.out.println("Value1 = " + value1);        // ==> 600        double value2 = formula.calculate(25);        System.out.println("Value2 = " + value2);    }}

3- 函数接口

Java8认为接口只有一个抽象方法就是函数接口。您可以使用@FunctionalInterface注释,标记你的接口为函数接口。这不是强制性的。但是,如果添加另一个抽象方法插入此注释错误地标记接口,Java编译器会通知显示有错误。
下面是使用 @FunctionalInterface 的一些实际的例子:
下面的例子是一个有效的FunctionalInterface,因为它只有一个抽象方法。
package com.yiibai.tutorial.j8.funcitf;@FunctionalInterfacepublic interface Foo {   void something();   default void defaultMethod() {       System.out.println("..");   }}
无效的例子:

有效的例子:

无效的例子:

有效的例子:

4- Lambda表达式

首先,我们来回顾Java8之前的版本是如何整理集合的。
关于在Java中比较和排序集合,可以看看下面的文章了解更多的细节:
  • http://www.yiibai.com/java/comparison-and-sorting-in-java.html
  • SortBefore8Example.java
package com.yiibai.tutorial.j8.lambda;import java.util.Arrays;import java.util.Collections;import java.util.Comparator;import java.util.List;public class SortBefore8Example {    public static void main(String[] args) {                 // A list of the fruits.        List<String> fruits = Arrays.asList("Grapefruit", "Apple", "Durian",                "Cherry");               // Use of Collections utility method to arrange collection.        // Provide a Comparator.        Collections.sort(fruits, new Comparator<String>() {            @Override            public int compare(String o1, String o2) {                return o1.compareTo(o2);            }        });        for (String fruit : fruits) {            System.out.println(fruit);        }    }}
运行上述示例得到的结果:

Java8知道接口具有唯一的抽象方法,该方法是函数接口。因此,实现接口的时候,只需要编写一个方法来实现唯一的抽象方法。Comparator有一个唯一的抽象方法的接口,并且它是一个函数接口。可以重写上面的例子中 Java8 Lambda 的形式:
  • SortJava8Example.java
package com.yiibai.tutorial.j8.lambda;import java.util.Arrays;import java.util.Collections;import java.util.List;public class SortJava8Example {    public static void main(String[] args) {                // A list of the fruits.        List<String> fruits = Arrays.asList("Grapefruit", "Apple", "Durian",                "Cherry");                // Use of Collections utility method to rearrange the collection.        // Provide a Comparator to the 2nd parameter of the method.        // Comparator has only one abstract method.        // Can write brief with Lambda expressions.        // No need to write the name of the interface,        // no need to write the name of the abstract method.        Collections.sort(fruits, (String o1, String o2) -> {            return o1.compareTo(o2);        });        for (String fruit : fruits) {            System.out.println(fruit);        }    }}
在语句块中,如果只有一个声明,您可以不使用{},以更简洁的方式来编写代码段。
Collections.sort(fruits, (String o1, String o2) -> o1.compareTo(o2)  );  
Java编译程序是甚至知道如何确定什么类型来安排的元素,在这个例子中,它是字符串类型。因此比较器 (Comparator) 一定会明确比较字符串类型的数据。也可以更简明地写出。
Collections.sort(fruits, (o1, o2) -> o1.compareTo(o2));

Lambda表达式的其他例子。

  • Converter.java
package com.yiibai.tutorial.j8.lambda;@FunctionalInterfacepublic interface Converter<F, T> {        T convert(F from);    }
使用Java8之前的版本的格式转换器接口(不使用Lambda)
  • ConverterBefore8Example.java
package com.yiibai.tutorial.j8.lambda;public class ConverterBefore8Example {    public static void main(String[] args) {             // Initialize the Converter object.        Converter<String, Integer> converter = new Converter<String, Integer>() {            @Override            public Integer convert(String from) {                return Integer.parseInt(from);            }        };        // ==> 100        Integer value = converter.convert("0100");        System.out.println("Value = " + value);    }}
使用 Java8 的 Lambda 表达式:
  • ConveterJava8Example.java
package com.yiibai.tutorial.j8.lambda;public class ConveterJava8Example {    public static void main(String[] args) {               // Converter is a FunctionalInterface        // Using Java 8 syntax (Lambda)        // In the case of initializing object from FunctionalInterface.        Converter<String, Integer> converter1 = (String from) -> {            return Integer.parseInt(from);        };        // ==> 100        Integer value1 = converter1.convert("0100");        System.out.println("Value1 = " + value1);        // Or more simply:        Converter<String, Integer> converter2 = (from) -> Integer                .parseInt(from);        // ==> 200        Integer value2 = converter2.convert("00200");        System.out.println("Value2 = " + value2);                     // If the method has only one parameter, can ignore ().        Converter<String, Integer> converter3 = from -> Integer                .parseInt(from);        // ==> 300        Integer value3 = converter3.convert("00300");        System.out.println("Value3 = " + value3);            }}

5- 函数接口API

Java8中有准备一个大量的函数接口,这个在 java.util.function 包提供。 在这里,我们将说明如何使用这些接口,这样就可以更容易理解Lambda表达式及其带来的方便。

5.1- java.util.function.Consumer

Consumer是Java8中可用函数接口,它有一个唯一的抽象方法接受一个输入参数,但这个方法无任务内容返回。
  • Consumer.java
package java.util.function;import java.util.Objects;@FunctionalInterfacepublic interface Consumer<T> {    // Method to accept an input parameter    // And not return anything.   void accept(T t);}
使用 List.forEach(Consumer) 方法:
// java.util.List extends java.util.Collection  (extends Iterable)// Interface java.util.Iterable:default void forEach(Consumer<? super T> action) {Objects.requireNonNull(action);   for (T t : this) {       action.accept(t);   }}
  • ConsumerExample.java
package com.yiibai.tutorial.j8.api;import java.util.Arrays;import java.util.List;import java.util.function.Consumer;public class ConsumerExample {        // Using the method List.forEach (Consumer) with Java <8.    // Print out the elements of the list    public static void beforeJ8() {        List<String> list = Arrays.asList("a", "b", "c", "a1", "a2");        list.forEach(new Consumer<String>() {            @Override            public void accept(String t) {                System.out.println(t);            }        });    }        // Using the method List.forEach(Consumer) with Java 8 syntax.    // (Using lambda expression).    public static void java8Consumer() {        List<String> list = Arrays.asList("a", "b", "c", "a1", "a2");        list.forEach((String t) -> {            System.out.println(t);        });    }        // Using the method List.forEach(Consumer) with Java 8 syntax.    // (Using lambda expression).        // (More simply)    public static void java8ConsumerMoreSimple() {        List<String> list = Arrays.asList("a", "b", "c", "a1", "a2");        list.forEach((String t) -> System.out.println(t));    }    }

5.2- java.util.function.Predicate

Java8可用的谓词函数接口,它有一个唯一的抽象方法接受一个输入参数并方法返回一个布尔值(true/false)。此方法用于计算的输入参数是否适于逻辑。
  • Predicate.java
package java.util.function;import java.util.Objects;@FunctionalInterfacepublic interface Predicate<T> {   // Evaluates this predicate on the given argument.   boolean test(T t);}
在下面的例子中,我们将过滤整数列表,并通过使用Predicate 在 Java8和以前版本的形式来打印奇数的列表。
  • PredicateExample.java
package com.yiibai.tutorial.j8.api;import java.util.Arrays;import java.util.List;import java.util.function.Predicate;import java.util.stream.Stream;public class PredicateExample {        // Use the Stream.filter(Predicate <T>) method way Java <8.    // Filter a list of integers and prints the odd.    public static void beforeJ8() {        List<Integer> list = Arrays.asList(1, 4, 5, 1, 7, 8);        // Stream containing the elements of the list above.        Stream<Integer> stream = list.stream();         // A new stream contains odd        Stream<Integer> stream2 = stream.filter(new Predicate<Integer>() {            @Override            public boolean test(Integer t) {                return t % 2 == 1;            }        });    }        // Use the Stream.filter (Predicate <T>) method way Java>= 8.    // Filter a list of integers and prints the odd.    // Using Lambda expressions.    public static void java8Predicate() {        List<Integer> list = Arrays.asList(1, 4, 5, 1, 7, 8);        // Stream containing the elements of the list above.        Stream<Integer> stream = list.stream();        // A new stream contains odd        Stream<Integer> stream2 = stream.filter(t -> {            return t % 2 == 1;        });        // Stream.forEach(Consumer<T>)        stream2.forEach(t -> System.out.println(t));    }        // Use the method Stream.filter (Predicate <T>) way Java>= 8.    // Filter a list of integers and prints the odd.    // Using Lambda expressions.    // Simple and more concise.    public static void java8ConsumerMoreSimple() {        List<Integer> list = Arrays.asList(1, 4, 5, 1, 7, 8);        // Stream containing the elements of the list above.        Stream<Integer> stream = list.stream();        stream.filter(t -> t % 2 == 1).forEach(t -> System.out.println(t));    }}

5.3- java.util.function.Function

函数就是 Java8 可用函数接口。它有一个唯一的抽象方法接受输入参数,并且方法返回另一个对象。
  • Function.java
package java.util.function;import java.util.Objects;@FunctionalInterfacepublic interface Function<T, R> {   // Applies this function to the given argument.   // return the function result   R apply(T t);}
例如:给出字符串列表,以大写来打印各个元素
  • FunctionExample.java
package com.yiibai.tutorial.j8.api;import java.util.Arrays;import java.util.List;import java.util.function.Function;import java.util.stream.Stream;public class FunctionExample {        // Use Stream.map(Function) with Java syntax <8.    // Print out the molecules in List.    public static void beforeJ8() {        List<String> list = Arrays.asList("a", "c", "B", "e", "g");        // Stream containing the elements of the list.        Stream<String> stream = list.stream();        // Stream.map(Function):        // <R> Stream<R> map(Function<? super T, ? extends R> mapper);         // Returns a new Stream, with the elements were changed.        Stream<String> streamUpper = stream.map(new Function<String, String>() {            @Override            public String apply(String t) {                return t == null ? null : t.toUpperCase();            }        });        streamUpper.forEach(t -> System.out.println(t));    }    public static void java8Function() {        List<String> list = Arrays.asList("a", "c", "B", "e", "g");        // Stream containing the elements of the list.        Stream<String> stream = list.stream();        stream.map(t -> t == null ? null : t.toUpperCase()).forEach(                t -> System.out.println(t));    }    public static void main(String[] args) {        beforeJ8();        java8Function();    }    }
一些相似的函数接口:
  • java.util.function.IntFunction<R>
  • java.util.function.DoubleFunction<R>
  • java.util.function.LongFunction<R>
@FunctionalInterfacepublic interface IntFunction<R> {     R apply(int value);}@FunctionalInterfacepublic interface LongFunction<R> {     R apply(long value);}@FunctionalInterfacepublic interface DoubleFunction<R> {     R apply(double value);}

5.4- java.util.function.Supplier

Supplier就是Java8的可用函数接口,具有一个唯一的的抽象方法没有参数,方法返回一个对象。
  • Supplier.java
package java.util.function;@FunctionalInterfacepublic interface Supplier<T> {    // Gets a result.    T get();}
  • SupplierExample.java
package com.yiibai.tutorial.j8.api;import java.util.function.Supplier;public class SupplierExample {     // A method with parameter is Supplier<String>.    public static void display(Supplier<String> supp) {        System.out.println(supp.get());    }    // Not used Lambda.    public static void beforeJ8() {        display(new Supplier<String>() {            @Override            public String get() {                return "Hello";            }        });        display(new Supplier<String>() {            @Override            public String get() {                return "World";            }        });    }    // Using Lambda expressions.    public static void java8Supplier() {        display(() -> {            return "Hello";        });        display(() -> {            return "World";        });    }        // Using Lambda expressions.    // (Write shorter).    public static void java8SupplierShortest() {        display(() -> "Hello");        display(() -> "World");    }    public static void main(String[] args) {    }}

类似的函数接口:

  • java.util.function.BooleanSupplier
  • java.util.function.IntSupplier
  • java.util.function.DoubleSupplier
  • java.util.function.LongSupplier

6- 方法引用

这关系到Lambda表达式的功能。它使我们能够引用构造函数或方法而不执行它们。
方法引用和Lambda相类似的是,它们都需要由一个兼容函数接口的目标类型。
Java8中可以通过关键字::传递的方法和构造函数的引用
看细节之前,让我们来看看一个简单的例子。
myFunction是一个函数接口。它定义了一个方法有两个参数,int a 和 b,并返回整型值。
  • MyFunction.java
package com.yiibai.tutorial.j8.mref;@FunctionalInterfacepublic interface MyFunction {    // Define a method to do something with a and b   // And returns int.   public int doSomething(int a, int b);   }
MathUtils类有两个静态方法是用来将两个整数相加以及相减。
  • MyMathUtils.java
package com.yiibai.tutorial.j8.mref;public class MyMathUtils {        // This method has two parameters a, b and returns the int.    // It has a structure similar to MyFunction.doSomething(int,int)    public static int sum(int a, int b) {        return a + b;    }        // This method has two parameters a, b and returns the int.    // It has a structure similar to MyFunction.doSomething    public static int minus(int a, int b) {        return a - b;    }}
  • MethodReferenceExample.java
package com.yiibai.tutorial.j8.mref;public class MethodReferenceExample {       // The third parameter of this method is MyFunction (A Functional Interface).    // When using this method:    // You can pass the reference of method, if the method is structured    // similar to the abstract method of MyFunction.    public static int action(int a, int b, MyFunction func) {        return func.doSomething(a, b);    }    public static void main(String[] args) {        int a = 100;        int b = 30;        // Pass the reference of MyMathUtils.sum method.        // ==> 130        int c = action(a, b, MyMathUtils::sum);        System.out.println("c = " + c);        // Pass the reference of MyMathUtils.minus method.        // == 70        int d = action(a, b, MyMathUtils::minus);        System.out.println("d = " + d);        // Pass the reference of Math.subtractExact method.        // ==> 70        int e = action(a, b, Math::subtractExact);        System.out.println("e = " + e);         // Pass the reference of Math.min method.        // ==> 30        int f = action(a, b, Math::min);        System.out.println("f = " + f);    }}

0 0
原创粉丝点击