Java8 新特性全解(保姆级)
·
本文介绍Java8 新特性。
一、接口支持默认方法(default)
Java8 允许接口里编写带具体实现的方法,使用default关键字修饰
优势:接口版本迭代时,不会破坏原有实现类代码,拓展性更强
// 定义学习行为接口
public interface Study {
// 抽象方法,由实现类重写
void learn();
// 默认方法,自带实现逻辑
default void play(String name) {
System.out.println("我和" + name + "一起玩");
}
}
// 接口实现类
public class Student implements Study {
// 重写抽象学习方法
@Override
public void learn() {
System.out.println("认真学习Java8");
}
}
// 调用默认方法
new Student().play("小码哥");
二、Lambda 表达式
作用:简化冗余的匿名内部类写法,精简代码结构
传统匿名内部类写法
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Comparator;
public class LambdaOldDemo {
public static void main(String[] args) {
List<String> list = Arrays.asList("peter", "anna", "mike");
// 字符串集合倒序排序
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return b.compareTo(a);
}
});
}
}
Lambda精简写法
import java.util.Arrays;
import java.util.List;
public class LambdaNewDemo {
public static void main(String[] args) {
List<String> list = Arrays.asList("peter", "anna", "mike");
// lambda表达式实现排序逻辑
Collections.sort(list, (a, b) -> b.compareTo(a));
}
}
进一步简化写法
list.sort((a, b) -> b.compareTo(a));
三、函数式接口(@FunctionalInterface)
定义:仅包含一个抽象方法的接口,是Lambda表达式使用的前提
注解用于编译校验格式合法性
// 标记为函数式接口
@FunctionalInterface
public interface Converter<T, R> {
// 通用类型转换抽象方法
R convert(T from);
}
public class FuncInterfaceTest {
public static void main(String[] args) {
// lambda实现字符串转数字
Converter<String, Integer> c = s -> Integer.valueOf(s);
Integer num = c.convert("123");
System.out.println(num); // 输出123
}
}
四、方法引用(::)
基于Lambda再次精简,直接调用现有方法、构造方法
静态方法引用
// 引用Integer静态转换方法
Converter<String, Integer> c = Integer::valueOf;
实例方法引用
public class Demo {
// 截取字符串首字符
public String first(String s) {
return s.charAt(0)+"";
}
public static void main(String[] args) {
Demo d = new Demo();
// 引用实例对象方法
Converter<String, String> c = d::first;
System.out.println(c.convert("Java")); // 输出J
}
}
构造器引用
// 用户实体类
class User {
String name;
// 带参构造方法
User(String name) {
this.name = name;
}
}
// 函数式工厂接口
@FunctionalInterface
interface UserFactory {
User create(String name);
}
public class ConstructorRefTest {
public static void main(String[] args) {
// 引用构造器创建对象
UserFactory f = User::new;
User u = f.create("szxmg");
}
}
五、Lambda 变量访问规则
- 局部变量默认隐式final修饰,不可二次赋值修改
public class LambdaVarTest {
public static void main(String[] args) {
int x = 1;
// 使用外层局部变量运算
Converter<Integer, String> c = i -> String.valueOf(i + x);
// x = 2; 重新赋值会编译报错
}
}
- 成员变量、静态变量支持读写操作
- Lambda内部无法直接访问接口默认方法
六、四大内置函数式接口(高频常用)
1. Predicate 断言判断接口,返回布尔结果
import java.util.function.Predicate;
public class PredicateDemo {
public static void main(String[] args) {
// 判断字符串长度是否大于3
Predicate<String> p = s -> s.length() > 3;
System.out.println(p.test("java")); // 输出true
}
}
2. Function 类型转换接口,入参出参不同
import java.util.function.Function;
public class FunctionDemo {
public static void main(String[] args) {
// 获取字符串长度
Function<String, Integer> f = s -> s.length();
System.out.println(f.apply("szxmg")); // 输出5
}
}
3. Consumer 消费接口,只处理数据无返回值
import java.util.function.Consumer;
public class ConsumerDemo {
public static void main(String[] args) {
// 打印拼接文本
Consumer<String> con = s -> System.out.println("你好:"+s);
con.accept("双栈小码哥");
}
}
4. Supplier 供给接口,无入参只返回数据
import java.util.function.Supplier;
import java.util.Date;
public class SupplierDemo {
public static void main(String[] args) {
// 获取当前系统时间
Supplier<Date> sup = Date::new;
System.out.println(sup.get());
}
}
七、Stream 流
简化集合操作,链式完成筛选、排序、转换、统计等功能
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class StreamDemo {
public static void main(String[] args) {
// 初始化测试集合数据
List<String> list = Arrays.asList("ddd2", "aaa2", "bbb1", "aaa1", "bbb3", "ccc");
// filter:过滤以a开头的元素
list.stream()
.filter(s -> s.startsWith("a"))
.forEach(System.out::println);
// sorted:自然排序
list.stream().sorted().forEach(System.out::println);
// map:字符统一转为大写
list.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
// anyMatch:判断是否存在指定开头元素
boolean hasA = list.stream().anyMatch(s -> s.startsWith("a"));
// count:统计符合条件元素个数
long cnt = list.stream().filter(s -> s.startsWith("b")).count();
// reduce:拼接所有元素字符串
Optional<String> res = list.stream().reduce((s1, s2) -> s1 + "-" + s2);
res.ifPresent(System.out::println);
// parallelStream:并行流,多线程加速处理
list.parallelStream().forEach(System.out::println);
}
}
八、Map集合新增实用方法
便捷实现不存在赋值、计算更新、合并数据等操作
import java.util.HashMap;
import java.util.Map;
public class MapNewFuncDemo {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
// 键不存在时才存入数据
map.putIfAbsent(1, "Java");
// 根据键动态计算赋值
map.computeIfAbsent(2, k -> "Python");
// 合并相同键的字符串内容
map.merge(1, "8", String::concat);
}
}
九、全新日期时间 API(java.time)
替代老旧线程不安全的Date、Calendar类,使用更简洁稳定
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class TimeApiDemo {
public static void main(String[] args) {
// 获取当前日期
LocalDate today = LocalDate.now();
// 获取当前时分秒
LocalTime now = LocalTime.now();
// 获取完整日期时间
LocalDateTime dt = LocalDateTime.now();
// 自定义时间格式化模板
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 格式化输出时间
System.out.println(dt.format(fmt));
}
}
十、重复注解(@Repeatable)
支持同一个位置多次添加相同类型注解
import java.lang.annotation.Repeatable;
// 容器注解
@interface Hints {
Hint[] value();
}
// 可重复标记注解
@Repeatable(Hints.class)
@interface Hint {
String value();
}
// 同一类上重复使用注解
@Hint("a")
@Hint("b")
class Demo {}
总结
Java8 核心知识点汇总:
- 接口 default 默认方法
- Lambda 表达式简化代码
- 函数式接口规范定义
- 方法引用进一步精简写法
- Stream流高效处理集合
- Map集合拓展操作方法
- 线程安全的新日期API
- 支持重复注解特性
更多推荐
所有评论(0)