Java SE 7 (or JDK 7), codenamed Dolphin, was released on July 77, 2011.
JDK 7 New Language Features
There are many small language changes (grouped under a project named Coin):
- Strings in
switch
statement. - Binary integer literals.
- Allowing underscores in numeric literals.
- Catching multiple exception types and rethrowing exceptions with improved type checking.
- Automatic resource management in
try
-statement. - Improved type inference for generic instance creation, aka the diamond operator
<>
. - Simplified varargs method declaration.
Strings in switch's Selector
Before JDK 7, only integral types (such as int
, char
) can be used as selector for switch-case
statement. In JDK 7, you can use a String
object as the selector. For example,
String day = "SAT";
switch (day) { // switch on String selector
case "MON": System.out.println("Monday"); break;
case "TUE": System.out.println("Tuesday"); break;
case "WED": System.out.println("Wednesday"); break;
case "THU": System.out.println("Thursday"); break;
case "FRI": System.out.println("Friday"); break;
case "SAT": System.out.println("Saturday"); break;
case "SUN": System.out.println("Sunday"); break;
default: System.out.println("Invalid");
}
String.equals()
method is used in comparison, which is case-sensitive. Java compiler can generate more efficient code on switch
than nested if-else statement.
This feature is handy in handling options specified in command-line arguments, which are String
s. For example, the following code is slightly neater code than using nested if-else statement:
/**
* This program accepts three command-line options
* -c : create
* -v : verbose
* -d : debug
* More than one options can be specified in any order.
*/
public class JDK7SwitchOnStringTest {
public static void main(String[] args) {
boolean create = false;
boolean verbose = false;
boolean debug = false;
for (String arg: args) {
switch (arg) {
case "-c": create = true; break;
case "-v": verbose = true; break;
case "-d": debug = true; break;
default:
System.out.println("invalid option");
System.exit(1);
}
}
System.out.println("create: " + create);
System.out.println("verbose: " + verbose);
System.out.println("debug: " + debug);
}
}
> javac JDK7SwitchOnStringTest.java
> java JDK7SwitchOnStringTest -c -d
create: true
verbose: false
debug: true
Binary Integer Literals with Prefix "0b" and Underscore in Numeric Literals
In JDK 7, you can express literal values in binary with prefix '0b
' (or '0B
') for integral types (byte
, short
, int
and long
), similar to C/C++ language. Before JDK 7, you can only use octal values (with prefix '0
') or hexadecimal values (with prefix '0x
' or '0X
').
You are also permitted to use underscore (_
) to break the digits to improve the readability but you must start and end with a digit, e.g.,
int number1 = 0b01010000101000101101000010100010;
int number2 = 0b0101_0000_1010_0010_1101_0000_1010_0010;
int number3 = 2_123_456; // break the digits with underscore
For example,
public class BinaryIntegerLiteralTest { public static void main(String[] args) { // Some 32-bit 'int' literal values int anInt1 = 0b0101_0000_1010_0010_1101_0000_1010_0010; int anInt2 = 0b0011_1000; // An 8-bit 'byte' literal value. By default, literal values are 'int'. // Need to cast to 'byte' byte aByte = (byte)0b0110_1101; // A 16-bit 'short' literal value short aShort = (short)0b0111_0101_0000_0101; // A 64-bit 'long' literal value. Long literals requires suffix "L". long aLong = 0b1000_0101_0001_0110_1000_0101_0000_1010_0010_1101_0100_0101_1010_0001_0100_0101L; // Formatted output: "%d" for integer in decimal, "%x" in hexadecimal, "%o" in octal. // Take note that "%b" prints true or false (for null), NOT binary. System.out.printf("%d(%x)(%o)(%b)\n", anInt1, anInt1, anInt1, anInt1); System.out.printf("%d(%x)(%o)(%b)\n", aByte, aByte, aByte, aByte); } }
1352847522(50a2d0a2)(12050550242)(true) 109(6d)(155)(true)
In JDK 7, you could insert underscore (_
) in between the digits in a numeric literals (integral and floating-point literals) to improve readability. For example,
int anInt = 0b10101000_01010001_01101000_01010001; double aDouble = 3.1415_9265; float aFloat = 3.14_15_92_65f;
Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking
In JDK 7, a single catch
block can handle more than one exception types.
For example, prior to JDK 7, you need two catch
blocks to catch two exception types although both perform identical task:
try { ...... } catch(ClassNotFoundException ex) { ex.printStackTrace(); } catch(SQLException ex) { ex.printStackTrace(); }
In JDK 7, you could use one single catch
block, with exception types separated by a vertical bar (|
).
try { ...... } catch(ClassNotFoundException|SQLException ex) { ex.printStackTrace(); }
[TODO] A complete example on file IO.
Automatic Resource Management in try-with-resources Statement
Before JDK 7, we need to use a try-catch-finally
statement to manage resources. We need a finally
block, to ensure that the resources are properly closed regardless of whether the try
completes normally or abruptly. The code is messy! For example,
import java.io.FileReader; import java.io.FileWriter; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; // Copy from one file to another file line by line. // Pre-JDK 7 requires you to close the resources using a finally block. public class FileCopyPreJDK7 { public static void main(String[] args) { BufferedReader src = null; BufferedWriter dest = null; try { src = new BufferedReader(new FileReader("in.txt")); dest = new BufferedWriter(new FileWriter("out.txt")); String line; while ((line = src.readLine()) != null) { System.out.println(line); dest.write(line); dest.newLine(); // write a newline } } catch (IOException ex) { ex.printStackTrace(); } finally { // always close the streams try { if (src != null) src.close(); // close() throw IOException if (dest != null) dest.close(); } catch (IOException ex) { ex.printStackTrace(); } } try { src.read(); // Trigger IOException: Stream closed } catch (IOException ex) { ex.printStackTrace(); } } }
JDK 7 introduces a try
-with-resources statement, which ensures that each of the resources in try(resources)
is properly closed at the end of the statement. This results in cleaner codes.
import java.io.FileReader; import java.io.FileWriter; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; // Copy from one file to another file line by line. // JDK 7 has a try-with-resources statement, which ensures that // each resource opened in try(resources) is closed at the end of the statement. public class FileCopyJDK7 { public static void main(String[] args) { try (BufferedReader src = new BufferedReader(new FileReader("in.txt")); BufferedWriter dest = new BufferedWriter(new FileWriter("out.txt"))) { String line; while ((line = src.readLine()) != null) { System.out.println(line); dest.write(line); dest.newLine(); } } catch (IOException ex) { ex.printStackTrace(); } // src and dest automatically close. // No need for finally to explicitly close the resources. } }
Improved Type Inference for Generic Instance Creation with the Diamond Operator <>
For example,
import java.util.*; public class JDK7GenericTest { public static void main(String[] args) { // Pre-JDK 7 List<String> lst1 = new ArrayList<String>(); // JDK 7 supports limited type inference for generic instance creation with diamond opeator <> List<String> lst2 = new ArrayList<>(); lst1.add("Mon"); lst1.add("Tue"); lst2.add("Wed"); lst2.add("Thu"); for (String item: lst1) System.out.println(item); // Mon // Tue for (String item: lst2) System.out.println(item); // Wed // Thu List<String> lst3 = List.of("Fri", "Sat"); // JDK 9 System.out.println(lst3); // [Fri, Sat] System.out.println(Arrays.toString(lst3.toArray())); // [Fri, Sat] lst3.forEach(System.out::println); // JDK 8 // Fri // Sat } }
Simplified varargs Method Declaration with @SafeVarargs Annotation
In JDK 7, you have the option of using @SafeVarargs
annotation to suppress the warning you get when compiling a method with a non-reifiable varargs parameter. This annotation should be used when the method ensures that only elements of the same type as the varargs parameter are stored in the varargs array.
Example [TODO]
JDK 7 Library Changes
New File IO Libraries (JSR 203)
JDK 7 added support for multiple file systems, file metadata and symbolic links in new packages java.nio.file
, java.nio.file.attribute
and java.nio.file.spi
.
Concurrency Utilities (JSR 166)
Timsort is used to sort collections and arrays of objects instead of merge sort
Library-level support for elliptic curve cryptography algorithms
Enhanced library-level support for new network protocols, including SCTP and Sockets Direct Protocol
JDK 7 Other New Features
JVM support for Dynamic Languages (JSR 292)
Upstream updates to XML and Unicode
REFERENCES & RESOURCES