GeeCON大会上的Java 9清洁代码实践
上周,我有幸参加了GeeCON大会。GeeCON是JVM领域中知名的会议,今年是其10周年纪念。在波兰克拉科夫举行的3天会议中,有1200多人参加了4个分会场的80多场演讲,演讲者超过70位。
这是我第一次参加GEECon。回顾起来,无论是在内容还是组织方面,这都是我参加过的最好的会议之一。会场设在电影院,坐在舒适的椅子上在大屏幕上观看演讲是一种美妙的体验。咖啡师冲泡的咖啡很美味,餐饮服务很棒,克拉科夫是我一直喜欢回来的美丽城市。我特别想称赞组织者对演讲者的周到照顾——提供体面的住宿、每日晚餐和饮品,甚至在活动后还有一日游。能参与其中是我的荣幸。
我进行了一场题为"使用Java 9编写清洁代码"的新演讲。这个环节是JDK 9中几个新特性的现场演示,这些特性可以让我们的代码更加清洁。我们首先描述了编写清洁代码的含义,接着介绍了JShell,最后使用JShell演示了集合的便利工厂方法、try-with-resources中的有效final变量、接口中的私有方法、匿名类的钻石操作符、Stream API增强、Optional的更新、StackWalker和HTTP/2客户端。我们还提供了以清洁方式使用这些特性的最佳实践。
JShell交互式演示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
1+1
int x = 1+1
System.out.println(x)
Thread.sleep(2000)
/vars
/types
/list
/l
/help
|
集合操作演示
1
2
3
4
5
6
7
8
9
10
11
|
Set<String> set = new HashSet<String>()
set.add("a")
set.add("b")
set.add("c")
Collections.unmodifiableSet(set)
List<Integer> list = List.of(1,2,3)
list.add(4) // 这行会抛出异常
list.getClass()
Map.ofEntries(entry(1, "hello"))
|
文件操作和接口特性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/open readfile.jsh
/l readFile
/ed readFile
readFile("/tmp/geecon.txt")
new FileInputStream("/tmp/geecon.txt").transferTo(System.out)
/open myinterface.jsh
/l MyInterface
/op myclass.jsh
/l MyClass
new MyClass().abstractMethod()
new MyClass().defaultMethod()
/ed MyInterface
new MyClass().defaultMethod()
new MyClass().privateMethod()
|
Stream API增强
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/open diamond.jsh
/l
/ed helloSupplier
helloSupplier.get()
IntStream.iterate(0, i -> i+2).filter(j -> j<100).forEach(System.out::println)
IntStream.iterate(0, i -> i+2).limit(50).forEach(System.out::println)
IntStream.iterate(0, i -> i+2).takeWhile(j -> j<100).forEach(System.out::println)
IntStream.iterate(0, i -> i<100, i -> i+2).forEach(System.out::println)
Stream.of(1)
Stream.of(null)
Stream.ofNullable(null)
Stream.ofNullable(null).count()
|
Optional改进
1
2
3
4
5
6
7
8
9
10
11
12
13
|
Optional.empty()
Optional.of("something")
Optional.of("something").ifPresent(System.out::println)
Optional.of("something").ifPresentOrElse(System.out::println, () -> System.out.println("empty"))
Optional.empty().ifPresentOrElse(System.out::println, () -> System.out.println("empty"))
Optional.empty().orElse("empty")
Optional.empty().orElseGet(() -> "empty")
Optional.empty().or(() -> Optional.of("empty"))
Optional.empty().stream().forEach(System.out::println)
Optional.of("something").stream().forEach(System.out::println)
List.of(Optional.of(1), Optional.empty(), Optional.of(2)).stream().filter(Optional::isPresent).map(Optional::get).forEach(System.out::println)
List.of(Optional.of(1), Optional.empty(), Optional.of(2)).stream().flatMap(Optional::stream).forEach(System.out::println)
|
StackWalker和HTTP客户端
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
|
StackTraceElement[] st = new Throwable().getStackTrace()
st
StackWalker.getInstance().walk(s -> s.collect(toList()))
StackWalker.getInstance().walk(s -> s.limit(3).collect(toList()))
StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE).walk(s -> s.map(f -> f.getDeclaringClass()).collect(toList()))
StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE).walk(s -> s.map(f -> f.getDeclaringClass()).filter(c -> c.equals(jdk.jshell.execution.Util.class)).collect(toList()))
HttpHandler handler = he -> {
String body = "hello geecon";
he.sendResponseHeaders(200, body.length());
try (OutputStream os = he.getResponseBody()) {
os.write(body.getBytes());
}
}
HttpServer hs = HttpServer.create(new InetSocketAddress(8000), 0)
hs.createContext("/hello", handler)
hs.start()
URI uri = new URI("http://localhost:8000/hello")
HttpURLConnection c = (HttpURLConnection) uri.toURL().openConnection()
c.setRequestMethod("GET")
c.getResponseCode()
new BufferedReader(new InputStreamReader(c.getInputStream())).readLine()
HttpClient client = HttpClient.newHttpClient()
HttpRequest request = HttpRequest.newBuilder().uri(uri).GET().build()
HttpResponse<String> response = client.send(request, BodyHandler.asString())
response.statusCode()
response.body()
CompletableFuture<HttpResponse<String>> response = client.sendAsync(request, BodyHandler.asString())
response.get().body()
|
外部代码示例
readfile.jsh:
1
2
3
4
5
6
7
8
9
|
void readFile(String file) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
try (BufferedReader reader2 = reader) {
String line;
while ((line = reader2.readLine()) != null) {
System.out.println(line);
}
}
}
|
myinterface.jsh:
1
2
3
4
5
6
7
|
interface MyInterface {
void abstractMethod();
default void defaultMethod() {
System.out.println("default method called");
}
}
|
myclass.jsh:
1
2
3
4
5
6
|
class MyClass implements MyInterface {
@Override
public void abstractMethod() {
System.out.println("abstract method called");
}
}
|
diamond.jsh:
1
2
3
4
5
6
7
8
|
List<String> myList = new ArrayList<>()
Supplier<String> helloSupplier = new Supplier<String>() {
@Override
public String get() {
return "hello geecon";
}
}
|
这场演讲被分配在估计容量为500人的大剧院进行。房间座无虚席,还有几个人坐在屏幕前的地板上。观众非常棒,提供了很多积极的反馈。事实上,他们将该演讲投票选为GeeCON的前10名演讲!
我要感谢组织者邀请我并创造了如此精彩的活动。我将来一定会再次参加这个会议!