The Best Technical Blog Ever

twitterrss

A Detailed look at Java 7's Features

Now everyone is talking about Java 8; but still developers are not familiar with changes introduced in Java 1.7. The Java 7 also included some amazing features like Strings in switch Statement, Binary Literals, automatic resource management, catching multiple exception in one catch block, using underscore on numeric literals and a few others which improved developer's day to day task. But there is very little known about these features.


Some of these features are summarized under the term Project Coin. The goal of Project Coin is to add a set of small language changes to JDK 7. These changes do simplify the Java language syntax. Less typing, cleaner, more readable and reliable code, happy developer ☻ Let's look into that.

  1. Numeric literals with underscores
  2. Binary literals with prefix 0b
  3. String in switch statements
  4. The try with resources statement
  5. Multi-catch
  6. More precise rethrow
  7. Type inference for generic instance creation
  8. Simplified varargs method invocation
  9. Fork Join framework
  10. Java.nio.file package
  11. The G1 collector

Here, the first 7 features are supported as part of Project Coin. In this post, we drill down on all these enhancements with examples


1. Numeric literals with underscores:

To improve readability of your code, java 7 enables this feature by adding any number of underscores (_) between digits in a numerical literal and separates this numeric literal into groups of digits. For example, if your code contains numbers with several digits, you can separate the digits in groups of three with underscore character like a comma, or a space, as a separator.


Examples:
float pi = 	3.14_15F;
long bytes = 0b11010010_01101001_10010100_10010010;
long debitCardNumber = 2453_5678_9012_3456L;

Rules:
  • You can place underscores only between digits; but you cannot place underscores at the beginning or end of a number.
    int a = 501_; // Invalid;

  • you cannot put underscores adjacent to a decimal point in a floating point literal
    float pi = 3._1415F; // Invalid;
    float pi = 3_.1415F; // Invalid;

  • Multiple underscores are allowed between digits.
    int a=56___32; // valid number.

  • You cannot place underscores prior to an F or L suffix.

  • You can't use underscores where you are expecting a string with digits. For example
    int d= Integer.parseInt("12_3"); -will throw java.lang.NumberFormatException. java.lang.NumberFormatException: For input string: "12_3".

Example :
java7 underscore


2. Binary Literals with prefix "0b":

In JDK 7, you can express literal values in binary notation with prefix '0b' (or '0B') for integral types (byte, short, int and long). In earlier versions, you can only use octal values (with prefix '0') or hexadecimal values (with prefix '0x' or '0X').


Examples:
int mask = 0b01000101;
int x = 0B0011_0000_1010_0010_1101_0000_1010_0010;

It is very helpful to bit-oriented systems like processors, network protocols and bitmapped hardware device.


Example :
java7 binary


3. String in switch statements:

Before java 7, only integral types (byte, short, int and long) can be used as selector for switch-case statement. However, for string variables, we have to use multiple if-then-else branches; because you cannot use string in switch in previous versions.


Example :
string

But java 7 primarily aimed to reduce code complexity related with usage of multiple if-else-if for comparing string or mapping those String to final integer constant or char constant to use them inside switch. To support String, Java7 included the enhanced Switch statement, which takes a String type as an argument. However, it looks like same old Java switch statement but differs in case statements. Switch case uses String.equals() method to compare the passed value with case values.


Example :
java7 string


4. The try with resources statement (or)Automatic Resource Management (ARM):

In earlier java versions, you had to use a finally block to close the resource manually that are no longer used such as a file, a SQL statement, etc.


If we forgot to release those resources in the finally block, then it creates a leaky-sources.


Example:
java exception


Here, the programmer has to close the resource explicitly and need to surround it with a try catch block and all inside the finally. This is a standard repeated code in java projects. To avoid this situation, Java 7 introduced a new feature called try-with-resources. Using this feature, the above program can be written as,


Example :
java exception

Using this try-with-resources block, we can give multiple resources. But that resources should be separated by a semicolon(;). The last resource should not be followed by a semicolon.


Example :
java exception

