JDK8十大特性


前言

简单总结JDK8十大特性

JDK8十大特性

1.Lambda表达式

2.Stream函数式操作流元素集合

3.接口新增:默认方法与静态方法

4.方法引用(双冒号运算),与Lambda表达式联合使用

5.引入重复注解

6.类型注解

7.最新的Date/Time API (JSR 310)

8.新增base64加解密API

9.数组并行(parallel)操作

10.JVM的PermGen空间被移除:取代它的是Metaspace(JEP 122)元空间

Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/**
* Description: JDK8的特性.
* All Rights Reserved.
*
* @version 1.0 2018/12/20
*/
public class Jdk8Features {
public List<Integer> list = Lists.newArrayList(1,2,3,4,5,6,7,8,9,10);

/**
* 1.Lambda表达式
*/
@Test
public void testLambda() {
System.out.println("方式一:双冒号");
list.forEach(System.out::println); // 双冒号的作用:就是把方法当做参数传到stream内部,使stream的每个元素都传入到该方法里面执行一下。
System.out.println("方式二:->方式");
list.forEach(x -> System.out.println(x)); // 第二种遍历打印的方式
}

/**
* 2.Stream函数式操作流元素集合
*/
@Test
public void testStream() {
List<Integer> nums = Lists.newArrayList(1, 1, null, 2, 3, 4, null, 5, 6, 7, 8, 9, 10);
int total = nums.stream()
.filter(v -> v != null) // 过滤非空
.distinct() // 去重
.mapToInt(v -> v*2) // map操作
.skip(2) // 跳过前两个元素
.limit(4) // 限制取前四个元素
.peek(System.out::println) // 流式处理对象函数
.sum(); // 求和
System.out.println("求和:" + total);
}

/**
* 3.接口新增功能:interface可以实现默认方法和静态方法
* default 接口默认实现方法是为了让集合类默认实现这些函数式处理,而不用修改现有代码
* List接口继承Iterable接口,Iterable接口实现了默认方法default void forEach()
*/
@Test
public void testDefaultMethod() {
// 可以直接使用【接口名.静态方法】的方式来访问接口中的静态方法
Jdk8Interface1.staticMethod();
// 接口中的默认方法必须通过实现类调用
new Jdk8InterfaceImpl1().defaultMethod();
// 同时实现了多个接口的实现类,默认方法重名的时候必须重写
new Jdk8InterfaceImpl2().defaultMethod();
}

public class Jdk8InterfaceImpl1 implements Jdk8Interface1 {
// 实现接口后,因为默认方法不是抽象方法,所以可以不重写

// @Override
// public void defaultMethod() {
//
// }
}

public class Jdk8InterfaceImpl2 implements Jdk8Interface1,Jdk8Interface2 {
// 因为接口1和2,默认方法名相同,所以必须重写默认方法
@Override
public void defaultMethod() {
// 默认方法重名的时候,不能直接通过【super.默认方法】调用父类方法,需要用如下写法
Jdk8Interface1.super.defaultMethod();
Jdk8Interface2.super.defaultMethod();
System.out.println("实现类重写重名的默认方法");
}
}

/**
* 4.方法引用(双冒号语法),与Lambda表达式联合使用
*/
@Test
public void testMethodReference() {
// 构造器引用。语法是【Class:new】,或者【Class<T>::new】,要求构造器方法是没有参数的
final Car car = Car.create(Car::new);
final List<Car> cars = Arrays.asList(car);
// 静态方法引用,语法是【Class类名::静态方法】,要求接受一个Class类型的参数
Consumer<Car> consumer = Car::collide;
cars.forEach(consumer);
// 任意对象的方法引用,语法是【类名:成员方法】,要求无参
cars.forEach(Car::repair);
// 特定对象的方法引用,语法是【实例对象::成员方法】,要求有参数,在某个对象上调用方法,将列表中的元素作为参数传入
final Car police = Car.create(Car::new);
cars.forEach(police::follow);
}

public static class Car {
public static Car create(final Supplier<Car> supplier) {
return supplier.get();
}

public static void collide(final Car car) {
System.out.println("静态方法引用 " + car.toString());
}

public void repair() {
System.out.println("任意对象的方法引用 " + this.toString());
}

public void follow(final Car car) {
System.out.println("特定对象的方法引用 " + car.toString());
}
}

/**
* 5.引入重复注解
* 1.@Repeatable
* 2.可以不用jdk8以前的“注解容器”写法,直接写两次相同注解即可
* <p>
* Java 8在编译器层做了优化,相同注解会以集合的方式保存,因此底层的原理并没有变化。
*/
@Test
public void RepeateAnnotation() {
RepeateAnnotation.main(null);
}

/**
* 6.新增类型注解
* 新增类型注解: ElementType.TYPE_PARAMETER 表示这个 Annotation 可以用在 Type 的声明式前,
* ElementType.TYPE_USE 表示这个 Annotation 可以用在所有使用 Type 的地方(如:泛型,类型转换等)。
*/
@Test
public void elementType() {
Annotations.main(null);
}

/**
* 7.最新的Date/Time API(JSR 310)
*/
@Test
public void dateTime() {
// Arrays.asList(TimeZone.getAvailableIDs()).forEach(System.out::println);
// 1.Clock
final Clock clock = Clock.systemUTC();
System.out.println(clock.getZone());
System.out.println(clock.instant());
System.out.println(clock.millis());

// 2.ISO-8601格式且无时区信息的日期部分
final LocalDate date = LocalDate.now();
final LocalDate date1 = LocalDate.now(clock);

System.out.println(date);
System.out.println(date1);

// 3.ISO-8601格式且无时区信息的时间部分
final LocalTime time = LocalTime.now();
final LocalTime time1 = LocalTime.now(clock);

System.out.println(time);
System.out.println(time1);

// 4.特定时区的日期/时间
final ZonedDateTime zonedDateTime = ZonedDateTime.now();
final ZonedDateTime zonedDateTime1 = ZonedDateTime.now(clock);
final ZonedDateTime zonedDateTime2 = ZonedDateTime.now(ZoneId.of("America/Los_Angeles"));

System.out.println(zonedDateTime);
System.out.println(zonedDateTime1);
System.out.println(zonedDateTime2);

// 5.在秒与纳秒级别上的一段时间
final LocalDateTime from = LocalDateTime.of(2014, Month.APRIL, 16, 0, 0, 0);
final LocalDateTime to = LocalDateTime.of(2015, Month.APRIL, 16, 23, 59, 59);

final Duration duration = Duration.between(from, to);
System.out.println("Duration in days: " + duration.toDays());
System.out.println("Duration in hours: " + duration.toHours());
}

/**
* 8.新增base64加解密API
*/
@Test
public void testBase64() {
final String text = "附近可大幅拉打开了房间克拉克拉发咖啡的快乐";
String encoded = Base64.getEncoder().encodeToString(text.getBytes(StandardCharsets.UTF_8));
System.out.println("加密后:" + encoded);

final String decoded = new String(Base64.getDecoder().decode(encoded), StandardCharsets.UTF_8);
System.out.println("解密后:" + decoded);
}

/**
* 9.数组并行(parallel)操作
*/
@Test
public void testParallel() {
long[] arry = new long[20000];
// 1.给数组随机赋值
Arrays.parallelSetAll(arry, index -> ThreadLocalRandom.current().nextInt(1000000));
// 2.打印出前10个元素
Arrays.stream(arry).limit(10).forEach(v -> System.out.print(v + " "));
System.out.println();
// 3.数组排序
Arrays.parallelSort(arry);
// 4.打印排序后的前10个元素
Arrays.stream(arry).limit(10).forEach(value -> System.out.print(value + " "));
System.out.println();
}

/**
* 10.JVM的PermGen空间被移除:取代它的是Metaspace(JEP 122)元空间
*/
@Test
public void testMetaspace(){
//-XX:MetaspaceSize初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整
//-XX:MaxMetaspaceSize最大空间,默认是没有限制
//-XX:MinMetaspaceFreeRatio在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集
//-XX:MaxMetaspaceFreeRatio在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集
}
}

