探索Java 9新特性:REPL实战演示

本文详细记录了在Index旧金山开发者大会上关于Java 9新特性的技术分享,重点演示了JShell REPL环境的使用,涵盖集合API更新、Stream增强、CompletableFuture改进等核心特性,并通过实际代码示例展示新API的用法。

探索Java 9在Index旧金山大会上的实践

Index开发者大会是由IBM组织的新会议,旨在促进软件开发技艺的发展。该活动于2018年2月20-22日在旧金山Moscone中心举行,这是一个知名的软件会议场所。这是我今年的第一个会议,非常兴奋受邀在两个不同轨道发表两场演讲(感谢IBM!)。在本文中,我们总结了第一场题为“使用REPL探索Java 9”的会议。

“使用REPL探索Java 9”属于编程语言和平台轨道,是一个现场编码环节,重点介绍有趣的Java 9 API。我们涵盖了4个现有API的更新——Collections、Stream、CompletableFuture和Optional,以及Java 9中的4个新API——Stackwalker、ProcessHandle、HTTP/2客户端和JShell本身。我非常享受这次演讲,反馈非常积极,演讲后走廊里的讨论也很有趣——感谢所有参与者!

该环节进行了直播,录制视频可在此处获取:

一如既往,幻灯片可在线获取(此处下载): 使用REPL探索Java 9 来自 Miro Cupak

如果你想自己尝试这些示例,请随意使用我的JShell会话导出:

  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
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
1+1

int x = 1+1

System.out.println(x)

Thread.sleep(2000)

/vars

/types

/list

/l

/help

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"))

IntStream.range(0,10).forEach(System.out::println)

IntStream.range(0,10).limit(5).forEach(System.out::println)

IntStream.range(0,10).skip(5).forEach(System.out::println)

IntStream.range(0,10).takeWhile(x -> x<5).forEach(System.out::println)

IntStream.range(0,10).dropWhile(x -> x<5).forEach(System.out::println)

IntStream.iterate(0, i -> i+2).filter(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.empty()

Optional.of("something")

Optional.of("something").ifPresent(System.out::println)

Optional.empty().ifPresent(System.out::println)

Optional.empty().ifPresentOrElse(System.out::println, () -> System.out.println("empty"))

Optional.of("something").ifPresentOrElse(System.out::println, () -> System.out.println("empty"))

Optional.empty().orElse("empty")

Optional.empty().orElseGet(() -> "empty")

Optional.empty().or(() -> Optional.of("empty"))

Optional.of("something").or(() -> Optional.of("empty"))

Optional.empty().stream().forEach(System.out::println)

Optional.of("something").stream().forEach(System.out::println)

CompletableFuture<String> cf = new CompletableFuture<String>()

cf.complete("done")

cf.get()

CompletableFuture<String> cf = new CompletableFuture<String>()

cf.get()

cf.completeExceptionally(new IllegalStateException())

cf.get()

CompletableFuture<String> cf = new CompletableFuture<String>()

cf.completeOnTimeout("timed out", 5, TimeUnit.SECONDS)

cf

cf

cf

cf.get()

CompletableFuture<String> cf = new CompletableFuture<String>()

cf.orTimeout(5, TimeUnit.SECONDS)

cf

cf

cf

cf

cf.get()

CompletableFuture<String> cf = new CompletableFuture<String>()

CompletableFuture<String> copy = cf.copy()

cf

copy

cf.complete("done")

cf

copy

copy.get()

CompletableFuture<String> cf = new CompletableFuture<String>()

CompletableFuture<String> copy = cf.copy()

copy.complete("done")

copy

cf

StackTraceElement[] st = new Throwable().getStackTrace()

st

StackWalker.getInstance().walk(s -> s.collect(Collectors.toList()))

StackWalker.getInstance().walk(s -> s.limit(3).collect(Collectors.toList()))

StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE).walk(s -> s.map(f -> f.getDeclaringClass()).collect(Collectors.toList()))

StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE).walk(s -> s.map(f -> f.getDeclaringClass()).filter(c -> c.equals(jdk.jshell.execution.Util.class)).collect(Collectors.toList()))

new ProcessBuilder().command("jps").start()

ProcessHandle.current().pid()

ProcessHandle.current().info()

ProcessHandle.current().info().commandLine()

ProcessHandle.allProcesses().map(p -> p.info().command()).collect(Collectors.toList()))

ProcessHandle.allProcesses().map(p -> p.info().command()).collect(Collectors.toList())

new ProcessBuilder().command("sleep", "3").start().toHandle().onExit().thenAccept(System.out::println)

ProcessBuilder jps = new ProcessBuilder().command("jps")

ProcessBuilder grep = new ProcessBuilder().command("grep", "JShell")

List<Process> pipeline = ProcessBuilder.startPipeline(List.of(jps, grep))

pipeline

new BufferedReader(new InputStreamReader(pipeline.get(1).getInputStream())).readLine()

HttpHandler handler = he -> {
    String body = "hello indexconf";
    he.sendResponseHeaders(200, body.length());
    try (OutputStream os = he.getResponseBody()){
        os.write(body.getBytes());
    }
}

/l handler

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())

CompletableFuture<HttpResponse<String>> response = client.sendAsync(request, BodyHandler.asString())

response.get().body()

JShell js = JShell.create()

List<SnippetEvent> events = js.eval("1+1")

js.variables().forEach(System.out::println)

events.stream().map(e -> e.status()).forEach(System.out::println)

events.stream().map(e -> e.snippet().source()).forEach(System.out::println)

events.stream().map(e -> e.value()).forEach(System.out::println)

/save -history indexconf.jsh
1
view raw indexconf.jsh hosted with ❤ by GitHub
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计