This feature automatically closes the resources when the program exits the try-with-resources block. Because, java 7 included the AutoCloseable interface, which has a close() method. This interface is made of the base interface of the Closeable interface. It ensures that you can use all old stream classes with try-with-resources, because they implement the AutoCloseable interface. See here for more detailed information on try-with-resource's suppressed exceptions .



5. Multicatch Statement:

To avoid duplication code in multiple catch blocks, Java 7 adds the feature called multicatch statement. Because of this feature, it is possible to catch multiple different exceptions in the same catch block by using pipe (|) characters. That means, just list out the types to handle in multicatch separated by pipe (|) characters.


But multicatch is mainly used for exceptions in different inheritance hierarchies. We can list many Exception types as we want until none of them have a super class/subclass relationship with each other.


Example :
java exception

In java, it is legal code to assign a new value to the catch block's parameter when there is only one type listed.


Examples:
catch(IOException e)
{
      e=new IOException();
}

However, Each multi-catch parameter is implicitly final. So it can't be assigned a new value. But, if you try to assign the parameter e of a multi-catch, compiler reports the error message like "The parameter e of a multi-catch block cannot be assigned".


6. More precise rethrow:

In some situations, we want to catch multiple exceptions of different types, do "something" with them, and rethrow them. Let us consider this example; which throws IOException and SQLException.


Example :
java rethrow

In the above example, we are logging each type of thrown exceptions before re-throwing them. This creates a duplication of code in the catch blocks.


