Java8语法和新功能,Java8语法新功能
分享于 点击 16841 次 点评:233
Java8语法和新功能,Java8语法新功能
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 Formula public class FormulaImpl implements Formula { // implements abstract method @Override public 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; @FunctionalInterface public 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; @FunctionalInterface public 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; @FunctionalInterface public 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; @FunctionalInterface public 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; @FunctionalInterface public 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>
@FunctionalInterface public interface IntFunction<R> { R apply(int value); } @FunctionalInterface public interface LongFunction<R> { R apply(long value); } @FunctionalInterface public interface DoubleFunction<R> { R apply(double value); }
5.4- java.util.function.Supplier
Supplier就是Java8的可用函数接口,具有一个唯一的的抽象方法没有参数,方法返回一个对象。- Supplier.java
package java.util.function; @FunctionalInterface public 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; @FunctionalInterface public 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); } }
相关文章
- 暂无相关文章
用户点评