Version | Year | New Language Features | Number of Classes and Interfaces |
1.0 | 1996 | The language itself | 200 |
1.1 | 1997 | Inner classes | 418 |
1.2 | 1998 | The strictfp modifier |
1,588 |
1.3 | 2000 | Nothing at all | 1,883 |
1.4 | 2002 | Assertions | 2,696 |
5.0 | 2004 | Generic classes, “for each” loop, varargs, autoboxing, metadata, enumerations, static import | 3,551 |
6 | 2006 | Nothing at all | 4,069 |
7 | 2011 | Switch with strings, diamond operator, binary literals, exception handling enhancements | 4,509 |
8 | 2014 | Lambda expressions, interfaces with default methods | 4,733 |
9 | 2017 | Modules | 6,603 |
10 | 2018 | var |
6,599 (!) |
11 | 2018 | Nothing at all | 4,910 (!!)—Java FX, JNLP, Java EE overlap, CORBA removed |
12 | 2019 | switch expression preview |
4,935 |
13 | 2019 | Text blocks preview | 4,904 |
StandardCharsets
subclass of Charset
StandardCharsets.UTF_8
can be autocompleted, don't have to ponder "UTF-8"
vs "UTF8"
vs "UTF_8"
Files.newBufferedReader(Path, Charset)
Scanner(..., Charset charset)
and PrintWriter(..., Charset charset)
FileReader
, FileWriter
openjdk-net-dev
mailing list
HttpURLConnection
HttpClient client = HttpClient.newBuilder() .followRedirects(HttpClient.Redirect.ALWAYS) .build();
HttpRequest request = HttpRequest.newBuilder() .uri(new URI("http://horstmann.com")) .GET() .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandler.asString());
client.sendAsync(request, HttpResponse.BodyHandler.asString()) .completeOnTimeout(errorResponse, 10, TimeUnit.SECONDS) .thenAccept(response -> ...);
jdk.incubator.httpclient
java.net.http
, with very minor API changes
HttpRequest.BodyProcessor.fromString(data)
→ HttpRequest.BodyPublishers.ofString(data)
URLEncloder
, MIME multipartthenAccept
lambda?
ExecutorService pool = Executors.newFixedThreadPool(NTHREADS); HttpClient.newBuilder() .followRedirects(HttpClient.Redirect.NORMAL) .executor(pool) .build() .sendAsync(request, HttpResponse.BodyHandlers.ofString()) .thenAccept(response -> . . .);
pool
String markdown = ````Writing about JavaScript ``` alert("JavaScript"); ``` in Markdown````
````
followed by newline?... String myNameInABox = ` +-----+ | Cay | +-----+`;
String myNameInABox = ` +-----+ | Cay | +-----+ `;
``
could be confused with empty string`
`
hard to see, hard to typeString myNameInABox = """ +-----+ | Cay | +-----+ """;
"""
required\n
\newline
and \s
escape sequences overcome zealous space stripping"
in """
Multiline | Raw | Interpolation | Postprocessing |
Yes | No | No | No |
switch
str(i) match { case '+' | '-' => sign = 44 - ch case ch if Character.isDigit(ch) => digit = Character.digit(ch, 10) case SPACE => -1 // Uppercase for constants case _ => sign = 0 }
obj match {
case x: Int => x
case s: String => Integer.parseInt(s)
case _: BigInt => Int.MaxValue // Caution: not case BigInt
case _ => 0
}
arr match { case Array() => 0 case Array(x, 0) => x case Array(x, rest @ _*) => rest.min }
val Array(first, second, rest @ _*) = arr for ((k, "") <- System.getProperties())
ch = obj instanceof String s && !s.isEmpty() ? s.charAt(0) : ' '
case String s case Point(var x, var y) case Point(var x, 0) case Point(var x, _) case String s && !s.isEmpty()
int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> 8; case WEDNESDAY -> 9; };
? :
->
default ->
->
?
case TUESDAY -> { logger.info("Tuesday"); 7 }
x -> x * x x -> { logger.info("Dare to be square"); return x * x }
case TUESDAY -> { logger.info("Tuesday"); return 7; }
case TUESDAY -> { logger.info("Tuesday"); break 7; } // JDK 12
case ... -> { for (int i = 0; i < a.length; i++) { if (a[i] == x) break i; // Error } break -1; }
case ... -> { ...; break out; } // A labeled break?
yield
switch (day) { case MONDAY, FRIDAY, SUNDAY -> // Multiple case labels numLetters = 6; // No fallthrough case TUESDAY -> { logger.info("Tuesday"); numLetters = 7; } case THURSDAY, SATURDAY -> numLetters = 8; default -> numLetters = 9; }
int numLetters = switch(day) { case MONDAY, FRIDAY, SUNDAY: yield 6; case TUESDAY: logger.info("Tuesday"); yield 7; case THURSDAY: logger.info("Thursday"); // Yay! Fallthrough case SATURDAY: yield 8; default: yield 9; };
Expression | Statement | |
No fallthrough | int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> 8; default -> 9; }; |
switch (day) { case MONDAY, FRIDAY, SUNDAY -> numLetters = 6; case TUESDAY -> { logger.info("Tuesday"); numLetters = 7; } case THURSDAY, SATURDAY -> numLetters = 8; default -> numLetters = 9; } |
Fallthrough | int numLetters = switch(day) { case MONDAY, FRIDAY, SUNDAY: break 6; case TUESDAY: logger.info("Tuesday"); break 7; case THURSDAY: logger.info("Thursday"); case SATURDAY: break 8; default: break 9; }; |
switch(day) { case MONDAY, FRIDAY, SUNDAY: numLetters = 6; break; case TUESDAY: logger.info("Tuesday"); numLetters = 7; break; case THURSDAY: logger.info("Thursday"); case SATURDAY: numLetters = 8; break; default: numLetters = 9; } |
Statement | Expression | |
Two-way branch | if /else |
? : |
Multi-way branch | switch |
switch |
int numLetters = day ?? MONDAY, FRIDAY, SUNDAY -> 6 : TUESDAY -> 7 : THURSDAY, SATURDAY -> 8 : 9;
switch
: Jump table with binary searchgit clone https://github.com/openjdk/loom cd loom git checkout fibers sh configure make images
FiberScope scope = FiberScope.open();
for (int i = 1; i <= NTASKS; i++) {
int n = i;
scope.schedule(() -> run(n));
}
scope.close(); // Autocloseable—can use try
-with-resources
Thread.sleep
makes the current fiber sleep:public static void run(int n) { try { Thread.sleep(1000); } catch (InterruptedException ex) { ex.printStackTrace(); } System.out.println(n); }
goto
go myfunc(); new Thread(this::myfunc).start();
goto
with branches, loops, functions
FiberScope scope = FiberScope.open(); for (int i = 1; i <= NTASKS; i++) { scope.schedule(this::myfunc); } scope.close();
static FiberScope open(Instant deadline, Option...options) static FiberScope open(Duration timeout, Option...options)
fiber.cancel()
to set cancel statusFiber.cancelled()
InterruptedException
/IOException
when cancelledFiberScope
constructor
CANCEL_AT_CLOSE
: Closing scope cancels all scheduled fibers instead of blockingPROPAGATE_CANCEL
: If owning fiber is canceled, any newly scheduled fibers automatically canceledIGNORE_CANCEL
: Scheduled fibers can't be canceledPROPAGATE_CANCEL
, IGNORE_CANCEL
inherited from parent scope