引用到的其他类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/**
* Description: jdk8中支持接口定义静态方法和默认方法.
* All Rights Reserved.
*
* @version 1.0 2018/12/20
*/
public interface Jdk8Interface1 {
// 1.接口中支持定义静态方法
public static void staticMethod() {
System.out.println("接口中的静态方法");
}

// 2.使用default可以定义为普通方法
public default void defaultMethod() {
System.out.println("接口中的默认方法");
}
}
/**
* Description: .
* All Rights Reserved.
*
* @version 1.0 2018/12/20
*/
public interface Jdk8Interface2 {
// 1.接口中支持定义静态方法
public static void staticMethod() {
System.out.println("接口2中的静态方法");
}

// 2.使用default可以定义为普通方法
public default void defaultMethod() {
System.out.println("接口2中的默认方法");
}
}

/**
* Description: 新增类型注解:ElementType.TYPE_USE, ElementType.TYPE_PARAMETER.
* All Rights Reserved.
*
* @version 1.0 2018/12/21
*/
public class Annotations {

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
public @interface NonEmpty {

}

public static class Holder<@NonEmpty T> extends @NonEmpty Object {
public void method() throws @NonEmpty Exception {

}
}

public static void main(String[] args) {
final Holder<String> holder = new @NonEmpty Holder<String>();
@NonEmpty Collection<@NonEmpty String> strings = new ArrayList<>();
}
}

/**
* Description: 重复注解@Repeatable.
* All Rights Reserved.
*
* @version 1.0 2018/12/20
*/
public class RepeateAnnotation {
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Filters {
Filter[] value();
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Filters.class)
public @interface Filter {
String value();

String value2();
}

@Filter(value = "filter1", value2 = "111")
@Filter(value = "filter2", value2 = "222")
// 注意:JDK8之前:1.没有@Repeatable2.采用本行“注解容器”写法
// @Filters({@Filter( value="filter1",value2="111" ),@Filter( value="filter2", value2="222")})
public interface Filterable {

}

public static void main(String[] args) {
// 获取注解后遍历打印
for (Filter filter : Filterable.class.getAnnotationsByType(Filter.class)) {
System.out.println(filter.value() + filter.value2());
}
}
}

其他博客

Java 8十个lambda表达式案例

Java 8 特性 – 终极手册

-------------本文结束感谢您的阅读-------------

本文标题:JDK8十大特性

文章作者:huihuicai

发布时间:2018年12月21日 - 18:39

最后更新:2018年12月21日 - 18:41

原始链接:http://yoursite.com/JDK8十大特性.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

您的支持将鼓励我继续创作!
分享
0%