Java SE 7 Features Part – 1 1

1. Introduction

The Java Platform, Standard Edition 7 is a major feature release. It contains new features and enhancements in many functional areas.
·        Highlights of Technology Changes in Java SE 7
Enhancements and additions have been made in the Java SE 7 release in the following technologies:
·        Java Language Enhancements
·        Class Loaders
·        Concurrency
·        I/O and NIO
·        Internationalization
·        JDBC Enhancements

2.  Language enhancements

2.1.Binary Literals

 In Java SE 7, the integral types (byte, short, int, and long) can also be expressed using the binary number system. To specify a binary literal, add the prefix 0b or 0B to the number.
The following examples, show binary literals:
 An 8-bit 'byte' value:
 byte aByte = (byte)0b00100001;
 A 16-bit 'short' value:
 short aShort = (short)0b1010000101000101;

2.2.Using underscores in numeric literals

In Java SE 7 and later, any number of underscore characters (_) can appear anywhere between digits in a numerical literal. To separate groups of digits in numeric literals, which can improve the readability of your code, this feature can be used. The underscore can be applied to primitive data types in any supported base (binary, octal, hexadecimal, or decimal), and to both integer and floating-point literals.
The following example shows other ways you can use the underscore in numeric literals:
 long creditCardNumber = 1234_5678_9012_3456L;
 long socialSecurityNumber = 999_99_9999L;
 float pi =   3.14_15F;
 long hexBytes = 0xFF_EC_DE_5E;

Underscores may generally be placed arbitrarily within the literals, but following are invalid locations:

·        At the beginning or end of a number
·        Adjacent to a decimal point in a floating point literal
·        Prior to an F or L suffix
·        In positions where a string of digits is expected
The following examples demonstrate invalid underscore placements:-
 float pi1 = 3_.1415F;      // Invalid; cannot put underscores adjacent to a decimal point
float pi2 = 3._1415F;      // Invalid; cannot put underscores adjacent to a decimal point
long number = 999_99_9999_L;     // Invalid; cannot put underscores prior to an L suffix
int x1 = 0x52_;            // Invalid; cannot put underscores at the end of a number
int x2 = 0_x52;            // Invalid; cannot put underscores in the 0x radix prefix

2.3.Using strings in switch Statements

Previously, only integer values were the valid arguments in a switch statement. Java 7 introduced another type that we can use in Switch statements: the String type. As such, the following code
public String getTypeOfDayWithSwitchStatement(String dayOfWeekArg) {
     String typeOfDay;
     switch (dayOfWeekArg) {
         case "Monday":
             typeOfDay = "Start of work week";
             break;
         case "Tuesday":
         case "Wednesday":
         case "Thursday":
             typeOfDay = "Midweek";
             break;
         case "Friday":
             typeOfDay = "End of work week";
             break;
         case "Saturday":
         case "Sunday":
             typeOfDay = "Weekend";
             break;
         default:
             throw new IllegalArgumentException("Invalid day of the week: " + dayOfWeekArg);
     }
     return typeOfDay;
}
In the above program, the dayOfWeekArg parameter is always compared against the case label by using the String.equals() method. The comparison of String objects in switch statements is case sensitive.

2.4.Using try-with-resources block

Resources such as Connections, Files, Input/OutStreams, etc. must be closed after the program is finished with it. Usually we use a try-finally block to close the respective resources. The use of the try-with-resources statement results in all of its resources being automatically closed when the try block exits. Any object that implements java.lang.AutoCloseable can be used as a resource for auto close.

The following example reads the first line from a file. It uses an instance of BufferedReader to read data from the file. BufferedReader is a resource that must be closed after the program is finished with it:

 static String readFirstLineFromFile(String path) throws IOException {
   try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    return br.readLine();
  }
}
In this example, the resource declared in the try-with-resources statement is a BufferedReader. The class BufferedReader, in Java 7 and later, implements the interface java.lang.AutoCloseable. Because the BufferedReader instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly (as a result of the method BufferedReader.readLine throwing an IOException).
A try-with-resources statement can have catch and finally blocks just like an ordinary try statement. In a try-with-resources statement, any catch or finally block is run after the resources declared have been closed. However, exceptions can still be thrown from these blocks.
Creating a resource that can be used with the try-with-resources technique
Let us, make up our own “resource” that can be used in a try-with-resource statement because it implements the java.lang.AutoCloseable interface. This “AutoCloseableDataSource” intentionally throws an exception when the overridden close method (the only one prescribed by the AutoCloseable interface) is called. The code listing for AutoCloseableDataSource is shown next.
package com.java7.languageEnhancement;

