jdk9
https://docs.oracle.com/javase/9/
https://docs.oracle.com/javase/9/whatsnew/toc.htm#JSNEW-GUID-527735CF-44E1-4144-919B-E7D7CC9CDD4D
jlink & jmod
https://juejin.cn/post/7065273545768566792
https://docs.oracle.com/javase/9/tools/jlink.htm#JSWOR-GUID-CECAC52B-CFEE-46CB-8166-F17A8E9280E9
https://docs.oracle.com/javase/9/tools/jmod.htm#JSWOR-GUID-0A0BDFF6-BE34-461B-86EF-AAC9A555E2AE
New Version-String Scheme
https://docs.oracle.com/javase/9/whatsnew/toc.htm#JSNEW-GUID-527735CF-44E1-4144-919B-E7D7CC9CDD4D
The new version-string format is as follows:
$MAJOR.$MINOR.$SECURITY.$PATCH
JShell
core-java-volume-i-fundamentals-11th-edition_compress # 2.4
In the preceding section, you saw how to compile and run a Java program. Java 9 introduces another way of working with Java.
The JShell program provides a “read-evaluate-print loop,” or REPL. You type a Java expression; JShellevaluates your input, prints the result, and waits for your next input.
D:\JobBucket\HelloMaven>jshell
| 欢迎使用 JShell -- 版本 11.0.5
| 要大致了解该版本, 请键入: /help intro
jshell> "Core java".length()
$1 ==> 9
jshell> 5 * $1 -3
$2 ==> 42
jshell> int answer = 6 *7
answer ==> 42
jshell> Math.
E IEEEremainder( PI abs( acos( addExact( asin( atan( atan2(
cbrt( ceil( class copySign( cos( cosh( decrementExact( exp( expm1(
floor( floorDiv( floorMod( fma( getExponent( hypot( incrementExact( log( log10(
log1p( max( min( multiplyExact( multiplyFull( multiplyHigh( negateExact( nextAfter( nextDown(
nextUp( pow( random() rint( round( scalb( signum( sin( sinh(
sqrt( subtractExact( tan( tanh( toDegrees( toIntExact( toRadians( ulp(
jshell> Math.log(1000)
$4 ==> 6.907755278982137
jshell> Math.log10(1000)
$5 ==> 3.0
jshell>
JShell starts with a greeting, followed by a prompt:
Click here to view code image
Welcome to JShell -- Version 9.0.1
For an introduction type: /help intro
jshell>
Now type an expression, such as
"Core Java".length()
JShell responds with the result—in this case, the number of characters in the
string “Core Java”.
$1 ==> 9
Note that you do not type System.out.println. JShell automatically prints
the value of every expression that you enter.
The $1 in the output indicates that the result is available in further calculations.
For example, if you type
5 * $1 - 3
the response is
$2 ==> 42
If you need a variable many times, you can give it a more memorable name.
However, you have to follow the Java syntax and specify both the type and the
name. (We will cover the syntax in Chapter 3.) For example,
jshell> int answer = 6 * 7
answer ==> 42
Another useful feature is tab completion. Type
Math.
followed by the Tab key. You get a list of all methods that you can invoke on the
generator variable:
Click here to view code image
jshell> Math.
E IEEEremainder( PI abs(
acos( addExact( asin( atan(
atan2( cbrt( ceil( class
copySign( cos( cosh( decrementExact(
exp( expm1( floor( floorDiv(
floorMod( fma( getExponent( hypot(
incrementExact( log( log10( log1p(
max( min( multiplyExact( multiplyFull(
multiplyHigh( negateExact( nextAfter( nextDown(
nextUp( pow( random() rint(
round( scalb( signum( sin(
sinh( sqrt( subtractExact( tan(
tanh( toDegrees( toIntExact( toRadians(
ulp(
Now type l and hit the Tab key again. The method name is completed to log,
and you get a shorter list:
jshell> Math.log
log( log10( log1p(
Now you can fill in the rest by hand:
jshell> Math.log10(0.001)
$3 ==> -3.0
To repeat a command, hit the ↑ key until you see the line that you want to reissue
or edit. You can move the cursor in the line with the ← and → keys, and add or
delete characters. Hit Enter when you are done. For example, hit and replace
0.001 with 1000, then hit Enter:
jshell> Math.log10(1000)
$4 ==> 3.0
JShell makes it easy and fun to learn about the Java language and library without
having to launch a heavy-duty development environment and without fussing
with public static void main.
jcmd
https://docs.oracle.com/javase/9/tools/jcmd.htm#JSWOR743
troubleshoot
https://docs.oracle.com/javase/9/troubleshoot/toc.htm
Diagnostic Tools
https://docs.oracle.com/javase/9/troubleshoot/diagnostic-tools.htm#JSTGD114
Command-Line Options
https://docs.oracle.com/javase/9/troubleshoot/command-line-options1.htm#JSTGD592
The try-with-Resources Statement
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
https://docs.oracle.com/javase/9/language/toc.htm#JSLAN-GUID-B06D7006-D9F4-42F8-AD21-BF861747EDCF
core-java-volume-i-fundamentals-11th-edition_compress # 7.2.5 The try-with-Resources Statement
As of Java 7, there is a useful shortcut to the code pattern
open a resource
try
{
work with the resource
}
finally
{
close the resource
}
provided the resource belongs to a class that implements the AutoCloseable
interface. That interface has a single method
void close() throws Exception
In its simplest variant, the try-with-resources statement has the form
try (Resource res = . . .)
{
work with res
}
When the try block exits, then res.close() is called automatically. Here is a typical example—reading all words of a file
try (var in = new Scanner(
new FileInputStream("/usr/share/dict/words"), StandardCharsets.UTF_8))
{
while (in.hasNext())
System.out.println(in.next());
}
When the block exits normally, or when there was an exception, the in.close()
method is called, exactly as if you had used a finally block.
You can specify multiple resources. For example,
try (var in = new Scanner(
new FileInputStream("/usr/share/dict/words"), StandardCharsets.UTF_8);
var out = new PrintWriter("out.txt", StandardCharsets.UTF_8))
{
while (in.hasNext())
out.println(in.next().toUpperCase());
}
No matter how the block exits, both in and out are closed. If you programmed this by hand, you would have needed two nested try/finally statements.
As of Java 9, you can provide previously declared effectively final variables in the try header:
An “effectively final” variable is one whose value is never changed after it is initialized.
public static void printAll(String[] lines, PrintWriter out)
{
try (out) { // effectively final variable
for (String line : lines)
out.println(line);
} // out.close() called here
}
A difficulty arises when the try block throws an exception and the close method also throws an exception. The try-with-resources statement handles this situation quite elegantly.
The original exception is rethrown, and any exceptions thrown by close methods are considered “suppressed.”
They are automatically caught and added to the original exception with the addSuppressed method. If you are interested in them, call the getSuppressed method which yields an array of the suppressed expressions
from close methods.
You don’t want to program this by hand. Use the try-with-resources statement whenever you need to close a resource.
A try-with-resources statement can itself have catch clauses and even a finally clause. These are executed after closing the resources.
VarHandle(待学习)
https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/VarHandle.html
Convenience Factory Methods for Collections
Creating Immutable Lists, Sets, and Maps
Convenience static factory methods on the List, Set, and Map interfaces, which were added in JDK 9, let you easily create immutable lists, sets, and maps.
An object is considered immutable if its state cannot change after it is constructed. After you create an immutable instance of a collection, it holds the same data as long as a reference to it exists.
If the collections created using these methods contain immutable objects, then they are automatically thread safe after construction. Because the structures do not need to support mutation, they can be made much more space efficient. Immutable collection instances generally consume much less memory than their mutable counterparts.
As discussed in About Immutability, an immutable collection can contain mutable objects, and if it does, the collection is neither immutable nor thread safe.
Immutable List Static Factory Methods
The List.of static factory methods provide a convenient way to create immutable lists.
A list is an ordered collection, where duplicate elements are typically allowed. Null values are not allowed.
The syntax of these methods is:
List.of()
List.of(e1)
List.of(e1, e2) // fixed-argument form overloads up to 10 elements
List.of(elements...) // varargs form supports an arbitrary number of elements or an array
Example 3-1 Examples
In JDK 8:
List<String> stringList = Arrays.asList("a", "b", "c");
stringList = Collections.unmodifiableList(stringList);
In JDK 9:
List stringList = List.of("a", "b", "c");
See Immutable List Static Factory Methods.
Immutable Set Static Factory Methods
The Set.of static factory methods provide a convenient way to create immutable sets.
A set is a collection that does not contain duplicate elements. If a duplicate entry is detected, then an IllegalArgumentException
is thrown. Null values are not allowed.
The syntax of these methods is:
Set.of()
Set.of(e1)
Set.of(e1, e2) // fixed-argument form overloads up to 10 elements
Set.of(elements...) // varargs form supports an arbitrary number of elements or an array
Example 3-2 Examples
In JDK 8:
Set<String> stringSet = new HashSet<>(Arrays.asList("a", "b", "c"));
stringSet = Collections.unmodifiableSet(stringSet);
In JDK 9:
Set<String> stringSet = Set.of("a", "b", "c");
See Immutable Set Static Factory Methods.
Immutable Map Static Factory Methods
The Map.of and Map.ofEntries static factory methods provide a convenient way to create immutable maps.
A Map cannot contain duplicate keys; each key can map to at most one value. If a duplicate key is detected, then an IllegalArgumentException
is thrown. Null values cannot be used as Map keys or values.
The syntax of these methods is:
Map.of()
Map.of(k1, v1)
Map.of(k1, v1, k2, v2) // fixed-argument form overloads up to 10 key-value pairs
Map.ofEntries(entry(k1, v1), entry(k2, v2),...)
// varargs form supports an arbitrary number of Entry objects or an array
Example 3-3 Examples
In JDK 8:
Map<String, Integer> stringMap = new HashMap<String, Integer>();
stringMap.put("a", 1);
stringMap.put("b", 2);
stringMap.put("c", 3);
stringMap = Collections.unmodifiableMap(stringMap);
In JDK 9:
Map stringMap = Map.of("a", 1, "b", 2, "c", 3);
Example 3-4 Map with Arbitrary Number of Pairs
If you have more than 10 key-value pairs, then create the map entries using the Map.entry method, and pass those objects to the Map.ofEntries method. For example:
import static java.util.Map.entry;
Map <Integer, String> friendMap = Map.ofEntries(
entry(1, "Tom"),
entry(2, "Dick"),
entry(3, "Harry"),
...
entry(99, "Mathilde"));
See Immutable Map Static Factory Methods.
Randomized Iteration Order
The iteration order for Set elements and Map keys is randomized: it is likely to be different from one JVM run to the next. This is intentional — it makes it easier for you to identify code that depends on iteration order. Sometimes dependencies on iteration order inadvertently creep into code, and cause problems that are difficult to debug.
You can see how the iteration order is the same until jshell
is restarted.
jshell> Map stringMap = Map.of("a", 1, "b", 2, "c", 3);
stringMap ==> {b=2, c=3, a=1}
jshell> Map stringMap = Map.of("a", 1, "b", 2, "c", 3);
stringMap ==> {b=2, c=3, a=1}
jshell> /exit
| Goodbye
C:\Program Files\Java\jdk-9\bin>jshell
| Welcome to JShell -- Version 9-ea
| For an introduction type: /help intro
jshell> Map stringMap = Map.of("a", 1, "b", 2, "c", 3);
stringMap ==> {a=1, b=2, c=3}
The collection instances created by the Set.of, Map.of, and Map.ofEntries methods are the only ones whose iteration orders are randomized. The iteration ordering of collection implementations such as HashMap and HashSet is unchanged.
About Immutability
The collections returned by the convenience factory methods added in JDK 9 are conventionally immutable. Any attempt to add, set, or remove elements from these collections causes an UnsupportedOperationException to be thrown.
These collections are not “immutable persistent” or “functional” collections. If you are using one of those collections, then you can modify it, but when you do, you are returned a new updated collection that may share the structure of the first one.
One advantage of an immutable collection is that it is automatically thread safe. After you create a collection, you can hand it to multiple threads, and they will all see a consistent view.
However, an immutable collection of objects is not the same as a collection of immutable objects. If the contained elements are mutable, then this may cause the collection to behave inconsistently or make its contents to appear to change.
Let’s look at an example where an immutable collection contains mutable elements. Using jshell
, create two lists of String objects using the ArrayList class, where the second list is a copy of the first. Trivial jshell
output was removed.
jshell> List<String> list1 = new ArrayList<>();
jshell> list1.add("a")
jshell> list1.add("b")
jshell> list1
list1 ==> [a, b]
jshell> List<String> list2 = new ArrayList<>(list1);
list2 ==> [a, b]
Next, using the List.of method, create ilist1
and ilist2
that point to the first lists. If you try to modify ilist1
, then you see an exception error because ilist1
is immutable. Any modification attempt throws an exception.
jshell> List<List<String>> ilist1 = List.of(list1, list1);
ilist1 ==> [[a, b], [a, b]]
jshell> List<List<String>> ilist2 = List.of(list2, list2);
ilist2 ==> [[a, b], [a, b]]
jshell> ilist1.add(new ArrayList<String>())
| java.lang.UnsupportedOperationException thrown:
| at ImmutableCollections.uoe (ImmutableCollections.java:70)
| at ImmutableCollections$AbstractImmutableList.add (ImmutableCollections
.java:76)
| at (#10:1)
But if you modify the original list1
, ilist1
and ilist2
are no longer equal.
jshell> list1.add("c")
jshell> list1
list1 ==> [a, b, c]
jshell> ilist1
ilist1 ==> [[a, b, c], [a, b, c]]
jshell> ilist2
ilist2 ==> [[a, b], [a, b]]
jshell> ilist1.equals(ilist2)
$14 ==> false
Immutable and Unmodifiable Are Not the Same
The immutable collections behave in the same way as the Collections.unmodifiable… wrappers. However, these collections are not wrappers — these are data structures implemented by classes where any attempt to modify the data causes an exception to be thrown.
If you create a List and pass it to the Collections.unmodifiableList method, then you get an unmodifiable view. The underlying list is still modifiable, and modifications to it are visible through the List that is returned, so it is not actually immutable.
To demonstrate this behavior, create a List and pass it to Collections.unmodifiableList. If you try to add to that List directly, then an exception is thrown.
jshell> List<String> unmodlist1 = Collections.unmodifiableList(list1);
unmodlist1 ==> [a, b, c]
jshell> unmodlist1.add("d")
| java.lang.UnsupportedOperationException thrown:
| at Collections$UnmodifiableCollection.add (Collections.java:1056)
| at (#17:1)
But, if you change the original list1
, no error is generated, and the unmodlist1
list has been modified.
jshell> list1.add("d")
$19 ==> true
jshell> list1
list1 ==> [a, b, c, d]
jshell> unmodlist1
unmodlist1 ==> [a, b, c, d]
MethodHandle(待学习)
Enhances the MethodHandle, MethodHandles, and MethodHandles.Lookup classes of the java.lang.invoke package to ease common use cases and enable better compiler optimizations.
Additions include:
- In the MethodHandles class in the java.lang.invoke package, provide new MethodHandle combinators for loops and try/finally blocks.
- Enhance the MethodHandle and MethodHandles classes with new MethodHandle combinators for argument handling.
- Implement new lookups for interface methods and, optionally, super constructors in the MethodHandles.Lookup class.
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/invoke/MethodHandles.html
jdk10
https://docs.oracle.com/javase/10/
var
https://docs.oracle.com/javase/10/language/toc.htm#JSLAN-GUID-7D5FDD65-ACE4-4B3C-80F4-CC01CBD211A4
对应书籍的位置:4.3.5 Declaring Local Variables with var
Starting with Java 10, you do not need to declare the types of local variables if they can be inferred from the initial value. Simply use the keyword var instead of the type:
var vacationDays = 12; // vacationDays is an int
var greeting = "Hello"; // greeting is a String
List listBefore10 = new ArrayList<>(); # 在JDK10之前
var listAfter10 = new ArrayList(); # 在JDK10之后
listBefore10.add("9");
listAfter10.add("10");
限制
1. 必须初始化
var原理大抵是编译器通过初始化的值推断声明的类型,由此引出使用它的一个约束——声明的同时必须进行初始化。
# 错误示例
var listAfter10;
listAfter10 = new ArrayList();
listAfter10.add("10");
用以上代码直接编译运行,JDK会报错,提示:无法推断本地变量 listAfter10 的类型
2. 不能为null值
虽然进行初始化,但是使用null值的话,编译器仍然无法进行类型推断确定你最终的类型,也会报错。
3. 不能用于非局部变量
回看之前说到的官方声明,”type inference to declarations of local variables with initializers”,local variable只能用于局部变量的使用,全局变量或者对象属性声明都不行,例如下面示例是无法正常运行:
# 错误示例
public class Java10 {
public var field = "Not allow here";
}
4. 不能用于Lambda表达式类型的声明
编译器不支持推断匿名函数的类型,例如:
# 错误示例
var lambdaVar = (String s) -> s != null && s.length() > 0;
虽然使用了匿名函数,但是其返回值并不是一个Lambda表达式类型,也是可以的。
# 正确示例
var result = Arrays.asList("Java", "10").stream().reduce((x, y) -> x + y);
jdk11
https://docs.oracle.com/en/java/javase/11/
https://www.oracle.com/java/technologies/javase/11-relnote-issues.html#NewFeature
var用于lambda表达式中
https://docs.oracle.com/en/java/javase/11/language/local-variable-type-inference.html
https://openjdk.org/projects/amber/guides/lvti-style-guide
Formal parameter declarations of implicitly typed lambda expressions: A lambda expression whose formal parameters have inferred types is implicitly typed:
CopyBiFunction<Integer, Integer, Integer> = (a, b) -> a + b;
In JDK 11 and later, you can declare each formal parameter of an implicitly typed lambda expression with the var
identifier:
Copy(var a, var b) -> a + b;
Java HTTP Client(待学习)
https://openjdk.org/groups/net/httpclient/
https://openjdk.org/groups/net/httpclient/intro.html
Examples and Recipes
https://openjdk.org/groups/net/httpclient/recipes.html
Collection.toArray(IntFunction)
default <T> T[] toArray(IntFunction<T[]> generator)
Returns an array containing all of the elements in this collection, using the provided generator
function to allocate the returned array.
If this collection makes any guarantees as to what order its elements are returned by its iterator, this method must return the elements in the same order.
-
API Note:
This method acts as a bridge between array-based and collection-based APIs. It allows creation of an array of a particular runtime type. Use
toArray()
to create an array whose runtime type isObject[]
, or usetoArray(T[\])
to reuse an existing array.Supposex
is a collection known to contain only strings. The following code can be used to dump the collection into a newly allocated array ofString
:String[] y = x.toArray(String[]::new);
-
Implementation Requirements:
The default implementation calls the generator function with zero and then passes the resulting array to
toArray(T[\])
. -
Type Parameters:
T
- the component type of the array to contain the collection -
Parameters:
generator
- a function which produces a new array of the desired type and the provided length -
Returns:
an array containing all of the elements in this collection
-
Throws:
ArrayStoreException
- if the runtime type of any element in this collection is not assignable to the runtime component type of the generated arrayNullPointerException
- if the generator function is null -
Since:
11
Set<String> setStrings = Set.of("Kiran", "John", "Frank", "Sai");
String[] strings = setStrings.toArray(String[]::new);
for (String string : strings) {
System.out.println(string);
}
Flight Recorder(JFR) & ZGC(待学习)
Java Tutorial
https://docs.oracle.com/javase/tutorial/tutorialLearningPaths.html