共计 4812 个字符,预计需要花费 13 分钟才能阅读完成。
目前咱们学习 Java 次要用到的应该就是 Java8 了,或者说大部分企业以后应用的也是 Java8。那么既然 Java8 的利用如此之宽泛,肯定有一些亮点所在:
Lambda 表达式
函数式接口
办法援用与结构器援用
Stream API
接口中的默认办法与静态方法
新工夫日期 API
其余新个性
速度更快、代码更少(减少了新的语法 Lambda 表达式)、弱小的 Stream API、便于并行、最大化缩小空指针异样 Optional。
2. 为什么要应用 Lambda 表达式?
Lambda 是一个 匿名函数 数,咱们能够把 Lambda 表达式了解为是 一段能够传递的 代码(将代码像数据一样进行传递)。能够写出更简洁、更灵便的代码。作为一种更紧凑的代码格调,使 Java 语言表达能力失去了晋升。
3.Lambda 表达式的根本语法
Lambda 表达式在 Java 语言中引入了一个新的语法元素和操作符。这个操作符为“->”,该操作符被称为 Lambda 操作符或剪头操作符。
它将 Lambda 分为两个局部:
左侧:指定了 Lambda 表达式须要的所有参数。
右侧:指定了 Lambda 体,即 Lambda 表达式要执行的性能。
具体的就看上面的代码案例。
package com.szh.java8;
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
/**
- Lambda 表达式的根底语法:
- Java8 中引入了一个新的操作符 “->”
- 该操作符称为 箭头操作符 或 Lambda 操作符
- 箭头操作符将 Lambda 表达式拆分成两局部:
*
- 左侧:Lambda 表达式的参数列表
- 右侧:Lambda 表达式中所需执行的性能,即 Lambda 体
*
- Lambda 表达式须要“函数式接口”的反对
- 函数式接口:接口中只有一个形象办法的接口, 称为函数式接口
- 能够应用注解 @FunctionalInterface 润饰, 能够查看是否是函数式接口
*/
public class MyTest2 {
/**
* 语法格局一:无参数,无返回值
* () -> System.out.println(“Hello World!!!”);
*/
@Test
public void test1() {
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println(“Hello World!!!”);
}
};
r1.run();
System.out.println(“—————————“);
Runnable r2 = () -> System.out.println(“Hello World!!!”);
r2.run();
}
}
package com.szh.java8;
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
/**
- Lambda 表达式的根底语法:
- Java8 中引入了一个新的操作符 “->”
- 该操作符称为 箭头操作符 或 Lambda 操作符
- 箭头操作符将 Lambda 表达式拆分成两局部:
*
- 左侧:Lambda 表达式的参数列表
- 右侧:Lambda 表达式中所需执行的性能,即 Lambda 体
*
- Lambda 表达式须要“函数式接口”的反对
- 函数式接口:接口中只有一个形象办法的接口, 称为函数式接口
- 能够应用注解 @FunctionalInterface 润饰, 能够查看是否是函数式接口
*/
public class MyTest2 {
/**
* 语法格局二:有一个参数,无返回值
* (x) -> System.out.println(x)
* 此语法格局中小括号能够省略不写,等价于
* x -> System.out.println(x)
*/
@Test
public void test2() {
Consumer<String> consumer = (str) -> System.out.println(str);
consumer.accept(“Lambda 表达式真好用 ….”);
}
}
package com.szh.java8;
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
/**
- Lambda 表达式的根底语法:
- Java8 中引入了一个新的操作符 “->”
- 该操作符称为 箭头操作符 或 Lambda 操作符
- 箭头操作符将 Lambda 表达式拆分成两局部:
*
- 左侧:Lambda 表达式的参数列表
- 右侧:Lambda 表达式中所需执行的性能,即 Lambda 体
*
- Lambda 表达式须要“函数式接口”的反对
- 函数式接口:接口中只有一个形象办法的接口, 称为函数式接口
- 能够应用注解 @FunctionalInterface 润饰, 能够查看是否是函数式接口
*/
public class MyTest2 {
/**
* 语法格局三:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
*/
@Test
public void test3() {
Comparator<Integer> comparator = (x,y) -> {
System.out.println(“ 函数式接口 ….”);
return Integer.compare(x,y);
};
}
}
package com.szh.java8;
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
/**
- Lambda 表达式的根底语法:
- Java8 中引入了一个新的操作符 “->”
- 该操作符称为 箭头操作符 或 Lambda 操作符
- 箭头操作符将 Lambda 表达式拆分成两局部:
*
- 左侧:Lambda 表达式的参数列表
- 右侧:Lambda 表达式中所需执行的性能,即 Lambda 体
*
- Lambda 表达式须要“函数式接口”的反对
- 函数式接口:接口中只有一个形象办法的接口, 称为函数式接口
- 能够应用注解 @FunctionalInterface 润饰, 能够查看是否是函数式接口
*/
public class MyTest2 {
/**
* 语法格局四:若 Lambda 体中只有一条语句,
* 则 return 和 大括号都能够省略不写
* Lambda 表达式的参数列表的数据类型能够省略不写,
* 因为 JVM 编译器通过上下文推断出,数据类型,即“类型推断”
*/
@Test
public void test4() {
Comparator<Integer> comparator = (x,y) -> Integer.compare(x,y);
}
}
上述 Lambda 表达式中的参数类型都是由编译器推断得出的。Lambda 表达式中无需指定类型,程序仍然能够编译,这是因为 java 培训中依据程序的上下文,在后盾推断出了参数的类型。Lambda 表达式的类型依赖于上下文环境,是由编译器推断进去的。这就是所谓的“类型推断”。
4. 自定义函数式接口
只蕴含一个形象办法的接口,称为 函 数 式 接 口。
你能够通过 Lambda 表达式来创立该接口的对象。(若 Lambda 表达式抛出一个受检异样,那么该异样须要在指标接口的形象办法上进行申明)
咱们能够在任意函数式接口上应用 @FunctionalInterface 注解,这样做能够查看它是否是一个函数式接口,同时 javadoc 也会蕴含一条申明,阐明这个接口是一个函数式接口。
就像 Runnable 接口一样,它就是一个典型的函数式接口。
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface {@code Runnable} is used
* to create a thread, starting the thread causes the object’s
* {@code run} method to be called in that separately executing
* thread.
* <p>
* The general contract of the method {@code run} is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
那么咱们必定也能够自定义函数式接口了,首先是没有泛型的自定义函数式接口。
package com.szh.java8.two;
/**
*
*/
@FunctionalInterface
public interface MyFunction {
public String getValue(String str);
}
package com.szh.java8.two;
/**
*
*/
public class TestLambda {
private static String strHandler(String str,MyFunction mf) {
return mf.getValue(str);
}
public static void main(String[] args) {
// 去除首尾空格
String trimStr = strHandler(“\t\t\t 张起灵 - 小哥 “,(str) -> str.trim());
System.out.println(trimStr);
// 转为大写
String upperStr = strHandler(“hello world”,str -> str.toUpperCase());
System.out.println(upperStr);
// 局部截取
String newStr = strHandler(“ 学 Java 的冷少 ”,(str) -> str.substring(0,5));
System.out.println(newStr);
}
}
上面再来看一个带泛型的函数式接口。
package com.szh.java8.three;
/**
*
*/
@FunctionalInterface
public interface MyFunction2<T,R> {
public R getValue(T t1,T t2);
}
package com.szh.java8.three;
import com.szh.java8.two.MyFunction;
/**
*
*/
public class TestLambda {
private static void operation(Long l1,Long l2,MyFunction2<Long,Long> mf) {
System.out.println(mf.getValue(l1,l2));
}
public static void main(String[] args) {
// 和
operation(100L,200L,(x,y) -> x + y);
// 积
operation(300L,500L,(x,y) -> x * y);
}
}
作为参数传递 Lambda 表达式:为了将 Lambda 表达式作为参数传递,接管 Lambda 表达式的参数类型必须是与该 Lambda 表达式兼容的函数式接口的类型。