Before Java 7, If the exception parameter of the catch clause, e, is of type Exception, then you have to specify the base Exception type in the throws clause. (public static void main(String[] args) throws Exception {)


Java 7 has added the "precise rethrow" feature which lets you catch and throw the base exception while still throwing the precise exception from the calling method. That means, you can specify the exception types IOException and SQLException in the throws clause. Even though the exception parameter of the catch clause, e, is type Exception. Because the java 7 compiler can determine that it is an instance of either IOException or SQLException.


Example :
java7 rethrow


7. Type Inference with the Diamond Operator for generic instance creation:

Java 5 introduced generics which allowed developers to write type safe collections. When working with Generics, you may have noticed complaints about types. Since in earlier java versions, you type more codes to specify types on both left and right hand side of object creation expression.


For example, to declare a map of student_records by generics, we write the code as follows:

Map< String, List < String >> student_records = new HashMap< String, 
						List< String >>();
List< String >  records= new ArrayList< String >();
Example :
diamondoperator

That means, when we are using generics you had to specify the type twice on both the sides, although the right hand side seems a bit redundant. Unluckily, this was a limitation of Java 5 and 6.


To get rid of this redundancy, java 7 introduces diamond operator<>. Using the diamond <> operator, it is possible to shorten the syntax used to create an instance of a generic type. In java7, the above code is written like this:

Map< String, List< String >> studentRecords = new HashMap<>();
List records = new ArrayList<>();
Example :
diamondoperator java7

Note the magic of Project Coin, here the instance creation portion simply uses < >, which is an empty type argument list. This is referred to as the diamond operator. It tells the compiler to infer the type arguments needed by the constructor in the new expression. Henceforth you don't have to write the whole list of types for the instantiation. Instead you can use the diamond operator.


The feature will surely save your fingers from some typing. Note that if you failed to declare the diamond operator as per syntax (<>), it will make the compiler generate a couple of type safety warnings.

List < String > records = new ArrayList();
Suppressing unchecked warnings:

It is possible to use the @SuppressWarnings annotation to suppress unchecked exceptions generated by the failure in using the diamond operator. For example,

@SuppressWarnings("unchecked")
List < String > records = new ArrayList();

8. Simplified varargs method invocation:

This Project Coin feature explains the removal of unchecked warning from the usage of varargs. All of you know, a varargs method is one that takes a variable number of parameters (all of the same type) at the end of the argument list. Basically, all of the variable parameters at the end are put into an array which is automatically created by the compiler; finally those parameters are passed as a single parameter. However, you always got compiler warning when calling certain varargs library methods that complains darkly about "unchecked or unsafe operations."


Java 7 provides a easy way to remove these compiler warning. Because of this feature, you can annotate your vararg method with new annotation type, java.lang.SafeVarargs. By annotating the method with @SafeVarargs, the developer essentially states that the method doesn't perform any unsafe operations. So, the compiler will suppress the warning and you won't get any of these warnings any more. Java7 will find all the places where @SafeVarargs annotation is applicable and suggest you to add this annotation.


Example :
safevarargs

Without the @SafeVarargs annotation this example would create warnings.



9. Fork Join Framework:

In prior java versions, main issue is parallelism. For this, java has given us concurrency concept but dealing with concurrency is not easy. But java's most attractive part is formulating things easier and easier. So java 7 introduced the new feature to solve this issue based on the concept of parallelism, called fork join framework. The aim is to use all the available processing power to enhance the performance of your application.


The fork/join framework supports parallel programming where problems are recursively split into smaller fragments, solved in parallel and recombined when all the problems are solved. The name itself implies it, divide one task into several subtasks until the subtask is simple enough that it can be solved without further breakups and join all the completed sub-tasks. It is based on a work-stealing algorithm. Because of this work-stealing algorithm, the idle workers steal the work from those workers who are busy. That means, here no worker thread is idle.


For that, new fork-join framework has been added in java.util.concurrent package. New fork-join executor framework has been formed which is responsible for creating one new task object which is again responsible for creating new sub-task object and waiting for sub-task to be completed. It maintains a thread pool internally. As with any ExecutorService implementation, the fork/join framework distributes tasks to worker threads in a thread pool. Worker threads that run out of things can steal tasks from other threads that are still busy.


The heart of the fork/join framework is the ForkJoinPool class, an extension of the AbstractExecutorService class. ForkJoinPool implements the core work-stealing algorithm and can execute ForkJoinTask processes.


Fork-join functionality is achieved by ForkjoinTask object, it has two method fork() and join () Method.


  • The fork() method allows a new ForkJoinTask to be created from an existing one.
  • The join() method allows a ForkJoinTask to wait for the completion of another one.

To implement this feature, first you have to write code that performs a segment of the work.


Example pseudocode:
if (task is small enough)
     do the work directly
else
     split the task into two pieces
     invoke the two pieces and wait for the results

You can wrap this code in a ForkJoinTask subclass either RecursiveTask or RecursiveAction. RecursiveAction represent executions that do not yield a return value. On the other hand, RecursiveTask returns an object of specified type. After your ForkJoinTask subclass is ready, create the object that represents all the work to be done and pass it to the invoke() method of a ForkJoinPool instance.



10. Java NIO.2 file package:

It refreshes the NIO library introduced in 2002 with Java 1.4. The NIO.2 has come forward with many enhancements. New classes are introduced to ease the life of a developer when working with multiple file systems. Java 7 introduced java.nio.file package and its related package, java.nio.file.attribute, to provide full support for file I/O and for accessing the default file system. It also introduced the Path class which allows you to represent any path in operating system.


New File system API complements older one and provides several useful methods for checking, deleting, copying, and moving files. It also provides a method to check if a file is hidden in Java. Using this features, you can also create symbolic and hard links from Java code. Again nio.2 gives one facility to watch a directory for modifications. These functionalities enables you to determine what kind of file or directory you are dealing with before you apply operations such as write or read. Also you can work with operations, such as reading, writing, creating, and opening files easily. See here to learn more about Java NIO.2 file package.



11. The G1 Collector:

The Garbage first collector (G1) introduced in JDK 7. The G1 collector utilizes several background threads to scan through the heap memory which is divided into multiple regions( earlier version has only 3 regions-{new, old and permgen space}), spanning from 1MB to 32MB (depending on the size of your heap). G1 garbage collector performs clean-up by scanning those regions that contain the most garbage objects first. It offers better throughput for memory intensive applications. G1 collector is enabled by using the -XX:+UseG1GC flag.


Keypoints to remember in java

1. Java is a high level, robust, secured , platform independent and object oriented programming.... more info

Back to Basics:- Java Syntax

In this session, you are going to refresh some basic set of rules(java syntax), defining how a ... more info

Total Visits
Traffic feed status