Java SE 7 (or JDK 7), codenamed Dolphin, was released on July 77, 2011.
JDK 7 New Language Features
JDK 7 introduces a few 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 re-throwing exceptions with improved type checking.
- Automatic resource management in
try
-resource statement. - Improved type inference for generic instance creation, aka the diamond operator
<>
. - Simplified
varargs
method declaration.
Strings in switch's Selector
Prior to JDK 7, only integral types (such as int
, char
) can be used as selector for switch-case
statement. From JDK 7, you can use a String
object as the selector. For example,
public class J7SwitchStringTest {
public static void main(String[] args) {
String day = "SAT";
switch (day) { // switch on String selector (JDK 7)
case "MON":
case "TUE":
case "WED":
case "THU":
System.out.println("Working Day");
break;
case "FRI":
System.out.println("Thank God It's Friday");
break;
case "SAT":
case "SUN":
System.out.println("Gone Fishing");
break;
default:
System.out.println("Invalid");
}
}
}
String
's .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,
/** * This program accepts three command-line options * -c|--create : create * -v|--verbose : verbose * -d|--debug : debug * More than one options can be specified in any order. */ public class J7SwitchArgsTest { public static void main(String[] args) { boolean create = false; boolean verbose = false; boolean debug = false; for (String arg : args) { switch (arg) { // Switch on String selector (JDK 7) case "-c": case "--create": create = true; break; case "-v": case "--verbose": verbose = true; break; case "-d": case "--debug": debug = true; break; default: System.out.println("invalid option: " + arg); System.exit(1); } } System.out.println("create: " + create); System.out.println("verbose: " + verbose); System.out.println("debug: " + debug); } }
Binary Integer Literals with Prefix "0b" and Underscore in Numeric Literals
From JDK 7, you can express literal values in binary with prefix '0b
' (or '0B
') for integral types, 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
'). From JDK 7, you are also permitted to use underscore (_
) to break the digits to improve the readability but you must start and end with a digit. For examples,
int anInt1 = 0b01010000101000101101000010100010; // binary literal prefix with '0b' or '0B' int anInt2 = 0b0101_0000_1010_0010_1101_0000_1010_0010; // break digits with underscore for readability int anInt3 = 2_123_456; // break the digits with underscore byte aByte = (byte)0b0110_1101; // '0b' for int(32-bit), need to cast to byte(8-bit)/short(16-bit) short aShort = (short)0b0111_0101_0000_0101; long aLong = 0b1000_0101_0001_0110_1000_0101_0000_1010_0010_1101_0100_0101_1010_0001_0100_0101L; // long(64-bit) with suffix 'L' double aDouble = 3.1415_9265; // You can also use underscore on fractional part for readability float aFloat = 3.14_15_92_65f;
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)
Catching Multiple Exception Types and Re-throwing Exceptions with Improved Type Checking
Prior to JDK 7, you need two catch
blocks to catch two exception types even though both perform identical task. For example,
try { ...... } catch(ClassNotFoundException ex) { ex.printStackTrace(); } catch(SQLException ex) { ex.printStackTrace(); }
From JDK 7, you could use one single catch
block to handle more than one exception types, with the exception types separated by a vertical bar (|
). For example,
try { ...... } catch(ClassNotFoundException|SQLException ex) { ex.printStackTrace(); }
[TODO] A complete example on file IO.
Automatic Resource Management in try-with-resources Statement
Prior to 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 PreJ7FileCopy { 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 J7FileCopy { 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 J7GenericTest { 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 operator <> 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