Java 9 清洁代码实践与GeeCON大会技术解析

本文详细介绍了在GeeCON大会上展示的Java 9新特性实战应用,包括JShell交互式编程、集合工厂方法、Stream API增强、Optional更新等核心技术,通过现场演示代码展示了如何编写更简洁高效的Java代码。

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名演讲!

我要感谢组织者邀请我并创造了如此精彩的活动。我将来一定会再次参加这个会议!

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计