JavaSE:第十六章:java8新特性
##java8內(nèi)容
1.Lambda表達(dá)式 ★
2.函數(shù)式接口 ★
3.方法引用 ★
4.構(gòu)造器引用|數(shù)組引用 ★
5.StreamAPI ★
6.接口中可以定義默認(rèn)方法和靜態(tài)方法 ★
7.Optional類的引入:為了減少空指針異常【了解】
8.新日期API【了解】
9.重復(fù)注解【了解】
10.Nashone引擎的使用:在jvm上運(yùn)行js【后面課程】
##Java8引進(jìn)
1995年推出jdk1.0
04年推出 jdk5 ,改革非常大
06年推出 jdk6 ,企業(yè)中使用的最長(zhǎng)久版本
--------被Oralce公司收購(gòu)-----------
11年 推出 jdk7
14年 推出 jdk8 LTS版本:受商業(yè)公司支持的長(zhǎng)期版本
17年 9月份推出 jdk9, “六個(gè)月版本升級(jí)計(jì)劃” 小版本
18年 3月份 推出jdk10 小版本
18年 9月份 推出jdk11 LTS版本:
##Lambda表達(dá)式
###理解
理解成一段可以傳遞的代碼,作為函數(shù)式接口的實(shí)例出現(xiàn)
###應(yīng)用場(chǎng)景
示例1:
接口 a = Lambda表達(dá)式;
示例2:【居多】
method(Lambda表達(dá)式);
public void method(接口 a){
}
###好處
1、語(yǔ)句更加簡(jiǎn)潔
2、更加緊湊,使java語(yǔ)言的表達(dá)能力得到了提升!
###語(yǔ)法 ★
(參數(shù)類型 參數(shù)名,參數(shù)類型 參數(shù)名)->{方法體的實(shí)現(xiàn)/Lambda體}
示例:
(String o1, String o2)->{return o1.compareTo(o2);}
特點(diǎn):
①左側(cè)參數(shù)列表中的參數(shù)類型可以省略!
②如果左側(cè)參數(shù)列表中,只有一個(gè)參數(shù),則小括號(hào)也可以省略
③右側(cè)的Lambda體中如果僅有一句話,則大括號(hào)可以省略
④右側(cè)的Lambda體中僅有的一句話為return語(yǔ)句,則return要求省略
##函數(shù)式接口
理解:
只有一個(gè)抽象方法的接口,稱為函數(shù)式接口
Consumer消費(fèi)型接口
Supplier供給型接口
Function<T,R>函數(shù)型接口
Predicate 斷定型接口
##方法引用
###理解
* 方法引用實(shí)質(zhì)上就是Lambda表達(dá)式的簡(jiǎn)化,同樣可以作為函數(shù)式接口的實(shí)例出現(xiàn)
* 能用方法引用 的肯定能用Lambda表達(dá)式
* 能用Lambda表達(dá)式的不一定能用方法應(yīng)用,除非滿足以下要求:
###要求:
①Lambda體中僅僅只有一句話
②僅有的一句話為 方法調(diào)用!
③調(diào)用方法的參數(shù)列表和Lambda體實(shí)現(xiàn)的抽象方法的參數(shù)列表一致!
調(diào)用方法的返回類型和Lambda體實(shí)現(xiàn)的抽象方法的返回類型一致!
特例:類名::普通方法
調(diào)用方法的調(diào)用者正好是 抽象方法的第一個(gè)參數(shù),并且其他參數(shù)一致
調(diào)用方法的返回類型和抽象方法的返回類型一致!
###語(yǔ)法:
類名或?qū)ο?:方法名
###情況:
* 1、對(duì)象::普通方法
* 2、類名::靜態(tài)方法
* 3、類名::普通方法
##關(guān)于方法引用、數(shù)組引用、構(gòu)造器引用的總結(jié)
1.能使用方法引用|數(shù)組引用|構(gòu)造器引用的地方,肯定能用Lambda表達(dá)式!
2.能用Lambda表達(dá)式的地方,不一定能用方法引用|數(shù)組引用|構(gòu)造器引用,必須滿足以下條件
3.能使用Lambda表達(dá)式的地方,肯定能用匿名內(nèi)部類
能用匿名內(nèi)部類的,不一定能用Lambda表達(dá)式,必須滿足:
實(shí)現(xiàn)的接口為 函數(shù)式接口(里面只有一個(gè)抽象方法的接口)!
方法引用:
①Lambda體只有一句話
②僅有的一句話為調(diào)用方法
③方法的參數(shù)列表、返回類型正好與抽象方法的參數(shù)列表、返回類型一致!
特殊:如果是類名::普通方法,則要求方法的調(diào)用者為抽象的方法的第一個(gè)參數(shù),其他一致
此類用于演示方法引用
* 舉例:
* 匿名內(nèi)部類:
* UnaryOperator<Double> up = new UnaryOperator<Double>(){
* public Double apply(Double t){
* return Math.sqrt(t);
* }
* };
* Lambda:
* UnaryOperator<Double> up =d->Math.sqrt(d);
* 方法引用:
UnaryOperator<Double> up = Math::sqrt;
*/
public class TestMethodRef {
//1、對(duì)象::普通方法
@Test
public void test1_1() {
//匿名內(nèi)部類
// Runnable r = new Runnable() {
// @Override
// public void run() {
// System.out.println();
// }
// };
//方法引用
Runnable r2 = System.out::println;
r2.run();
}
//對(duì)象::普通方法
@Test
public void test1_2() {
//匿名內(nèi)部類
// Consumer<String> con = new Consumer<String>() {
// @Override
// public void accept(String t) {
// System.out.println(t);
//
// }
// };
//方法引用
Consumer<String> con2 = System.out::println;
con2.accept("趙麗穎和馮紹峰已經(jīng)結(jié)婚了");
}
//2、類名::靜態(tài)方法
@Test
public void test2() {
//匿名內(nèi)部類
Comparator<Double> com = new Comparator<Double>() {
@Override
public int compare(Double o1, Double o2) {
return Double.compare(o1, o2);
}
};
//Lambda
Comparator<Double> com1 = (o1,o2)->Double.compare(o1, o2);
//方法引用
Comparator<Double> com2 =Double::compare;
}
//3、類名::普通方法
@Test
public void test3() {
//匿名內(nèi)部類
// Function<Employee,String> fun = new Function<Employee,String>(){
// @Override
// public String apply(Employee t) {
// return t.getName();
// }
// };
//方法引用
Function<Employee,String> fun2 = Employee::getName;
System.out.println(fun2.apply(new Employee("張無(wú)忌", 12, 1000, '男')));
}
//3、類名::普通方法
@Test
public void test3_2() {
//匿名內(nèi)部類
// BiFunction<String, String, Boolean> bf = new BiFunction<String, String, Boolean>() {
// @Override
// public Boolean apply(String t, String u) {
// return t.equals(u);
// }
// };
//方法引用
BiFunction<String, String, Boolean> bf2 = String::equals;
System.out.println(bf2.apply("hello", "Hello"));
}
}
構(gòu)造器引用
理解:構(gòu)造器引用本質(zhì)上就是Lambda表達(dá)式,只是語(yǔ)句更加簡(jiǎn)潔。作為函數(shù)式接口的實(shí)例,一般作為參數(shù)傳遞給方法!
能用構(gòu)造器引用的地方,肯定能用Lambda表達(dá)式
但能用Lambda表達(dá)式的地方,不一定能用構(gòu)造器引用
要求:
①Lambda體中僅僅只有一句話
②僅有的一句話為調(diào)用構(gòu)造器 new ClassName(實(shí)參列表);
③抽象方法的參數(shù)列表和構(gòu)造器的參數(shù)列表完全一致
抽象方法的返回類型為構(gòu)造器所屬的類型。
語(yǔ)法:
類名::new
此類用于演示構(gòu)造器引用
public class TestConstructorRef {
//案例1:返回new String();
@Test
public void test1() {
//匿名內(nèi)部類
// Supplier<String> sup = new Supplier<String>() {
// @Override
// public String get() {
// return new String();
// }
// };
//構(gòu)造器引用
Supplier<String> sup2 = String::new;
int length = sup2.get().length();
System.out.println(length);
}
//案例2:返回new StringBuffer(int capacity);
@Test
public void test2() {
Function<Integer,StringBuffer> fun = new Function<Integer,StringBuffer>(){
@Override
public StringBuffer apply(Integer t) {
return new StringBuffer(t);
}
};
Function<Integer,StringBuffer> fun2 = StringBuffer::new;
}
//案例3:返回new Employee("段譽(yù)", 22, 10000, '男')
@Test
public void test3() {
A<String,Integer,Double,Character,Employee> a1 = (s,i,d,c)->new Employee(s,i,d,c);
A<String,Integer,Double,Character,Employee> a = Employee::new;
}
}
interface A<T,R,U,M,N>{
N test(T t,R r,U u,M m);
}
數(shù)組引用
理解:數(shù)組引用本質(zhì)上就是Lambda表達(dá)式,只是語(yǔ)句更加簡(jiǎn)潔。作為函數(shù)式接口的實(shí)例,一般作為參數(shù)傳遞給方法!
能用數(shù)組引用的地方,肯定能用Lambda表達(dá)式
但能用Lambda表達(dá)式的地方,不一定能用數(shù)組引用
要求:
①Lambda體僅僅有一句話
②僅有的一句話為返回一個(gè)新數(shù)組 new 數(shù)組類型[長(zhǎng)度];
③抽象方法的參數(shù)只有一個(gè),就是數(shù)組的長(zhǎng)度;抽象方法的返回為創(chuàng)建的新數(shù)組類型
語(yǔ)法:
數(shù)組類型[]::new
此類用于演示數(shù)組引用
public class TestArrayRef {
//案例1:返回一個(gè)String[] s = new String[5]
@Test
public void test1() {
//匿名內(nèi)部類
// Function<Integer,String[]> fun = new Function<Integer,String[]>(){
// @Override
// public String[] apply(Integer t) {
// return new String[t];
// }
// };
//數(shù)組引用
Function<Integer,String[]> fun2 = String[]::new;
String[] arr = fun2.apply(5);
for (String string : arr) {
System.out.println(string);
}
}
//案例2:返回一個(gè)Employee[]
@Test
public void test2() {
Function<Integer,Employee[]> fun = Employee[]::new;
Employee[] apply = fun.apply(3);
for (Employee employee : apply) {
System.out.println(employee);
}
}
}
綜述:匿名內(nèi)部類》Lambda表達(dá)式》方法引用|數(shù)組引用|構(gòu)造器引用
##StreamAPI
###好處
1、更高效
2、易于使用,提供了豐富強(qiáng)大的方法。
###使用步驟
1.開始操作(√)
說明:創(chuàng)建Stream對(duì)象,指向一個(gè)具體的數(shù)據(jù)源(集合、數(shù)組、一系列值、無(wú)線流)
2.中間操作(可選 0——n)
說明:對(duì)數(shù)據(jù)源數(shù)據(jù)的計(jì)算、處理
3.終止操作(√)
說明:想要一個(gè)結(jié)果(打印、計(jì)數(shù)、去最值等)
###使用特點(diǎn)
1、Stream講究的是“計(jì)算”,可以處理數(shù)據(jù),但不能更新源數(shù)據(jù)
2、Stream 屬于“惰性操作”,必須等待終止操作執(zhí)行后,前面的中間操作或開始操作才會(huì)處理
3、Stream只能消費(fèi)一次,一旦消費(fèi),就不能再次使用,除非重新創(chuàng)建Stream對(duì)象
4、Stream的中間操作可以有0個(gè)或多個(gè),每個(gè)操作都會(huì)返回一個(gè)新的Stream
5、Stream相當(dāng)于一個(gè) 更強(qiáng)大的Iterator,可以處理更加復(fù)雜的數(shù)據(jù),并且實(shí)現(xiàn)并行化,效率更高!
###開始操作的相關(guān)API
一、通過集合來獲取Stream對(duì)象 ★
Stream stream = list.stream();
二、通過數(shù)組來獲取Stream對(duì)象
Stream stream = Arrays.stream(數(shù)組);
三、通過一組指定的值來獲取Stream對(duì)象
Stream stream = Stream.of(T…ts)
四、生成無(wú)限流
Stream stream= Stream.generate(Supplier sup);
/**
* 此類用于演示Stream的使用步驟一:創(chuàng)建Stream對(duì)象
* 引申:
* Stream的使用步驟
* 1、創(chuàng)建Stream對(duì)象,指向數(shù)據(jù)源
* 2、中間操作,處理數(shù)據(jù),返回一個(gè)新的Stream
* 3、終止操作,執(zhí)行
* 創(chuàng)建Stream對(duì)象的方式
* 1、通過集合對(duì)象創(chuàng)建Stream
* 2、通過數(shù)組對(duì)象創(chuàng)建Stream
* 3、通過一系列值創(chuàng)建Stream
* 4、生成無(wú)限流
*/
public class TestStreamStart {
// 1、通過集合對(duì)象創(chuàng)建Stream ★
@Test
public void test1() {
List<Employee> list = EmployeeData.getData();//集合
//獲取串行流對(duì)象stream
Stream<Employee> stream = list.stream();
//獲取并行流對(duì)象parallelStream
// Stream<Employee> parallelStream = list.parallelStream();
//補(bǔ)充:終止操作
stream.forEach(System.out::println);
}
// 2、通過數(shù)組對(duì)象創(chuàng)建Stream
@Test
public void test2() {
Stream<String> stream = Arrays.stream(new String[] {"白眉鷹王","青易斧王","紫衫龍王","金毛獅王"});
stream.forEach(System.out::println);
}
// 3、通過一系列值創(chuàng)建Stream
@Test
public void test3() {
Stream<String> of = Stream.of("周芷若","小昭","殷離","趙敏");
of.forEach(System.out::println);
}
// 4、生成無(wú)限流
@Test
public void test4() {
Stream<Double> stream = Stream.generate(Math::random);
stream.forEach(System.out::println);
}
//案例:演示鏈?zhǔn)秸{(diào)用(流式編程)
@Test
public void exec1() {
//測(cè)試1
// EmployeeData.getData().stream().forEach(System.out::println);
//測(cè)試2
Person p = new Person();
// p.eat();
// p.sleep();
// p.play();
// p.study();
p.eat().sleep().play().study();
}
}
class Person{
public Person eat() {
System.out.println("吃");
return this;
}
public Person sleep() {
System.out.println("睡");
return this;
}
public Person play() {
System.out.println("玩");
return this;
}
public Person study() {
System.out.println("學(xué)");
return this;
}
}
###中間操作的相關(guān)API
* filter(Predicate):根據(jù)條件過濾
* limit(long max):截取size<=max的元素
* skip(long s):跳過前s個(gè)
* distinct():返回去重后的元素集合,根據(jù)hashCode和equals方法判斷重復(fù)項(xiàng)
* map(Function):映射成新元素
* flatMap(Function):映射成Stream類型的新元素
* sorted():自然排序
* sorted(Comparator):定制排序
*
/**
* 此類用于演示Stream的使用步驟二:中間操作
* 特點(diǎn):
* ①每個(gè)中間操作方法,都會(huì)返回一個(gè)持有結(jié)果的新的Stream對(duì)象
* ②中間操作是“惰性求值”,必須等待終止操作后,才會(huì)有處理結(jié)果
* ③Stream是一次性消費(fèi),每次消費(fèi)后,則不能再次消費(fèi),除非重新創(chuàng)建新的Stream
* ④中間操作可以實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用!
* 常見方法:
* filter(Predicate):過濾
* skip(n):去掉前幾項(xiàng)
* limit(n):獲取前n項(xiàng)
* distinct():去重
* map(Function):映射
* flatMap(Function):映射,返回Stream
* sorted():自然排序,要求元素本身實(shí)現(xiàn)Comparable接口
* sorted(Comparator):定制排序
*/
public class TestStreamMiddle {
List<Employee> list;
@Before
public void before() {
list = EmployeeData.getData();
}
/*
* 篩選與切片
* filter(Predicate p)——接收 Lambda , 從流中排除某些元素。
limit(n)——截?cái)嗔?,使其元素不超過給定數(shù)量。
skip(n) —— 跳過元素,返回一個(gè)扔掉了前 n 個(gè)元素的流。若流中元素不足 n 個(gè),則返回一個(gè)空流。與 limit(n) 互補(bǔ)
distinct()——篩選,通過流所生成元素的 hashCode() 和 equals() 去除重復(fù)元素
*/
@Test
public void test1() {
//1.創(chuàng)建Stream對(duì)象
Stream<Employee> stream = list.stream();
//2.中間操作
//方式一:filter過濾
// Stream<Employee> filter = stream.filter(t->t.getGender()=='男');
//方式二:limit限制,返回不超過指定條目數(shù)的數(shù)據(jù)
// Stream<Employee> limit = stream.limit(5);
//方法三:skip(n),跳過指定的n條數(shù)據(jù)
// Stream<Employee> skip = stream.skip(3);
//方法四:distinct()去重:兩個(gè)元素通過equals判斷,如果返回true,則為重復(fù)項(xiàng),一般往往需要重寫元素的equals和hashCode方法
Stream<Employee> distinct = stream.distinct();
//3.終止操作
distinct.forEach(System.out::println);
}
/**
* 映射
* map:映射(將元素映射成任意類型)
* flatMap:映射(將元素映射成Stream類型)
*/
@Test
public void test2() {
//1.創(chuàng)建Stream對(duì)象
Stream<Employee> stream = list.stream();
//2.中間操作
//方法5:map
// Stream<String> map = stream.map(Employee::getName);
// Stream<String> filter = map.filter(s->s.contains("段"));
Stream<Stream<Object>> map = stream.map(TestStreamMiddle::fromEmployeeToStream);
//方法6:flatMap
// Stream<Object> flatMap = stream.flatMap(TestStreamMiddle::fromEmployeeToStream);
//3.終止操作
// filter.forEach(System.out::println);
map.forEach(System.out::println);
}
/*
* 排序
* sorted()——自然排序
sorted(Comparator com)——定制排序
*/
@Test
public void test3() {
//1.開始操作
Stream<Employee> stream = list.stream();
//2.中間操作
//方法7:sorted自然排序
// Stream<Employee> sorted = stream.sorted();
//方法8:sorted(Comparator) 定制排序
Stream<Employee> sorted = stream.sorted((o1,o2)->Double.compare(o2.getSalary(), o1.getSalary()));
//3.終止操作
sorted.forEach(System.out::println);
}
//將Employee轉(zhuǎn)換成Stream
public static Stream<Object> fromEmployeeToStream(Employee e){
return Stream.of(e.getName(),e.getAge(),e.getGender(),e.getSalary());
}
//案例:獲取工資>6000的,第2條——第8條數(shù)據(jù),并且去掉重復(fù)項(xiàng),最后打印
@Test
public void exec1() {
EmployeeData.
getData().
stream().
filter(t->t.getSalary()>6000).
skip(1).
limit(7).
distinct().
forEach(System.out::println);
}
//練習(xí)1:獲取員工姓名長(zhǎng)度大于2的員工的姓名。
@Test
public void exec2() {
list.stream().map(Employee::getName).filter(s->s.length()>2).forEach(System.out::println);
}
//練習(xí)2:獲取員工工資>5000并且年齡<30的員工的工資
@Test
public void exec3() {
list.stream().filter(e->e.getAge()<30&&e.getSalary()>5000).map(Employee::getSalary).forEach(System.out::println);
}
//練習(xí)3:最老的三個(gè)員工的工資
@Test
public void exec4() {
list.stream().sorted((e1,e2)->Integer.compare(e2.getAge(),e1.getAge())).limit(3).map(Employee::getSalary).forEach(System.out::println);
}
}
###終止操作的相關(guān)API
* allMatch:測(cè)試是否全部匹配
* anyMatch:測(cè)試是否至少有一個(gè)匹配
* noneMatch:測(cè)試是否所有的都不匹配
* findFirst:返回第一個(gè)
* findAny:返回并行流中的任意一個(gè)
* count:統(tǒng)計(jì)個(gè)數(shù)
* max(comparator):返回最大值
* min(comparator):返回最小值
* forEach(Consumer):內(nèi)部迭代(遍歷)
* reduce(BinaryOperator):歸約,往往和map搭配使用
/**
* 此類用于演示Stream的使用步驟三:終止操作
* 常見方法:
* reduce:歸約 ★
* forEach:內(nèi)部迭代 ★
* max:求最大值
* min:求最小值
* count:統(tǒng)計(jì)個(gè)數(shù) ★
* allMatch:檢測(cè)是否所有元素都匹配指定條件
* anyMatch:檢測(cè)是否至少有一個(gè)元素匹配指定條件
* noneMatch:檢測(cè)是否所有元素都不匹配指定條件
* findFirst:返回第一個(gè)元素
* findAny:返回任意一個(gè)元素
* collect:將Stream轉(zhuǎn)換成集合對(duì)象
*/
public class TestStreamEnd {
List<Employee> list;
@Before
public void before() {
list = EmployeeData.getData();
}
/**
* 匹配與查找
* allMatch(Predicate p)——檢查是否匹配所有元素
anyMatch(Predicate p)——檢查是否至少匹配一個(gè)元素
noneMatch(Predicate p)——檢查是否沒有匹配的元素
findFirst——返回第一個(gè)元素
findAny——返回當(dāng)前流中的任意元素
*/
@Test
public void test1() {
//1.開始操作:創(chuàng)建Stream對(duì)象
Stream<Employee> stream = list.stream();
//2.中間操作(支持0——n步)
//3.終止操作
boolean allMatch = stream.anyMatch(e->e.getSalary()>10000);
System.out.println(allMatch);
}
/*
* 統(tǒng)計(jì)和迭代
* count
* max
* min
* forEach
*/
@Test
public void test2() {
//1.開始操作:創(chuàng)建Stream對(duì)象
Stream<Employee> stream = list.stream();
//2.中間操作(支持0——n步)
//3.終止操作
//方法1:count統(tǒng)計(jì)
// long count = stream.count();
// System.out.println(count);
//方法2:max求最大值
Optional<Employee> max = stream.max((o1,o2)->o1.getAge()-o2.getAge());
System.out.println(max);
}
/*
* 歸約
* reduce:反復(fù)結(jié)合流中的元素
*/
@Test
public void test3() {
//1.開始操作:創(chuàng)建Stream對(duì)象
Stream<Employee> stream = list.stream();
//2.中間操作(支持0——n步)
//3.終止操作
Optional<Double> sum = stream.map(Employee::getSalary).reduce((t,u)->t+u);
System.out.println(sum);
}
/*
*收集
* collect:收集
*/
@Test
public void test4() {
//1.開始操作:創(chuàng)建Stream對(duì)象
Stream<Employee> stream = list.stream();
//2.中間操作(支持0——n步)
//3.終止操作
List<Employee> collect = stream.collect(Collectors.toList());
System.out.println(collect);
}
//練習(xí)2:?jiǎn)T工姓名中包含“馬”的員工個(gè)數(shù)
@Test
public void exec2() {
Optional<Integer> reduce = list.stream().filter(t->t.getName().contains("馬")).map(t->1).reduce((t,u)->t+u);
System.out.println(reduce);
}
//練習(xí):返回最高的工資:
@Test
public void exec1() {
Optional<Double> max = list.stream().map(Employee::getSalary).max(Double::compare);
System.out.println(max);
}
}
JDK8對(duì)接口的改進(jìn)
JDK8:
說明:接口中允許出現(xiàn)靜態(tài)方法和默認(rèn)方法
語(yǔ)法:
靜態(tài)方法:
public static 返回類型 方法名(參數(shù)列表){
}
默認(rèn)方法:
public default 返回類型 方法名(參數(shù)列表){
}
使用特點(diǎn):
1、靜態(tài)方法不能被實(shí)現(xiàn)類或子接口繼承,只能通過所在的接口名調(diào)用!
2、默認(rèn)方法具備繼承性??梢员粚?shí)現(xiàn)類或子接口繼承過去
解決同名沖突的問題:
1、類優(yōu)先原則
當(dāng)父類或?qū)崿F(xiàn)的接口中出現(xiàn)了同名并且已經(jīng)實(shí)現(xiàn)好的方法時(shí),如果子類中沒有重寫,則默認(rèn)使用的是父類的方法
2、當(dāng)實(shí)現(xiàn)的多個(gè)接口中出現(xiàn)了同名并且已經(jīng)實(shí)現(xiàn)好的方法時(shí),子類必須重寫該方法,否則報(bào)錯(cuò)!
JDK9:
說明:接口中允許私有方法
語(yǔ)法:
private 返回類型 方法名(參數(shù)列表){
//代碼
}
Optional的特性
理解:
Optional實(shí)質(zhì)上是一個(gè)容器,里面包裝了具體類型的對(duì)象??梢员苊鈱?duì)象出現(xiàn)空指針異常的現(xiàn)象
方法:
of
ofNullable
orElse
重復(fù)注解
說明:jdk8支持重復(fù)注解
語(yǔ)法:
在被修飾的數(shù)據(jù)上方:
@注解類名
@注解類名
…
示例:
public class TestJava8Ann {
@MyAnn
@MyAnn
// @AnnArray({@MyAnn,@MyAnn})
String name;
}
@Repeatable(AnnArray.class)
@interface MyAnn{
//語(yǔ)法:類型 value() [default 值];
}
@interface AnnArray{
MyAnn[] value();
}
##日期API
第一代日期:
Date類
SimpleDateFormat類
Date date = new Date();//當(dāng)前時(shí)間
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh::mm::ss");
String dateString = sdf.format(date);
/**
* 此類用于演示第一代日期類
* Date
* new Date();
* getTime()
* SimpleDateFormat
* format
* parse
*/
public class TestDate1 {
//創(chuàng)建Date對(duì)象,表示一個(gè)時(shí)間,精確到毫秒
@Test
public void test1() {
//代表當(dāng)前系統(tǒng)時(shí)間
Date d1 = new Date();
System.out.println(d1);
//獲取距離1970-1-1的毫秒數(shù)
System.out.println(d1.getTime());
}
//測(cè)試SimpleDateFormat,格式化或解析日期
@Test
public void test2() throws ParseException {
Date d=new Date();
//1.創(chuàng)建SimpleDateFormat對(duì)象
//①使用默認(rèn)的格式 18-8-8 下午4:25
// SimpleDateFormat sdf = new SimpleDateFormat();
//②使用指定的格式【建議】
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh小時(shí)mm分鐘ss秒 S毫秒");
//-------------格式化日期(將日期轉(zhuǎn)換成字符串)------------
String format = sdf.format(d);
System.out.println(format);
//------------解析字符串為日期(將字符串轉(zhuǎn)換成日期)--------
String s = "2018年12月12日 12小時(shí)12分鐘12秒 12毫秒";
Date date = sdf.parse(s);
System.out.println(date);
}
}
第二代日期:
Calendar抽象類:更側(cè)重于獲取和設(shè)置日歷字段
Calendar date = Calendar.getInstance();
System.out.println(date);
int year = date.get(Calendar.YEAR);
int month = date.get(Calendar.MONTH);
int day = date.get(Calendar.DAY_OF_MONTH);
System.out.println(year+"年"+(month+1)+"月"+day+"日");
/**
* 此類用于演示第二代日期類
* Calendar
*/
public class TestDate2 {
@Test
public void test1() {
//1.獲取一個(gè)Calendar對(duì)象
Calendar c = Calendar.getInstance();
// System.out.println(c);
//2.獲取日歷字段
System.out.println("年:"+c.get(Calendar.YEAR));
System.out.println("月:"+(c.get(Calendar.MONTH)+1));
System.out.println("日:"+c.get(Calendar.DAY_OF_MONTH));
System.out.println("小時(shí):"+c.get(Calendar.HOUR));
System.out.println("分鐘:"+c.get(Calendar.MINUTE));
System.out.println("秒:"+c.get(Calendar.SECOND));
System.out.println("------------------------------------------");
//3.設(shè)置具體的時(shí)間
c.set(2000, 1, 1);
System.out.println("年:"+c.get(Calendar.YEAR));
System.out.println("月:"+(c.get(Calendar.MONTH)+1));
System.out.println("日:"+c.get(Calendar.DAY_OF_MONTH));
System.out.println("小時(shí):"+c.get(Calendar.HOUR));
System.out.println("分鐘:"+c.get(Calendar.MINUTE));
System.out.println("秒:"+c.get(Calendar.SECOND));
}
}
第三代日期:
//1.LocalDate/LocalTime/LocalDateTime————>Calendar
@Test
public void test1() {
//①創(chuàng)建日期對(duì)象
LocalDateTime ldt = LocalDateTime.now();
//System.out.println(ldt);
//②獲取日歷字段
int year = ldt.getYear();
int month = ldt.getMonthValue();
int day = ldt.getDayOfMonth();
int hour = ldt.getHour();
int minute = ldt.getMinute();
int second = ldt.getSecond();
System.out.println(year+"年"+month+"月"+day+"日 "+hour+"小時(shí)"+minute+"分鐘"+second+"秒");
}
//2.Instant————————>Date
@Test
public void test2() {
//①創(chuàng)建Instant對(duì)象
Instant now = Instant.now();
//②實(shí)現(xiàn)Instant和Date之間的轉(zhuǎn)換
//Instant——————>Date
Date date = Date.from(now);
System.out.println(date);
//Date——————>Instant
Instant instant = date.toInstant();
System.out.println(instant);
}
//3.DateTimeFormatter——————>SimpleDateFormat
/*
* 可以格式化LocalDateTime,也可以格式化Instant
*/
@Test
public void test3() {
LocalDateTime ldt = LocalDateTime.now();
//①創(chuàng)建DateTimeFormatter對(duì)象
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd kk::mm::ss");
//②格式化日期(日期——————>字符串)
String format = dtf.format(ldt);
System.out.println(format);
//③解析日期(字符串——>日期)
LocalDateTime parse = LocalDateTime.parse("2018-08-08 16::32::21", dtf);
System.out.println(parse);
}