Every release of JDK involves few minor enhancements, which
are majorly overlooked under the shadow of major ones, but can be very handy in
day-to-day coding. In this article I tried to collate a list of such minor
enhancements (taken from JDK 5, 6 and 7), which can really make your code efficient,
clean and less error-prone.
Catching Multiple Exceptions in Single Catch Block (Since
JDK 7)
Consider an example
where your try block can throw multiple exceptions and those are caught
separately but the codes within catch blocks are same, as shown below
try {
//some code which can throw IOException and
ParseException
} catch (ParseException exception) {
//log the error
//create new custom exception
//throw exception
} catch (IOException exception) {
//log the error
//create new custom exception
//throw custom exception
}
The multiple catch blocks can be combined together as shown
below
try {
//some code which can throw IOException and
ParseException
} catch (ParseException | IOException exception) {
//log the error
//create new custom exception
//throw custom exception
}
This can improve the code reusability, exception handling
and overall code structure.
Try with Resources (Since JDK 7)
How many times you needed to take care of closing the
streams and other resources after performing write/read operations. Typically
we use finally blocks for these mandatory actions. But now the same can be
auto-close by Java, if you use try-with-resource blocks as shown below.
Older way:
FileInputStream fis = null;
try {
fis = new FileInputStream("SomeFile")
//Do something with
File input stream, but you needn't to close it.
} catch (IOException ioException)
{
//Do something
}
finally {
fis.close();
}
Try with resource statement:
try (FileInputStream fis = new FileInputStream("SomeFile")) {
//Do something with
File input stream, but you needn't to close it.
} catch (IOException ioException) {
//Do something
}
This will allow developers to avoid error of not closing the
resource and extra repeating code. Any implementation of AutoCloseable
interface can be used as resource with try block.
Switch with String (Since JDK 7)
A much awaited feature of Java. Prior to 7, only int or
enums were allowed inside switch statement, but with jdk 7, you can also work
with Strings inside switch, as shown below:
String day = "Tuesday";
switch (day) {
case "Monday" : //do something
break;
case "Tuesday" : //do something
break;
default : //for all other
days
break;
}
Underscore in Numeric Literals (Since JDK 7)
Many times, while using numerical literals, you found it
difficult to read its value for e.g.
long bankAccountNumber = 1007876345678L;
How good it would be, if we can use some separator for
better readability (for e.g. if first 3 digits indicates bank’s state wise
code, while next 4 for bank code and rest as individual number)? JDK 7 allows
you to use as many underscores as you need within the numeric literals. For
e.g.
long bankAccountNumber = 100_7876_345678L;
This greatly improves the readability of your code.
Type Inference for Generic Instance Creation (Since JDK 7)
Prior to Java 7, if you use generics, you need to pass type
arguments to call appropriate constructor, but with JDK 7 now that is options
hence the code,
Map> mapofMap = new
HashMap>();
Can now be replaced with
Map> mapofMap = new
HashMap<>();
This enhances the code readability, and avoid unnecessary repetition
of generic parameters.
Varargs (Since JDK 5)
How many times you need to create an array, may be of single
value, just because your method needs array as input? Let’s see the code below
public class Test {
public static void main(String[] args)
{
String
inputsingle = "SingleString";
new Test().needArray(new
String[]{inputsingle});
}
private void needArray(String[]
input) {
//do something with
string array
}
}
But now with JDK 5, the last parameter of the method can
have 3 dots to represent varargs, which means, the compiler will create the
array while invoking this method for you. Hence the above code can be written as
shown below:
public class Test {
public static void main(String[] args)
{
String
inputsingle = "SingleString";
new
Test().needArray(inputsingle);
new Test().needArray(new String[]{"a", "b","c"});
}
private void
needArray(String...input) {
//do something with
string array
}
}
Static Imports (Since JDK 5)
If you fade up using class name for static variables, you
can use static import as shown below.
Instead of writing code like
Color
black = Color.BLACK;
Color red =
Color.RED;
You would write like
import static
java.awt.Color.*;
and then use the static variable directly
Color black = BLACK;
Color red = RED;
This avoids the repeating prefixing of class name. But
beware, it can reduce the code readability as well. Read More: http://docs.oracle.com/javase/1.5.0/docs/guide/language/static-import.html
Rethrowing exceptions with improved types (Since JDK 7)
There are instances where, although you catch the higher
level exception but still, you want to throw specific exceptions. Let’s
consider the code below which is valid for JDK 6 and prior versions:
public void method() throws Exception {
try {
//Some code which
can throw Exception1 and Exception 2 (sublcasses of Exception)
}
catch (Exception e) {
throw e;
}
}
With the improved types in throws clause in JDK 7, now you
can also throw specific exceptions, thus the above method can also be written
as
public void method() throws Exception1,
Exception2 {
try {
//Some code which
can throw Exception1 and Exception 2 (sublcasses of Exception)
}
catch (Exception e) {
throw e;
}
}
As complier can understand that the code can only throw
Exception1 and Exception2, it allows to define method which can throw specific
exception, along with allowing the catch of higher level exception object.