public class AutoCloseableDataSource implements AutoCloseable {
  public void manipulateResource() {
     // Perform some resource specific operation
     System.out
          .println("AutoCloseableDataSource - manipulateResource method executed");
  }

  @Override
  public void close() throws Exception {
     // Close the resource as appropriate
     System.out
          .println("AutoCloseableDataSource - close method executed");
  }
}

Now use this resource in try-with-resources block

 

public static void main(String[] arguments) throws Exception {
     try (AutoCloseableDataSource resource1 = new AutoCloseableDataSource()) {
        resource1.manipulateResource();
     }
  }
Output:
AutoCloseableDataSource – manipulateResource method executed
AutoCloseableDataSource – close method executed
Understanding suppressed exceptions
Suppressed exceptions are those exceptions that are not explicitly reported. In the case of the try-with-resources try block, exceptions may be thrown from the try block itself or when the resources created by the try block are closed. When more than one exception is thrown, exceptions may be suppressed.
Let’s now make this “AutoCloseableDataSource” intentionally throws an exception when the code using it attempts to use it and then continues its bad form by throwing another exception when the overridden close method.
public class AutoCloseableDataSource implements AutoCloseable {
  public void manipulateResource() throws Exception {
     // Perform some resource specific operation
     System.out
          .println("AutoCloseableDataSource - manipulateResource method executed");
     throw new ServiceException(
          "A problem has occurred in manipulating datasource");
  }

  @Override
  public void close() throws Exception {
     // Close the resource as appropriate
     System.out
          .println("AutoCloseableDataSource - close method executed");
     throw new TechnicalException(
          "A problem has occurred in AutoCloseableDataSource");
  }
}
Now use this resource in try-with-resources block
public static void main(String[] arguments) throws Exception {
     try (AutoCloseableDataSource resource1 = new AutoCloseableDataSource()) {
        resource1.manipulateResource();
     }
  }
Output:
AutoCloseableDataSource – manipulateResource method executed
AutoCloseableDataSource – close method executed
Exception in thread “main” com.java7.languageEnhancement.ServiceException: A problem has occurred in manipulating datasource
  at com.java7.languageEnhancement.AutoCloseableDataSource.manipulateResource(AutoCloseableDataSource.java:10)
  at com.java7.languageEnhancement.UsingTryWithResourcesBlock.main(UsingTryWithResourcesBlock.java:6)
  Suppressed: com.java7.languageEnhancement.TechnicalException
     at com.java7.languageEnhancement.AutoCloseableDataSource.close(AutoCloseableDataSource.java:19)
     at com.java7.languageEnhancement.UsingTryWithResourcesBlock.main(UsingTryWithResourcesBlock.java:7)
In the above example you can observe in the try-with-resources block, any exceptions associated with a close operation are suppressed when an exception is thrown from the block itself.
In support of this approach, a new constructor was added to the java.lang.Exception class along with two methods: addSuppressed and getSuppressed. Suppressed exceptions can be retrieved using the getSuppressed method. Programmer created exceptions can designate an exception as suppressed by using the addSuppressed method.
One doesn’t need to use try-with-resources to work with suppressed exceptions. To see both exceptions thrown during use and closure of AutoCloseableDataSource in conjunction with try-finally, I can make use of Throwable.addSuppressed(Throwable) as shown in the next code listing. In that listing, the try and finally clauses are enhanced to capture the exception thrown during use of the AutoCloseableDataSource and to add that caught exception to the actually-thrown exception as a suppressed exception.
public class SuppressedExceptions {
  /**
   * Method that uses AutoCloseableDataSource with traditional try-finally
   * statement.
   */
  public static void performTryFinally() throws Exception {
     final AutoCloseableDataSource datasource = new AutoCloseableDataSource();
     Throwable throwable = null;
     try {
        datasource.manipulateResource();
     } catch (Exception ex) {
        throwable = ex;
     } finally {
        try {
          datasource.close();
        } catch (Exception closingEx) {
          if (throwable != null) {
             closingEx.addSuppressed(throwable);
             throw closingEx;
          }
        }
     }
  }

