Java8新特性学习
Java8新特性学习
- 为啥使用Lambda表达式
- Lambda表达式的基础语法
- 无参无返回
- 有参无返回
- 一个参数
- 多参
- 单个语句体
- 类型推断
- 四大内置核心函数式接口
- 其他接口
- 方法引用与构造器引用
- Stream
- 简介
- 什么是Stream
- Stream操作步骤
- 创建Stream
- 中间操作
- 终止操作(终端操作)
- 归约与收集
- 并行流与顺序流
- Fork/Join框架
- Optional类
- 接口中的默认方法与静态方法
- 时间和日期
- 传统时间格式化
- jdk8中的日期
- 时间校正器
- 时区的处理
- 重复注解与类型注解
为啥使用Lambda表达式
Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码 像数据一样进行传递)。可以写出更简洁、更 灵活的代码。作为一种更紧凑的代码风格,使 Java的语言表达能力得到了提升。
Lambda表达式的基础语法
Java8中引入了一个新的操作符>
该操作符称为箭头操作符或Lambda操作符箭头操作符将 Lambda 表达式拆分成两部分:
左侧:Lambda 表达式的参数列表
右侧:Lambda 表达式中所需执行的功能,即Lambda 体
无参无返回
语法格式一: 无参数,无返回值
() -> System.out.println("hello lambda");
有参无返回
语法格式二:有一个参数,并且无返回值
(x) -> System.out.println(x)
一个参数
语法格式三 : 若只有一个参数,小括号可以省略不写
x -> System.out.println(x)
多参
语法格式四:有两个以上的参数,并且Lambda体中有多条语句
Comparator<Integer> comparator = (x, y) -> {System.out.println("函数式接口");return Integer.compare(x, y);
};
单个语句体
语法格式五:若Lambda体中只有一条语句,return和大括号都可以省略不写
Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);
类型推断
语法格式六:Lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即"类型推断"
Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);
上联:左右遇一括号省
下联:左侧推断类型省
横批:能省则省
二、Lambda 表达式需要“函数式接口”的支持
函数式接口:接口中只有一个抽象方法的接口,称为函数式接口。可以使用注解@FunctionalInterface 修饰可以检查是否是函数式接口
package com.company;import org.junit.Test;import java.util.Comparator;
import java.util.function.Consumer;/*** @author Helen* @version 1.0* @createTime 2023/1/3 23:02* @Description Lambda基础语法*/
public class TestLambda2 {/*** 语法格式一: 无参数,无返回值*/@Testpublic void test() {Runnable runnable = () -> System.out.println("Hello Lambda!");runnable.run();}/*** 语法格式二:有一个参数,并且无返回值*/@Testpublic void test2() {Consumer consumer = (x) -> System.out.println(x);consumer.accept("我是上柜");}/*** 语法格式三 : 若只有一个参数,小括号可以省略不写*/@Testpublic void test3() {Consumer consumer = x -> System.out.println(x);consumer.accept("我是上柜");}/*** 语法格式四:有两个以上的参数,并且Lambda体中有多条语句*/@Testpublic void test4() {Comparator<Integer> comparator = (x, y) -> {System.out.println("函数式接口");return Integer.compare(x, y);};}/*** 语法格式五:若Lambda体中只有一条语句,return和大括号都可以省略不写*/@Testpublic void test5() {Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);}/*** 语法格式六:Lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即"类型推断"*/@Testpublic void test6() {Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);}
}
四大内置核心函数式接口
package com.company;import org.junit.Test;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;/*** @author Helen* @version 1.0* @createTime 2023/1/3 23:38* @Description Java8内置的四大核心函数式接口* Consumer<T> :消费型接口* void accept(T t);* Supplier<T>:供给型接口* T get();* Function<T,R>:函数型接口* R apply(T t);* Predicate<T>:断言型接口* boolean test(T t);*/
public class TestLambda3 {/*** Predicate<T>:断言型接口*/@Testpublic void test4() {List<String> list= Arrays.asList("Hello","java","Lambda");List<String> stringList=filterStr(list,(s)->s.length()>4);System.out.println(stringList);}public List<String> filterStr(List<String> list, Predicate<String> predicate) {List<String> strList = new ArrayList<>();for (String str : list) {if (predicate.test(str)) {strList.add(str);}}return strList;}/*** Function<T,R>:函数型接口*/@Testpublic void test3() {String newStr = strHandler("\t\t\t 我要吃饭了", (str) -> str.trim());System.out.println(newStr);}/*** 用于处理字符串** @return*/public String strHandler(String str, Function<String, String> function) {return function.apply(str);}/*** Supplier<T>:供给型接口*/@Testpublic void test2() {List<Integer> list = getNumList(5, () -> (int) (Math.random() * 100));System.out.println(list);}public List<Integer> getNumList(int num, Supplier<Integer> sup) {List<Integer> list = new ArrayList<>();for (int i = 0; i < num; i++) {Integer n = sup.get();list.add(n);}return list;}/*** Consumer<T> :消费型接口*/@Testpublic void test1() {happy(10000, m -> System.out.println(m));}public void happy(double money, Consumer<Double> consumer) {consumer.accept(money);}
}
其他接口
方法引用与构造器引用
package com.company;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** @author Helen* @version 1.0* @createTime 2023/2/5 16:32* @Description*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee implements Serializable {private static final long serialVersionUID = 1L;private String name;
}
package com.company;import org.junit.Test;import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;/*** @author Helen* @version 1.0* @createTime 2023/2/1 22:41* @Description 方法引用* 方法引用:若Lambda 体中的内容有方法已经实现了,我们可以使用“方法引用”* (可以理解为方法引用是Lambda表达式的另外一种表现形式)* 主要有三种语法格式:* 对象::实例方法名* 类::静态方法名* 类::实例方法名* 注意:* ①Lambda 体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致!* ②若Lambda 参数列表中的第一参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用ClassName::method* <p>* 二、构造器引用:* <p>* 格式:* ClassName::new* 注意:需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致!* <p>* 三、数组引用* Type[]::new;*/
public class TestMethodRef {/*** 数组引用*/@Testpublic void test7() {Function<Integer, String[]> fun = (x) -> new String[x];String[] strs = fun.apply(10);System.out.println(strs.length);}@Testpublic void test6() {Function<String, Employee> function = (x) -> new Employee(x);// Employee只有一个有参构造器Function<String, Employee> fun2 = Employee::new;Employee employee = fun2.apply("小红");System.out.println(employee);}/*** 构造器引用*/@Testpublic void test5() {Supplier<Employee> supplier = () -> new Employee();// 构造器引用方式Supplier<Employee> supplier2 = Employee::new;Employee employee = supplier2.get();System.out.println(employee);}/*** 类::实例方法名*/@Testpublic void test4() {BiPredicate<String, String> biPredicate = (x, y) -> x.equals(y);BiPredicate<String, String> bp = String::equals;}/*** 类 :: 静态方法名*/@Testpublic void test3() {Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);Comparator<Integer> com = Integer::compare;}/*** 对象 ::实例方法名*/@Testpublic void test1() {PrintStream ps1 = System.out;Consumer<String> con = (x) -> ps1.println(x);PrintStream ps = System.out;Consumer<String> con1 = ps::println;Consumer<String> con2 = System.out::println;con2.accept("acdef");}@Testpublic void test2() {Employee emp = new Employee();Supplier<String> sup = () -> emp.getName();String str = sup.get();System.out.println(str);}
}
Stream
简介
Java8中有两大最为重要的改变。第一个是Lambda 表达式;另外一
个则是流API(java.util.stream.*
).
Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对 集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。 使用Stream API 对集合数据进行操作,就类似于使用SQL执行的数
据库查询。也可以使用Stream API来并行执行操作。简而言之,
Stream API 提供了一种高效且易于使用的处理数据的方式。
什么是Stream
是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
“集合讲的是数据,流讲的是计算!”
注意:
- Stream自己不会存储元素。
- Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream
- Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行
Stream操作步骤
创建Stream
一个数据源(如:集合、数组),获取一个流
package com.company;import org.junit.Test;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;/*** Stream操作步骤* 1.创建Stream* 2.中间操作* 3.终止操作(终端操作)*/
public class TestStreamAPI {// 创建Stream@Testpublic void test1() {//1.可以通过Collection 系列集合提供的stream()或parallelStream()List<String> list = new ArrayList<>();Stream<String> stream1 = list.stream();// 2.通过Arrays 中的静态方法stream()获取数组流Employee[] employee = new Employee[10];Stream<Employee> stream2 = Arrays.stream(employee);// 3.通过Stream类中的静态方法of()Stream<String> stream3 = Stream.of("aa", "bb", "cc", "dd", "ee");//4。创建无限流//迭代Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);stream4.limit(10).forEach(System.out::println);//生成Stream.generate(()->Math.random()).limit(5).forEach(System.out::println);}
}
中间操作
一个中间操作链,对数据源的数据进行处理
package com.company;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** @author Helen* @version 1.0* @createTime 2023/2/5 16:32* @Description*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee implements Serializable {private static final long serialVersionUID = 1L;private String name;private Integer age;private Double salary;
}
package com.company;import org.junit.Test;import java.util.*;
import java.util.stream.Stream;/****/
public class TestStreamAPI2 {List<Employee> employees = Arrays.asList(new Employee("张三", 18, 9999.99),new Employee("李四", 58, 5555.55),new Employee("王五", 26, 3333.33),new Employee("赵六", 36, 6666.66),new Employee("田七", 12, 8888.88),new Employee("田七", 12, 8888.88),new Employee("田七", 12, 8888.88));/*** 筛选与切片* filter—接收Lambda,从流中排除某些元素* limit—截断流,使其元素不超过给定数量。* skip(n)—跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。* 与limit(n)互补 distinct一—筛选,通过流所生成元素的hashcode()和equals()去除重复元素*///内部迭代:迭代操作由Stream API完成@Testpublic void test1() {// 中间操作:不会执行任何操作Stream<Employee> stream = employees.stream().filter((e) -> e.getAge() > 35);//终止操作:一次性抓行全部内容,即“惰性求值”stream.forEach(System.out::println);}/*** 外部迭代*/@Testpublic void test2() {Iterator<Employee> iterator = employees.iterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}/*** limit 截断流*/@Testpublic void test3() {employees.stream().filter((e) -> {System.out.println("短路");return e.getSalary() > 5000;}).limit(2).forEach(System.out::println);}/*** skip 跳过*/@Testpublic void test4() {employees.stream().filter((e) -> e.getSalary() > 5000).limit(2).skip(2).forEach(System.out::println);}/*** distinct 去重*/@Testpublic void test5() {employees.stream().filter((e) -> e.getSalary() > 5000).limit(2).distinct().forEach(System.out::println);}/*** 映射* map—接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。* flatMap—接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流*/@Testpublic void test6() {List<String> list = Arrays.asList("aaa", "ccc", "ddd");list.stream().map((str) -> str.toUpperCase()).forEach(System.out::println);System.out.println("--------------------------------");Stream<Stream<Character>> stream = list.stream().map(TestStreamAPI2::filterCharacter);stream.forEach((sm) -> {sm.forEach(System.out::println);});System.out.println("--------------------------------");list.stream().flatMap(TestStreamAPI2::filterCharacter).forEach(System.out::println);}public static Stream<Character> filterCharacter(String str) {List<Character> list = new ArrayList<>();for (Character ch : str.toCharArray()) {list.add(ch);}return list.stream();}/*** sorted()—自然排序(Comparable)* sorted(Comparator com)—定制排序(Comparator)*/@Testpublic void test7() {List<String> list = Arrays.asList("aaa", "ccc", "ddd");list.stream().sorted().forEach(System.out::println);System.out.println("--------------------------------");employees.stream().sorted((e1, e2) -> {if (e1.getAge().equals(e2.getAge())) {return e1.getName().compareTo(e2.getName());} else {return e1.getAge().compareTo(e2.getAge());}}).forEach(System.out::println);}
}
终止操作(终端操作)
一个终止操作,执行中间操作链,并产生结果
package com.company;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee implements Serializable {private static final long serialVersionUID = 1L;private String name;private Integer age;private Double salary;private Status status;public enum Status{FREE,BUSY,VOCATION;}
}
package com.company;import org.junit.Test;import java.util.Arrays;
import java.util.List;
import java.util.Optional;/*** @author Helen* @version 1.0* @createTime 2023/2/9 23:58* @Description 终止操作*/
public class TestStreamAPI3 {/*** 查找与匹配* allMatch—检查是否匹配所有元素* anyMatch一检查是否至少匹配一个元素* noneMatch—检查是否没有匹配所有元素* findFirst—返回第一个元素* findAny—返回当前流中的任意元素* count—返回流中元素的总个数* max—返回流中最大值* min—返回流中最小值*/List<Employee> employees = Arrays.asList(new Employee("张三", 18, 9999.99, Employee.Status.FREE),new Employee("李四", 58, 5555.55, Employee.Status.BUSY),new Employee("王五", 26, 3333.33, Employee.Status.VOCATION),new Employee("赵六", 36, 6666.66, Employee.Status.FREE),new Employee("田七", 12, 8888.88, Employee.Status.BUSY));@Testpublic void test1() {boolean flag = employees.stream().allMatch(e -> e.getStatus().equals(Employee.Status.BUSY));System.out.println("flag=" + flag);boolean flag1 = employees.stream().anyMatch(e -> e.getStatus().equals(Employee.Status.BUSY));System.out.println("flag1=" + flag1);boolean flag2 = employees.stream().noneMatch(e -> e.getStatus().equals(Employee.Status.BUSY));System.out.println("flag2=" + flag2);// 按工资排序取出最大的值Optional<Employee> optional = employees.stream().sorted((e1, e2) -> -Double.compare(e1.getSalary(), e2.getSalary())).findFirst();System.out.println(optional.get());System.out.println("并行流,多个线程同时去查找");Optional<Employee> op2 = employees.parallelStream().filter((e) -> e.getStatus().equals(Employee.Status.FREE)).findAny();System.out.println(op2.get());}@Testpublic void test2() {Long count = employees.stream().count();System.out.println("count=" + count);Optional<Employee> optional = employees.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));System.out.println("获得最大值");System.out.println(optional.get());System.out.println("最小值");Optional<Double> op2 = employees.stream().map(Employee::getSalary).min(Double::compare);System.out.println(op2.get());}
}
归约与收集
package com.company;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** @author Helen* @version 1.0* @createTime 2023/2/5 16:32* @Description*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee implements Serializable {private static final long serialVersionUID = 1L;private String name;private Integer age;private Double salary;private Status status;public enum Status{FREE,BUSY,VOCATION;}
}
package com.company;import org.junit.Test;import java.util.*;
import java.util.stream.Collectors;/*** @author Helen* @version 1.0* @createTime 2023/2/15* @Description*/
public class TestStreamAPI4 {List<Employee> employees = Arrays.asList(new Employee("张三", 18, 9999.99, Employee.Status.FREE),new Employee("李四", 58, 5555.55, Employee.Status.BUSY),new Employee("王五", 26, 3333.33, Employee.Status.VOCATION),new Employee("赵六", 36, 6666.66, Employee.Status.FREE),new Employee("田七", 12, 8888.88, Employee.Status.BUSY),new Employee("田七", 12, 8888.88, Employee.Status.BUSY));/*** 归约* reduce(T identity,BinaryOperator)/ reduce(BinaryOperator)—可以将流中元素反复结合起来,得到一个值。* T identity:初始值* BinaryOperator:二进制操作,用于累加,相减*/@Testpublic void test() {System.out.println("第一种方式");List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);Integer sum = list.stream().reduce(0, (x, y) -> x + y);System.out.println("sum=" + sum);System.out.println("第二种方式");Integer sum2 = list.stream().reduce(0, Integer::sum);System.out.println("sum2=" + sum2);}/*** 收集* collect—将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法*/@Testpublic void test2() {System.out.println("--------------list类型收集--------------");List<String> list = employees.stream().map(Employee::getName).collect(Collectors.toList());list.forEach(System.out::println);System.out.println("--------------set类型收集--------------");Set<String> set = employees.stream().map(Employee::getName).collect(Collectors.toSet());set.forEach(System.out::println);System.out.println("----------------HashSet类型收集-------------");HashSet<String> hs = employees.stream().map(Employee::getName).collect(Collectors.toCollection(HashSet::new));hs.forEach(System.out::println);}@Testpublic void test3() {System.out.println("总数");Long count = employees.stream().collect(Collectors.counting());System.out.println(count);System.out.println("平均值");Double avg = employees.stream().collect(Collectors.averagingDouble(Employee::getSalary));System.out.println(avg);System.out.println("总和");Double sum = employees.stream().collect(Collectors.summingDouble(Employee::getSalary));System.out.println(sum);System.out.println("最大值");Optional<Employee> max = employees.stream().collect(Collectors.maxBy((e1, e2) ->Integer.compare(e1.getAge(), e2.getAge())));System.out.println(max.get());System.out.println("最小值");Optional<Double> min = employees.stream().map(Employee::getSalary).collect(Collectors.minBy(Double::compareTo));System.out.println(min.get());}/*** 分组*/@Testpublic void test4() {Map<Employee.Status, List<Employee>> map =employees.stream().collect(Collectors.groupingBy(Employee::getStatus));// jdk8遍历mapmap.forEach((k, v) -> {System.out.println(k);System.out.println(v);System.out.println("----------------");});/** 返回格式如下* BUSY* [Employee(name=李四, age=58, salary=5555.55, status=BUSY), Employee(name=田七, age=12, salary=8888.88, status=BUSY),* Employee(name=田七, age=12, salary=8888.88, status=BUSY)]*/}
}
并行流与顺序流
Fork/Join框架
package com.company;import java.util.concurrent.RecursiveTask;/*** @author Helen* @version 1.0* @createTime 2023/2/18* @Description*/
public class ForkJoinCalculate extends RecursiveTask<Long> {private static final long serialVersionUID = 1L;/*** 开始*/private long start;/*** 结束*/private long end;/*** 临界值*/private static final long THRESHOLD = 10000;public ForkJoinCalculate(long start, long end) {this.start = start;this.end = end;}@Overrideprotected Long compute() {long length = end - start;if (length <= THRESHOLD) {long sum = 0;for (long i = start; i <= end; i++) {sum += i;}return sum;} else {long middle = (start + end) / 2;ForkJoinCalculate left = new ForkJoinCalculate(start, middle);// 拆分子任务,同时加入线程队列left.fork();ForkJoinCalculate right = new ForkJoinCalculate(middle + 1, end);right.fork();return left.join() + right.join();}}
}
package com.company;import org.junit.Test;import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;/*** @author Helen* @version 1.0* @createTime 2023/2/18* @Description*/
public class TestForkJoin {/*** ForkJoin框架*/@Testpublic void test1() {Instant start = Instant.now();ForkJoinPool pool = new ForkJoinPool();ForkJoinTask<Long> task = new ForkJoinCalculate(0, 100000000000L);Long sum = pool.invoke(task);System.out.println(sum);Instant end = Instant.now();// 932356074711512064//耗费时间:12513毫秒System.out.println("耗费时间:" + Duration.between(start, end).toMillis() + "毫秒");}/*** 普通for循环*/@Testpublic void test2() {Instant start = Instant.now();long sum = 0L;for (long i = 0; i <= 100000000000L; i++) {sum += i;}System.out.println(sum);Instant end = Instant.now();//932356074711512064//耗费时间:26157毫秒System.out.println("耗费时间:" + Duration.between(start, end).toMillis() + "毫秒");}/*** java8并行流*/@Testpublic void test3() {Instant start = Instant.now();LongStream.rangeClosed(0, 100000000000L)// 并行流.parallel().reduce(0, Long::sum);Instant end = Instant.now();// 耗费时间:6971毫秒System.out.println("耗费时间:" + Duration.between(start, end).toMillis() + "毫秒");}
}
Optional类
package com.company;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** @author Helen* @version 1.0* @createTime 2023/2/5 16:32* @Description*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee implements Serializable {private static final long serialVersionUID = 1L;private String name;private Integer age;private Double salary;private Status status;public enum Status{FREE,BUSY,VOCATION;}
}
package com.company;import org.junit.Test;import java.util.Optional;/*** @author Helen* @version 1.0* @createTime 2023/2/18* @Description*/
public class OptionalTest {/*** 创建一个Optional实例*/@Testpublic void test1() {Optional<Employee> op = Optional.of(new Employee());Employee employee = op.get();System.out.println(employee);}@Testpublic void test2() {Optional<Employee> op = Optional.empty();System.out.println(op.get());}@Testpublic void test3() {Optional<Employee> op = Optional.ofNullable(null);if (op.isPresent()) {System.out.println("判断是否包含值");System.out.println(op.get());}Employee employee = op.orElse(new Employee("张三", 19, 888.88, Employee.Status.BUSY));System.out.println(employee);}@Testpublic void test4() {Optional<Employee> op = Optional.ofNullable(null);Employee employee = op.orElseGet(() -> new Employee());System.out.println(employee);}@Testpublic void test5() {Optional<Employee> op = Optional.ofNullable(new Employee("张三", 19, 888.88, Employee.Status.BUSY));Optional<String> str = op.map(Employee::getName);System.out.println(str.get());}@Testpublic void test6() {Optional<Employee> op = Optional.ofNullable(new Employee("张三", 19, 888.88, Employee.Status.BUSY));Optional<String> str = op.flatMap((e) -> Optional.of(e.getName()));System.out.println(str.get());}
}
接口中的默认方法与静态方法
package com.company;public class MyClass {public String getName() {return "嘿嘿";}
}
package com.company;public interface MyFun {/*** 接口中的默认方法,用default修饰** @return*/default String geName() {return "哈哈";}/*** 接口中的静态方法的调用* 类名.静态方法名()*/public static void say(){System.out.println("接口中的静态方法");}
}
package com.company;
public class SubClass extends MyClass implements MyFun{
}
package com.company;public class DefaultInterfaceTest {public static void main(String[] args) {SubClass sc = new SubClass();String str = sc.geName();System.out.println(str);}
}
输出 哈哈
时间和日期
传统时间格式化
package com.company;import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;/*** @author Helen* @version 1.0* @createTime 2023/2/18* @Description 传统时间格式化线程问题*/
public class SimpleDateFormatTest {public static void main(String[] args) throws Exception {SimpleDateFormat sf = new SimpleDateFormat("yyyyMMdd");Callable<Date> task = new Callable<Date>() {@Overridepublic Date call() throws Exception {return sf.parse("20230218");}};// 固定数量的线程池ExecutorService pool = Executors.newFixedThreadPool(10);List<Future<Date>> results = new ArrayList<>();for (int i = 0; i < 10; i++) {results.add(pool.submit(task));}for (Future<Date> future : results) {System.out.println(future.get());}}
}
上述代码,出现日期格式解析失败,修复代码如下
package com.company;import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;/*** @author Helen* @version 1.0* @createTime 2023/2/18* @Description*/
public class DateFormatThreadLocal {private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {@Overrideprotected DateFormat initialValue() {return new SimpleDateFormat("yyyyMMdd");}};public static Date convert(String source) throws Exception {return df.get().parse(source);}
}
package com.company;import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;/*** @author Helen* @version 1.0* @createTime 2023/2/18* @Description 传统时间格式化线程问题*/
public class SimpleDateFormatTest {public static void main(String[] args) throws Exception {SimpleDateFormat sf = new SimpleDateFormat("yyyyMMdd");Callable<Date> task = new Callable<Date>() {@Overridepublic Date call() throws Exception {return DateFormatThreadLocal.convert("20230218");}};// 固定数量的线程池ExecutorService pool = Executors.newFixedThreadPool(10);List<Future<Date>> results = new ArrayList<>();for (int i = 0; i < 10; i++) {results.add(pool.submit(task));}for (Future<Date> future : results) {System.out.println(future.get());}// 关闭线程pool.shutdown();}
}
jdk8中的日期
package com.company;import org.junit.Test;import java.time.*;/*** @author Helen* @version 1.0* @createTime 2023/2/18* @Description*/
public class DateDemo {/*** 系统当前时间*/@Testpublic void test1() {LocalDateTime ldt = LocalDateTime.now();System.out.println(ldt);LocalDateTime ldt2 = LocalDateTime.of(2023, 2, 18, 22, 10);System.out.println(ldt2);LocalDateTime ldt3 = ldt.plusYears(2);System.out.println(ldt3);LocalDateTime ldt4 = ldt.minusMonths(2);System.out.println(ldt4);}/*** Instant:时间戳(以Unix元年:1970年1月1日 00:00:00)*/@Testpublic void test2() {//默认获取UTC时区Instant now = Instant.now();System.out.println(now);// 偏移量OffsetDateTime of = now.atOffset(ZoneOffset.ofHours(8));System.out.println(of);// 毫秒时间System.out.println(now.toEpochMilli());// 秒Instant instant = Instant.ofEpochSecond(1000);System.out.println("instant=" + instant);}/*** Duration:计算两个“时间”之间的间隔*/@Testpublic void test3() {Instant ins1 = Instant.now();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}Instant ins2 = Instant.now();Duration duration = Duration.between(ins1, ins2);// 获取时间以秒为单位System.out.println("秒=" + duration.getSeconds());// 获取毫秒System.out.println("毫秒=" + duration.toMillis());}/*** Period:计算两个“日期”之间的间隔*/@Testpublic void test4() {LocalDate ld1 = LocalDate.of(2022, 1, 5);LocalDate ld2 = LocalDate.now();Period period = Period.between(ld1, ld2);System.out.println("相差年数:" + period.getYears());System.out.println("相差月数:" + period.getMonths());System.out.println("相差天数:" + period.getDays());}
}
时间校正器
package com.company;import org.junit.Test;import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;/*** @author Helen* @version 1.0* @createTime 2023/2/19* @Description*/
public class DateDemo2 {/*** 时间校正器 TemporalAdjuster*/@Testpublic void test1() {LocalDateTime ldt1 = LocalDateTime.now();System.out.println("ldt1=" + ldt1);LocalDateTime ldt2 = ldt1.withDayOfMonth(10);System.out.println("ldt2=" + ldt2);}@Testpublic void test2() {LocalDate nextSunday = LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.SUNDAY));System.out.println("下个周日:" + nextSunday);// 下一个工作日LocalDateTime ldt1 = LocalDateTime.now();LocalDateTime day = ldt1.with((l) -> {LocalDateTime ldt2 = (LocalDateTime) l;DayOfWeek dow = ldt2.getDayOfWeek();if (dow.equals(DayOfWeek.MONDAY)) {ldt2.plusDays(1);} else if (dow.equals(DayOfWeek.TUESDAY)) {ldt2.plusDays(2);} else if (dow.equals(DayOfWeek.WEDNESDAY)) {ldt2.plusDays(3);} else if (dow.equals(DayOfWeek.THURSDAY)) {ldt2.plusDays(4);} else if (dow.equals(DayOfWeek.FRIDAY)) {ldt2.plusDays(5);} else if (dow.equals(DayOfWeek.SATURDAY)) {ldt2.plusDays(8);} else if (dow.equals(DayOfWeek.SUNDAY)) {ldt2.plusDays(9);}return ldt2;});System.out.println("下一个工作日=" + day);}/*** DateTimeFormatter:格式化时间/日期*/@Testpublic void test3() {DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME;LocalDateTime ldt = LocalDateTime.now();String str = ldt.format(dtf);System.out.println(str);System.out.println("----------------------------");DateTimeFormatter df2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");String strDate2 = df2.format(ldt);LocalDateTime newDate = LocalDateTime.parse(strDate2, df2);System.out.println(newDate);}
}
时区的处理
package com.company;import org.junit.Test;import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;public class DateDemo2 {/*** ZoneDate、ZonedTime、ZonedDateTime*/@Testpublic void test4() {LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Europe/Tallinn"));// 2023-02-19T17:53:10.695System.out.println(ldt);System.out.println("---------------------");LocalDateTime ldt2 = LocalDateTime.now();ZonedDateTime zdt = ldt.atZone(ZoneId.of("Europe/Tallinn"));// 2023-02-19T17:53:10.695+02:00[Europe/Tallinn]System.out.println(zdt);}
}
重复注解与类型注解
package com.company;import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;import static java.lang.annotation.ElementType.*;/*** @author Helen* @version 1.0* @createTime 2023/2/20* @Description @Repeatable:可重复的注解* MyAnnotations.class:容器类*/@Repeatable(MyAnnotations.class)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE,TYPE_PARAMETER})
@Retention(RetentionPolicy.SOURCE)
public @interface MyAnnottation {String value() default "atguigu";}
package com.company;import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;/*** @author Helen* @version 1.0* @createTime 2023/2/20* @Description*/
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotations {MyAnnottation[] value();
}
package com.company;import org.junit.Test;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;/*** @author Helen* @version 1.0* @createTime 2023/2/20* @Description*/
public class TestAnnotation {@Testpublic void test() throws Exception {Class<TestAnnotation> clazz = TestAnnotation.class;Method method = clazz.getMethod("show");MyAnnottation[] mas = method.getAnnotationsByType(MyAnnottation.class);for (MyAnnottation m : mas) {System.out.println(m.value());}}@MyAnnottation("Hello")@MyAnnottation("World")public void show() {}
}
输出
Hello
World