As with every new Java version, Java 7 introduced some new features. The new features are definitely worth the change and as developers, we must be happy as we can be more efficient. There are many features introduced in Java 7 but we will look at some of them.
- Allows Strings to be used in ‘case’ switch statements.
- Try with resources
- Custom Autocloseable Class
- Using underscore characters in numeric values.
- Multi-catch Exceptions
- Improved Type reference for Generic Instance creation
- Binary literals
Lets look at these features one by one.
Strings In Switch Statements
In all computer languages that I know of, switch case statements can switch either on int or char type. If at all, we needed to switch based on Strings, then we had to figure out some workarounds using char data types or else switch to “if-else” logic to do that. And Java allowed ‘enum’ types also to be used in switch statement. But still we were not able to switch based on strings in switch case statements till Java 7.
Java 7 officially supports using Strings in switch case statements. This can definitely save developers some time instead of opting for workarounds. A good research topic would be trying to figure out the reasons Java took so long for Strings to be included in switch case statements!. An example is illustrated below: (this code will not compile in any version below Java 7)
public class TestSwit { public static void main(String[] args) { String java7_switch; System.out.println("Enter a test string"); java7_switch = StdIn.readString(); switch (java7_switch) { case "Java 4": System.out.println("Java 4"); break; case "Java 2": System.out.println("Java 5"); break; case "Java 6": System.out.println("Java 6"); break; case "Java 7": System.out.println("Java 7 ..."); } } }
Try With Resources Statements
This is my favorite of all the new features in Java 7 and shortly, you will see the reasons for my bias towards this particular feature. Lets look at an example.
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class Java6TryCatch { public static void main(String[] args) { String filename = "test.txt"; BufferedReader br = null; FileReader test = null; try { test = new FileReader(filename); br = new BufferedReader(test); String lines = ""; while ((lines = br.readLine())!=null){ System.out.println(lines); } } catch (IOException | SQLException e) { e.printStackTrace(); } finally { try { br.close(); test.close(); } catch (IOException e) { e.printStackTrace(); } } } }
This program is pretty straightforward to understand. It reads from a file line by line and prints out the content. The class FileReader throws IOException and the BufferedReader class throws a checked IOException. Since these are checked exceptions, I am surrounding this piece of code in a try-catch block. And at last, I need to close the opened resources and so use br.close() in the finally block to close the file. This finally block will be called regardless of an exception occurs or not. And then again in the finally block, since br.close() throws a checked exception, that is also surrounded with try-catch block.
Think of a scenario where there are 10 checked exceptions that need to be handled. Either we can throw them to the parent class and catch them all under the parent java.io.Exception class. But applications needs sophisticated error messages to be displayed and so we need to handle each exception differently. So we will have 10 try-catch blocks, and one finally block to clean up all resources. Again, we may have several try-catch blocks inside finally block as it may throw some checked exceptions just like shown in our example.
Do you get an idea of the volume of code in catch block first and then almost similar exceptions being handled in finally block while cleaning up opened resources. Wouldn’t it be if Java made it simpler to code?. Yes. Java 7 does this exactly and it is called Try-with-Resources statement. This is how it works.
try(BufferedReader buff = new BufferedReader( new FileReader(filename))) { String lines = ""; while ((lines = br.readLine())!=null) { System.out.println(lines); } }
Almost 5-6 lines of code has been coded in just one line of code. This method of handling the cleanup of resources using only “try” statement is called Try-With-Resources statement. But then are we missing something? You may ask where is the br.close() method!. In our example, the FileReader and BufferedReader classes implement java.lang.AutoCloseable interface, which takes care of closing these resources. I will also provide an example of this AutoCloseable interface in this article.
Also, multiple try-with resources can be used by separating them with a semi-colon; eg.,
try(FileReader fRead = new FileReader(filename); BufferedReader buff = new BufferedReader(fRead) { /* Other code here */ }
If you are wondering in which order these resources will be closed. Javadocs has an answer. It will be closed in the opposite order it appears in the Try-With-resources statement. So, in our case first buff.close() will be called and then fRead.close() will be called. Also, what about the exceptions handling. Though the fRead.close() and buff.close() methods implements AutoCloseable interface, exceptions in the try block exceptions take preference over the close() exceptions. In other words, if exceptions occur in try-with-resources statement and close() method, only the try-with-resource exception will be passed back to the stack and the close() methods exception will be suppressed. Also if needed, there are methods to get this suppressed exception also. So the try-with-resources exception take precedence over exceptions in AutoCloseable interface.
Custom AutoCloseable Class
I will provide an example, which extends this AutoCloseable interface so that we can use it if required in our own classes.
java.lang.AutoCloseable interface:
public interface AutoCloseable { public void close() throws Exception; }
A test class extending the AutoCloseable interface. Any class implementing AutoCloseable interface has to implement only the close () method.
class TryClose implements AutoCloseable { @Override public void close() throw Exception { System.out.println(" Custom close method … close resources "); } }
Underscore Character In Numeric Values
This was introduced to improve the code readability. Underscores can be used wherever we use numeric values. Assume that you want to declare a number i.e., say 1 million, prior to Java 7, declaration would be something like this:
int million = 1000000;
This may be hard to read, as the user may have to manually count the zeros and then figure out that if it is 1 million/10 million. Wouldn’t it be nice if we are allowed to declare as 1,000,000 clearly separating 1 million from 10 million using commas just as we do in Maths. Wouldn’t it improve code readability?
Exactly. This is what Java 7 address. Instead of comma, we are allowed to use underscore character (_) between numeric values.
int million = 1_000_000; double amount = 60.50_40_30;
Though there are certain rules that must be kept in mind, that is a _ can’t begin a numeral, a _ can’t precede/succeed a decimal point, it helps developers make the code readable.
int million = _100; // invalid double amount = 60._50; // invalid
Multi-Catch Exceptions
Lets look at the next feature – multi –catch exceptions. Before Java 7, we needed to have catch block for each of the different exceptions that needed to be handled.
try { new FileReader(filename); br = new BufferedReader(test); String lines = ""; while ((lines = br.readLine())!=null){ System.out.println(lines); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e){ e.printStackTrace(); }
From Java 7, we can handle multiple exceptions as part of the same catch block. It basically does the OR condition check and we can have as many exceptions as need and handle it the same way.
try { new FileReader(filename); br = new BufferedReader(test); String lines = ""; while ((lines = br.readLine())!=null){ System.out.println(lines); } } catch (FileNotFoundException | IOException e) { e.printStackTrace(); }
Improved Type reference For Generic Instance
This feature saves some coding/typing time. Before Java 7, we had to type this in order to compile,
ArrayList<string> list2 = new ArrayList<String>();
Now, from Java 7, we can safely ignore the right hand type, as Java will automatically infer the type from the left hand side. So we could write as below:
ArrayList<String> list2 = new ArrayList<>();
One thing to note is that we mustn’t ignore the <> operator on the right, otherwise we will get a compiler error. This operator is called the Diamond operator.
Binary Literals
From Java 7, (byte,short,int,long) can also be expressed in binary number system. We just need to add a prefix “0b” or “OB” before the number.
int binInt1 = 0b100; Long binLong = 0B100000000000L;
That’s it for this article on some of the new features introduced in Java7. Hope you enjoyed reading. Thanks for reading this article on Java 7 new features list.
This article is originally published at Java tutorials – Lets jump into the ocean, re-posted here with authors permission and as part of the JBC program.