Appearance
- 接口中默认方法与静态方法
- 函数式接口(Functional Interface)
- Lambda表达式(Lambda Expressions)
- 流API(Streams API)
- Optional 类
- 新的日期时间API(New Date-Time API)
1、接口中默认方法与静态方法
在Java 8之前,接口只能有方法声明,而不能有方法实现。这意味着一旦接口被更改(比如添加新方法),所有实现了该接口的类都必须随之修改以实现新添加的方法。
Java 8引入的default和static方法正是为了解决这个问题。
default方法
作用:
default方法允许我们在接口中添加有具体实现的非抽象方法。这意味着实现接口的类可以不用实现这些default方法。用途: 这对于向现有接口添加新功能非常有用,因为它不会破坏实现该接口的现有类的功能。
类比: 想象一下,有一个标准的建筑蓝图(接口)。突然,需要在所有这样的建筑中添加一个新的功能(比如中央供暖)。
default方法就像是一个标准的中央供暖系统设计,可以直接加入到现有的蓝图中,而不需要重新设计整个建筑。
static方法
作用:
static方法允许我们在接口中添加静态方法。这些方法可以直接通过接口来调用,而不需要一个接口的实例。用途:
static方法通常用于提供一些与接口相关的工具方法。类比: 如果接口是一种服务的标准(比如邮寄服务),那么
static方法就像是可以直接从服务标准本身获得的额外帮助或工具,如一个在线邮资计算器。
具体使用示例
interface MyInterface {
// 一个默认方法
default void newMethod() {
System.out.println("This is a default method");
}
// 一个静态方法
static void anotherNewMethod() {
System.out.println("This is a static method");
}
}
// 实现接口的类
class MyClass implements MyInterface {
// 不需要实现newMethod()
}
public class Main {
public static void main(String[] args) {
MyClass myClass = new MyClass();
myClass.newMethod(); // 调用默认方法
MyInterface.anotherNewMethod(); // 直接调用接口的静态方法
}
}在这个例子中,MyClass实现了MyInterface但没有实现newMethod()方法,因为它是一个默认方法。
同时,可以直接通过MyInterface调用静态方法anotherNewMethod()。
有一种情况需要重写 default 的接口方法,注意一下,示例如下:
public interface InterfaceNew {
static void sm() {
System.out.println("interface提供的方式实现");
}
static void sm2() {
System.out.println("interface提供的方式实现");
}
default void def() {
System.out.println("interface default方法");
}
default void def2() {
System.out.println("interface default2方法");
}
//须要实现类重写
void f();
}
public interface InterfaceNew1 {
default void def() {
System.out.println("InterfaceNew1 default方法");
}
}如果有一个类既实现了 InterfaceNew 接口又实现了 InterfaceNew1接口,它们都有def(),并且 InterfaceNew 接口和 InterfaceNew1接口没有继承关系的话,这时就必须重写def()。
不然的话,编译的时候就会报错。
public class InterfaceNewImpl implements InterfaceNew , InterfaceNew1{
public static void main(String[] args) {
InterfaceNewImpl interfaceNew = new InterfaceNewImpl();
interfaceNew.def();
}
@Override
public void def() {
InterfaceNew1.super.def();
}
@Override
public void f() {
}
}Java8中,接口和抽象类的区别
- interface 和 class 的区别,主要有:
- 接口多实现,类单继承
- 接口的方法是 public abstract 修饰,变量是 public static final 修饰。 abstract class 可以用其他修饰符
- interface 的方法是更像是一个扩展插件。而 abstract class 的方法是要继承的。
interface 新增default和static修饰的方法,为了解决接口的修改与现有的实现不兼容的问题,并不是为了要替代abstract class。
2、函数式接口(Functional Interface)
函数式接口(Functional Interface)是Java 8引入的一个重要概念,它是Java对函数式编程支持的一部分。
定义
函数式接口是只有一个抽象方法的接口。尽管接口可以包含多个默认方法、静态方法,但只能有一个抽象方法。这种接口的主要目的是为了与Lambda表达式结合使用。
@FunctionalInterface注解
虽然不是强制性的,但通常会使用@FunctionalInterface注解来标记函数式接口。这个注解有助于编译器识别意图,并在接口不是有效的函数式接口时生成编译时错误。
函数式接口示例:
@FunctionalInterface
interface Greeting {
String sayHello(String name);
}这个Greeting接口定义了一个接受一个字符串参数并返回一个字符串的方法。
由于它只有一个抽象方法,所以它是一个函数式接口。
使用场景
函数式接口在Java 8中引入Lambda表达式时变得非常重要。Lambda表达式提供了一种简洁的方式来实现函数式接口,从而使代码更简洁、更易读。
可以将函数式接口想象成一种特殊的工具套件。这个套件里只有一个工具槽(抽象方法),但你可以以多种方式(Lambda表达式、方法引用)填充这个槽。这就像是一个可定制的工具,你可以根据需要插入不同的功能。
函数式接口在Java中的很多地方都有使用,例如:
- 在
java.util.function包中,Java 8引入了一系列标准的函数式接口,如Predicate<T>、Function<T,R>、Consumer<T>等。 - 在集合框架中,它们被用于简化迭代、过滤和转换操作。
- 在并发编程中,例如使用
Runnable或Callable接口。
3、Lambda 表达式
Lambda表达式是Java 8中一个非常重要的新特性,它为Java带来了一种简洁的方式来表示函数式接口的实例。
Lambda表达式主要用于提供一种简洁、表达式风格的方法来表示可以传递的匿名函数。这种表达方式非常适合创建简短的、只使用一次的方法版本。
语法格式
语法格式
(parameters) -> expression 或
(parameters) ->{ statements; }- parameters
- 与方法定义中的参数列表类似。对于单个参数,可以省略括号
->- Lambda表达式的核心,用于分隔参数列表和Lambda体
- Lambda体
- 可以是一个表达式或一个代码块。表达式体会返回一个值,而代码块可以包含零个或多个语句。
简易示例
使用示例
Lambda表达式通常与函数式接口一起使用。函数式接口是只有一个抽象方法的接口,这意味着Lambda表达式可以为该抽象方法提供实现。
假设我们有一个简单的函数式接口:
@FunctionalInterface
interface StringOperation {
int getLength(String s);
}不使用Lambda表达式,我们可能需要这样实现:
StringOperation operation = new StringOperation() {
@Override
public int getLength(String s) {
return s.length();
}
};使用Lambda表达式,我们可以这样简化:
StringOperation operation = s -> s.length();替代匿名内部类
平时开发经常会用到 Runnable 接口、Comparator 接口、Listener 接口 这三个接口,下面分别就看一下他们的使用示例。
Runnable 接口
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("The runable now is using!");
}
}).start();
//用lambda
new Thread(() -> System.out.println("It's a lambda function!")).start();Comparator 接口
List<Integer> strings = Arrays.asList(1, 2, 3);
Collections.sort(strings, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;}
});
//Lambda
Collections.sort(strings, (Integer o1, Integer o2) -> o1 - o2);
//分解开
Comparator<Integer> comparator = (Integer o1, Integer o2) -> o1 - o2;
Collections.sort(strings, comparator);Listener 接口
JButton button = new JButton();
button.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
e.getItem();
}
});
//lambda
button.addItemListener(e -> e.getItem());集合上使用
在集合上的应用
Lambda表达式特别适合用在集合的操作上,比如forEach、map、filter等方法:
List<String> list = Arrays.asList("Java", "Python", "C++");
// 使用Lambda表达式迭代
list.forEach(element -> System.out.println(element));
// 使用Lambda表达式和Stream API进行过滤
list.stream()
.filter(s -> s.startsWith("J"))
.forEach(System.out::println);void lamndaFor() {
List<String> strings = Arrays.asList("1", "2", "3");
//传统foreach
for (String s : strings) {
System.out.println(s);
}
//Lambda foreach
strings.forEach((s) -> System.out.println(s));
//or
strings.forEach(System.out::println);
//map
Map<Integer, String> map = new HashMap<>();
map.forEach((k,v)->System.out.println(v));
}方法的引用
Java 8 允许使用 :: 关键字来传递方法或者构造函数引用,无论如何,表达式返回的类型必须是 functional-interface。
public class LambdaClassSuper {
LambdaInterface sf(){
return null;
}
}
public class LambdaClass extends LambdaClassSuper {
public static LambdaInterface staticF() {
return null;
}
public LambdaInterface f() {
return null;
}
void show() {
//1.调用静态函数,返回类型必须是functional-interface
LambdaInterface t = LambdaClass::staticF;
//2.实例方法调用
LambdaClass lambdaClass = new LambdaClass();
LambdaInterface lambdaInterface = lambdaClass::f;
//3.超类上的方法调用
LambdaInterface superf = super::sf;
//4. 构造方法调用
LambdaInterface tt = LambdaClassSuper::new;
}
}访问变量
int i = 0;
Collections.sort(strings, (Integer o1, Integer o2) -> o1 - i);
//i =3;lambda 表达式可以引用外边变量,但是该变量默认拥有 final 属性,不能被修改,如果修改,编译时就报错。
to be contined......
4、Stream
Stream 是什么
java 新增了 java.util.stream 包,它和之前的流大同小异。之前接触最多的是资源流,比如java.io.FileInputStream,通过流把文件从一个地方输入到另一个地方,它只是内容搬运工,对文件内容不做任何 CRUD。
Stream依然不存储数据,不同的是它可以检索(Retrieve)和逻辑处理集合数据、包括筛选、排序、统计、计数等。可以想象成是 Sql 语句。
它的源数据可以是 Collection、Array 等。由于它的方法参数都是函数式接口类型,所以一般和 Lambda 配合使用。
流类型
- stream 串行流
- parallelStream 并行流,可多线程执行
Stream 常用方法
stream(),parallelStream()filter()findAny()findFirst()sortforEachvoidmap(), reduce()flatMap()- 将多个Stream连接成一个Streamcollect(Collectors.toList())distinct,limitcountmin,max,summaryStatistics
5、Optional
参考: https://javaguide.cn/java/new-features/java8-common-new-features.html#optional
Optional是Java 8引入的一个容器类,用于表示一个值可能存在或不存在。它提供了一种更优雅的方法来处理可空值,从而减少NullPointerException的风险。
to be contined...
6、Date-Time API
to be contined....
参考