  /**
   * Executable function demonstrating suppressed exceptions.
   */
  public static void main(String[] arguments){
     try {
        performTryFinally();
     } catch (Exception ex) {
        logger.error("Exception encountered: ", ex);
        final Throwable[] suppressedExceptions = ex.getSuppressed();
        final int numSuppressed = suppressedExceptions.length;
        if (numSuppressed > 0) {
          logger.error("\tThere are " + numSuppressed
               + " suppressed exceptions:");
          for (final Throwable exception : suppressedExceptions) {
             logger.error("\t\t" , exception);
          }
        } else {
          logger.error("\tNo Suppressed Exceptions.");
        }
     }
  }

}
Output:
AutoCloseableDataSource - manipulateResource method executed
AutoCloseableDataSource - close method executed
Exception encountered: <span style="text-decoration: underline;">com.java7.languageEnhancement.TechnicalException</span>
  There are 1 suppressed exceptions:
     <span style="text-decoration: underline;">com.java7.languageEnhancement.ServiceException</span>: A problem has occurred in manipulating datasource

2.5.Catching multiple exception types

In the pre Java 7 world, you would handle exceptions by writing separate catch blocks for different types of exceptions that can occur in the try block. In case of related exception, the derived class exceptions are listed above the base class exception, e.g. FileNotFoundException should be listed above IOException since former is derived from the latter. Java 7 multi catch block provides you the flexibility to combine such catch blocks, provided you have similar code to handle these exceptions.
Often, we have that kind of code:
} catch (FirstException ex) {
     logger.error(ex);
     throw ex;
} catch (SecondException ex) {
     logger.error(ex);
     throw ex;
}
So now, with that new feature, you can do
} catch (FirstException | SecondException ex) {
     logger.error(ex);
     throw ex;
}

2.6.Rethrowing exceptions with improved type checking

Java SE 7’s compiler analyzes rethrown exceptions more precisely than its predecessors, but only when no assignments are made to the rethrown exception’s catch block parameter (the parameter is effectively final). When an exception originates from the preceding try block and is a supertype/subtype of the parameter’s type, the compiler throws the actual type of the caught exception instead of throwing the type of the parameter (as is done in previous Java versions).
For example:
class SuperException extends Exception
{
}
class SubException1 extends SuperException
{
}

class SubException2 extends SuperException
{
}

In pre Java7 scenario:

void someMethod() throws SubException1, SubException2 {
  try {
   /* Something that can throw SubException1, SubException2 */ 
  }
  catch (Throwable e) {
    logger.log(e);
    throw e; // Error: Unreported exception Throwable
  }
}
So now, with that new feature, you can do:
void m() throws SubException1, SubException2 {
  try {
     /* Something that can throw SubException1, SubException2 */ 
  }
  catch (final Throwable e) {
    logger.log(e);
    throw e; // Compiles OK; can throw SubException1, SubException2
  }
}

Because of the improved type checking offered by final rethrow, source code that compiled under previous versions of Java might fail to compile under Java SE 7. For example:-

// BreakageDemo.java
public class BreakageDemo
{
   public static void main(String[] args) throws SuperException
   {
      try
      {
         throw new SubException1();
      }
      catch (SuperException se)
      {
         try
         {
            throw se;
         }
         catch (SubException2 se2)
         {
         }
      }
   }
}

 

The above example compiles under Java SE 6 and earlier. However, it fails to compile under Java SE 7, whose compiler detects and reports the fact that SubException2 is never thrown in the body of the corresponding try statement.

2.7.Type inference for generic instance creation

Until now when you create an object of a class with parameterized types, we need to specify the type both in the declaration (left of =) and also in the call to constructor (right of =).
Map<String, List<String>> myMap = new HashMap<String, List<String>>();
In Java 7, you can substitute the parameterized type of the constructor with an empty set of type parameters (<> the diamond operator).
Map<String, List<String>> myMap = new HashMap<>();
If the compiler can infer the type arguments from the context, it does all the work for you. Note that you have always been able do a “new HashMap ()” without the type, but this results in an unchecked conversion warning.

One comment on “Java SE 7 Features Part – 1

  1. Reply wiecej Aug 29,2013 1:15 pm

    It is in point of fact a great and useful piece of info. I??m satisfied that you shared this useful information with us. Please keep us informed like this. Thank you for sharing.

Leave a Reply