JDK 7 Important Features


JDK 7

Language Enhancement

switch on String

Before JDK 7, only integral types 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) {
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 than using nested if-then-else statement.

This feature is handy in handling options specified in command-line arguments, which are Strings. For example (slightly neater code than using nested if-then-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 SwitchOnString {
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);
}
}

Binary Literals with prefix "0b"

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 BinaryLiteralTest {
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)

Underscore for Numeric Literals

In JDK 7, you could insert underscore(s) '_' in between the digits in an 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

In JDK 7, a single catch block can handle more than one exception types.

For example, before 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 '|'.

try {
......
} catch(ClassNotFoundException|SQLException ex) {
ex.printStackTrace();
}

[TODO] A complete example on file IO.

The try-with-resources Statement

For example, before JDK 7, we need to use a finally block, to ensure that a resource is closed regardless of whether the try statement completes normally or abruptly. The code is messy!

import java.io.*;
// Copy from one file to another file character by character.
// Pre-JDK 7 requires you to close the resources using a finally block.
public class FileCopyPreJDK7 {
public static void main(String[] args) {
BufferedReader in = null;
BufferedWriter out = null;
try {
in = new BufferedReader(new FileReader("in.txt"));
out = new BufferedWriter(new FileWriter("out.txt"));
int charRead;
while ((charRead = in.read()) != -1) {
System.out.printf("%c ", (char)charRead);
out.write(charRead);
}
} catch (IOException ex) {
ex.printStackTrace();
} finally { // always close the streams
try {
if (in != null) in.close();
if (out != null) out.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}

try {
in.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(resourses) is closed at the end of the statement. This results in cleaner codes.

import java.io.*;
// Copy from one file to another file character by character.
// JDK 7 has a try-with-resources statement, which ensures that
// each resource opened in try() is closed at the end of the statement.
public class FileCopyJDK7 {
public static void main(String[] args) {
try (BufferedReader in = new BufferedReader(new FileReader("in.txt"));
BufferedWriter out = new BufferedWriter(new FileWriter("out.txt"))) {
int charRead;
while ((charRead = in.read()) != -1) {
System.out.printf("%c ", (char)charRead);
out.write(charRead);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}

Type Inference for Generic Instance Creation

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
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);
}

for (String item: lst2) {
System.out.println(item);
}
}
}

Comments

Popular posts from this blog

Android Objective type Question and Answers

Android Questions and Answers for written exams

SCJP1.6 Question and Answers