虽然java8已经快过期了,但是作为技术总结,还是简单总结一下。
目录
1所谓的java8新特性有哪些
2.java8新特性详解
2.1 lambda表达式
1.概述
2.示例代码
3. Lambda的语法规则
4.函数式接口@FunctionalInterface注解
5. 练习
6.Lambda表达式的使用前提
7.有价值的参考文章
3.接口的增强
3.1. JDK8中接口的新增
3.2 默认方法
1为什么要增加默认方法
2接口默认方法的格式
3 接口中默认方法的使用
3.3. 静态方法
1 语法规则
2 静态方法的使用
3 两者的区别介绍
4.函数式接口
4.1定义
4.2.可看成函数式接口的接口
4.3函数式接口存在的意义
4.4 常见的几种函数是接口的分类
Lambda表达式
接口的增强
函数式接口
方法引用
Stream API
Optional
新时间日期API
其他新特性
Java中的Lambda表达式是JDK8中的一种新特性,它允许我们将一段代码(这段代码可以理解为一个接口的实现)当成参数传递给某个方法,然后进行业务处理,这种方式更像是一种函数式编程风格,可以让代码结构更简洁,开发效率更高。
比较让人容易迷乱的是lambda的几个简化写法。后面会一一细说。
lambda的学习点也就两个,一个是把一点代码作为参数传递,一个是它的简化写法。
public static void main(String[] args) {
// 开启一个新的线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("新线程中执行的代码 : "+Thread.currentThread().getName());
}
}).start();
System.out.println("主线程中的代码:" + Thread.currentThread().getName());
}
从这段代码看到,将Runnable接口实现作为一个参数传递,创建了Thread类后,调用了start()。这也是lamnda的核心思想所在。当然在使用中,我们更多的使用在这个基础上的简化写法。
分析上面代码,在创建Thread对象时,其实在乎的作为入参的这段代码的结果,这个结果才是Thread对象创建需要的。换句话说就是这段代码的params和body体。而lambda简化的精髓就在于,只需要关注作为参数的这个代码块的params和body体,其他的编译器会通过底层的类型推断编译时自动补充。(因此能用lanbda的也是一些常用的固定写法:编译器能识别到的写法。事实上必须入参代码块是个函数式接口。
new Thread(() ->System.out.println("新线程中执行的代码 : "+Thread.currentThread().getName())).start();
上面是简化后的写法。看起来是不是很清爽,因为在作为入参的代码块的组成元素:
访问修饰符
返回值类型
方法名
参数列表
body体
中为只关注了参数列表(没有就用()表示)和body体。
Lambda的标准格式由3个部分组成:
(参数类型 参数名称) -> { 代码体; }
格式说明:
(参数类型 参数名称):参数列表
{代码体;} :方法体
-> : 箭头,分割参数列表和方法体
常见结构如下:
() -> statement |
Lambda表达式有返回值,返回值的类型也由编译器推理得出。如果
Lambda表达式中的语句块只有一行,则可以不用使用return语句,下列两个代码片段效果相同:
Arrays.asList( "a", "b", "d" )
.sort( ( e1, e2 ) -> e1.compareTo( e2 ) );
Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> {
int result = e1.compareTo( e2 );
return result;
} );
/**
* @FunctionalInterface
* 这是一个标志注解,被该注解修饰的接口只能声明一个抽象方法
*/
@FunctionalInterface
public interface UserService {
void show();
}
public interface UserService {
void show();
}
public class Demo03Lambda {
public static void main(String[] args) {
goShow(new UserService() {
@Override
public void show() {
System.out.println("show 方法执行了...");
}
});
System.out.println("----------");
goShow(() -> { System.out.println("Lambda show 方法执行了..."); });
}
public static void goShow(UserService userService){
userService.show();
}
}
输出
show 方法执行了...
----------
Lambda show 方法执行了...
Lambda表达式的语法是非常简洁的,但是Lambda表达式不是随便使用的,使用时有几个条件要特别注意
方法的参数或局部变量类型必须为接口才能使用Lambda
接口中有且仅有一个抽象方法(@FunctionalInterface)
关于Java Lambda表达式看这一篇就够了
在JDK8中针对接口有做增强,在JDK8之前
interface 接口名{ 静态常量; 抽象方法; }
JDK8之后对接口做了增加,接口中可以有默认方法和静态方法
interface 接口名{
静态常量;
抽象方法;
默认方法;
静态方法; }
在JDK8以前接口中只能有抽象方法和静态常量,会存在以下的问题:
如果接口中新增抽象方法,那么实现类都必须要抽象这个抽象方法,非常不利于接口的扩展的
package com.bobo.jdk.inter;
public class Demo01Interface {
public static void main(String[] args) {
A a = new B();
A c = new C();
}
}
interface A{
void test1();
// 接口中新增抽象方法,所有实现类都需要重写这个方法,不利于接口的扩展
void test2();
}
class B implements A{
@Override
public void test1() {
}
@Override
public void test2() {
}
}
class C implements A{
@Override
public void test1() {
}
@Override
public void test2() {
}
}
接口中默认方法的语法格式是
interface 接口名{
修饰符 default 返回值类型 方法名{
方法体;
}
}
package com.bobo.jdk.inter;
public class Demo01Interface {
public static void main(String[] args) {
A a = new B();
a.test3();
A c = new C();
c.test3();
}
}
interface A{
void test1();
// 接口中新增抽象方法,所有实现类都需要重写这个方法,不利于接口的扩展
void test2();
/**
* 接口中定义的默认方法
* @return
*/
public default String test3(){
System.out.println("接口中的默认方法执行了...");
return "hello";
}
}
class B implements A{
@Override
public void test1() {
}
@Override
public void test2() {
}
@Override
public String test3() {
System.out.println("B 实现类中重写了默认方法...");
return "ok ...";
}
}
class C implements A{
@Override
public void test1() {
}
@Override
public void test2() {
}
}
接口中的默认方法有两种使用方式
实现类直接调用接口的默认方法
实现类重写接口的默认方法
换句话说就是,需要用的实现类可以重写或者直接调用,不需要用的实现类,可以不用管接口中的默认方法的存在
JDK8中为接口新增了静态方法,作用也是为了接口的扩展
interface 接口名{
修饰符 static 返回值类型 方法名{
方法体;
}
}
package com.bobo.jdk.inter;
public class Demo01Interface {
public static void main(String[] args) {
A a = new B();
a.test3();
A c = new C();
c.test3();
A.test4();
}
}
interface A{
void test1();
// 接口中新增抽象方法,所有实现类都需要重写这个方法,不利于接口的扩展
void test2();
/**
* 接口中定义的默认方法
* @return
*/
public default String test3(){
System.out.println("接口中的默认方法执行了...");
return "hello";
}
/**
* 接口中的静态方法
* @return
*/
public static String test4(){
System.out.println("接口中的静态方法....");
return "Hello";
}
}
class B implements A{
@Override
public void test1() {
}
@Override
public void test2() {
}
@Override
public String test3() {
System.out.println("B 实现类中重写了默认方法...");
return "ok ...";
}
}
class C implements A{
@Override
public void test1() {
}
@Override
public void test2() {
}
}
接口中的静态方法在实现类中是不能被重写的,调用的话只能通过接口类型来实现: 接口名.静态方法名();
默认方法通过实例调用,静态方法通过接口名调用
默认方法可以被继承,实现类可以直接调用接口默认方法,也可以重写接口默认方法
静态方法不能被继承,实现类不能重写接口的静态方法,只能使用接口名调用,专属于接口
当且仅当,一个接口被@FunctionInterface注解,且接口中有且只有一个抽象方法的接口
注意:
1.一旦被@FunctionInteface注解后,接口中有多个抽象方法就会报错
2.其他方法:
* 函数时接口就中的静态方法,默认方法
接口没有被@FunctionInterface注解,但是接口中只有一个抽象方法,这种接口也可以堪称函数式接口
配和 lambda表达式 操作
1 消费性接口: 有入参没有返回值,如 Consumer
2 函数式接口: 有入参,入参在接口方法中计算后返回接口,如 Function
3 判定式样接口: 有入参,返回值是boolean 类型 如 Predicate
4 供给式接口: 无参数,有返回值 ,如 supply
package com.tmooc.interfacedefaultandstaticmethod;
import java.sql.SQLOutput;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class FunctionIntefaceDemo {
public static void main(String[] args) {
//创建函数式接口实例
Fun fun = new Fun() {
@Override
public void domethod01() {
System.out.println("函数式接口被成功调用");
}
};
//调用函数式接口中唯一的抽象方法
fun.domethod01();
System.out.println("=======================================");
//================================常见的集中函数式接口类型举例================================
//消费型接口
Consumer consumer = new Consumer() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
consumer.accept("消费型接口成功被调用");
System.out.println("=======================================");
//函数式接口举例
Function function = new Function() {
@Override
public Integer apply(String s) {
return Integer.parseInt(s);
}
};
Integer result = function.apply("100");
System.out.println(result);
consumer.accept("函数型接口成功被调用");
System.out.println("=======================================");
Predicate predicate = new Predicate() {
@Override
public boolean test(String s) {
return false;
}
};
boolean res = predicate.test("测试");
System.out.println(res);
System.out.println("判定型接口被成功调用");
System.out.println("=======================================");
Supplier supplier = new Supplier() {
@Override
public Integer get() {
return 0;
}
};
Integer ress = supplier.get();
System.out.println(ress);
System.out.println("供给型接口被成功调用");
}
}
@FunctionalInterface
interface Fun {
//函数式接口中的唯一抽象方法
void domethod01();
//其他的都是一个或多个静态方法或则默认方法
static int domethod2() {
return 1;
}
default void domethod03() {
}
}