Sunday, August 18, 2013

Java 7 features


String in Switch Statements

In JDK7 release, you can use String in the expression of a switch statement.

Example:

public class SwingJava7 {
public static void main(String arg[]){
String dayOfTheWeek="Monday"; // try to use 'm' instead of M
//String dayOfTheWeek=null; // null case
switch(dayOfTheWeek){
case "Monday":
System.out.println("Today is Monday");
break;
case "monday":
System.out.println("Today is monday");
break;
case "Tuesday":
System.out.println("Today is Tuesday");
break;
default :
throw new IllegalArgumentException("Invalid day:"+dayOfTheWeek);

}
}
}

Points to remember while using String in switch expression

  1. The switch statement compares the String object in its expression with the expressions associated with each case label as if it were using the String.equals method.
  2. String object in switch expression is case sensitive as it is using String.equals() method.
    You can check this case by changing 'M' to 'm' in the above example.
  3. Check null before switch case, otherwise you'll get NullPointerException.
    You can check this by uncommenting the line of "null case"


*A switch statement can be used with enums, strings, and primitive types byte, char,short, and int and their wrapper types; it cannot be used with a floating-point type


Binary Literals in java 7

A literal is the source code representation of a fixed value; literals are represented directly in your code without requiring computation.

For instance, you can write following things:


boolean result = true;
char capitalJ = 'J';
byte b = 99;
short s = 10000;
int i = 100000;


Integer can be expressed into following number systems:
Decimal: Base 10, whose digits consists of the numbers 0 through 9; this is the number system you use every day.
Hexadecimal: Base 16, whose digits consist of the numbers 0 through 9 and the letters A through F.
Binary: Base 2, whose digits consists of the numbers 0 and 1.


Now, 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

Example:

public class BinaryLiteralJava7 {
public static void main(String arg[]){
//byte: 8 bit
byte aByte = (byte)0b00100001;
//short: 16 bit
short aShort = (short)0b0010000101000101;
//int: 32 bit
int anInt = 0b00100001010001011010000101000101;
//long: 64 bit
long aLong = 0b0010000101000101101000010100010110100001010001011010000101000101L;
System.out.println("aByte:"+aByte+" aShort:"+aShort+" anInt:"+anInt+" aLong:"+aLong);
}


}


Underscores in Numeric Literals

Now any number of underscore characters (_) can appear anywhere between digits in a numerical literal.
Advantage:
This help you to to separate groups of digits in numeric literals, which can improve the readability of your code.

*You can place underscores only between digits.

Example:

public class UnderScoreJava7 {
public static void main(String[] args) {
long myCardNumber = 9857_1242_2653_1431L;
long hexBytes = 0xEE_CD_DE_8A;
System.out.println("myCardNumber:"+myCardNumber+" hexBytes:"+hexBytes);
}


}

Points to remember while declaring underscore in numeric literals:

  1. As earlier told, you can place underscores only between digits not at the beginning or end of a number.
    int x = _12; //wrong
    int y = 12_;//wrong
  2. You can't place underscore adjacent to a decimal point in a floating point literal.
    float x = 5_.1231F; //wrong
    float y = 5._1231F; //wrong
  3. You can't place underscore prior to an F in floar or L in long suffix.
    long x=1213_121_31_L;
    float y=1231.4_F;
  4. You can't place underscore in positions where a string of digits is expected.
    int x = 0_x34;
    int y = 0x_34;




The try-with-resources Statement

When you open a stream, you must close it. If done correctly, closing of the stream may require a lot of coding.

Example :

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class TryWithResourcesNormal {
public static void main(String[] args) {
BufferedReader inputStraam =null;
try{
inputStraam=new BufferedReader(new FileReader("output.txt"));
System.out.println(inputStraam.readLine());
}catch(IOException e){
e.printStackTrace();
}finally{
if(inputStraam!=null){
try {
inputStraam.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

}


}

If you see above code marked with red require a bit of code (for this case) to close a BufferedReader Stream. The following example uses a try-with-resources statement to automatically close a stream.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class TryWithResourcesJava7 {
public static void main(String[] args) {
BufferedReader inputStream =null;
try{
inputStream=new BufferedReader(new FileReader("c:\\output.txt"));
System.out.println(inputStream.readLine());
}catch(IOException e){
e.printStackTrace();
}
if(inputStream==null){
System.out.println("stream is close");
}else{
System.out.println("stream is close");
}
}


}

Note: 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.


Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking

Defining multiple exceptions in one catch block.

  • A single catch block can handle more than one type of exception and reduce code duplication.
Use | (or) as separator between exception types.

Simplify exception handling.

Rethrowing Exceptions with More Inclusive Type Checking
  • This enables you to specify more specific exception types in the throws clause of a method declaration.

Example 1:


public class MultiCatchNormal {

public static void main(String[] args) {
try{
int no1=Integer.parseInt(args[0]);
int no2=Integer.parseInt(args[1]);
int result=no1/no2;
System.out.println("result="+result);
}catch(NumberFormatException e){
//logger.log(e);
e.printStackTrace();
}catch(ArithmeticException e){
//logger.log(e);
e.printStackTrace();
}catch(ArrayIndexOutOfBoundsException e){
//logger.log(e);
e.printStackTrace();
}
}



public class MultiCatchJava7 {

public static void main(String[] args) {
try{
int no1=Integer.parseInt(args[0]);
int no2=Integer.parseInt(args[1]);
int result=no1/no2;
System.out.println("result="+result);
}catch(NumberFormatException | ArithmeticException | ArrayIndexOutOfBoundsException e ){
//logger.log(e);
e.printStackTrace();
}
}


}

Note: If a catch block handles more than one exception type, then the catch parameter is implicitly final. In this example, the catch parameter ex is final and therefore you cannot assign any values to it within the catch block.

Example 2:

public class MutliCatchTypeCastingNormal {

public static void main(String[] args) throws Exception {
MutliCatchTypeCastingNormal.rethrowFunction("11");
}

static void rethrowFunction(String type) throws Exception  {
try{
if(type.equals("1"))
throw new FirstException();
else
throw new SecondException();
}catch(Exception e){
e.printStackTrace();
}

}
}
class FirstException extends Exception{
FirstException(){
super("firstException");
}
}
class SecondException extends Exception{
SecondException(){
super("SecondException");
}
}

This examples's try block could throw either FirstException or SecondException.
Suppose you want to specify these exception types in the throws clause of the rethrowException method declaration. You cannot do so prior to java 7. Because the exception parameter of the catch clause, e, is type Exception, and the catch block rethrows the exception parameter e,you can only specify the exception type Exception in the throws clause of the rethrowException method declaration.

public class MutliCatchTypeCastingJava7 {
public static void main(String[] args) throws Exception {
MutliCatchTypeCastingJava7.rethrowFunction("11");
}
static void rethrowFunction(String type) throws FirstException1, SecondException1{
try{
if(type.equals("1"))
throw new FirstException1();
else
throw new SecondException1();
}catch(Exception e){
e.printStackTrace();
}
}

}

class FirstException1 extends Exception{
FirstException1(){
super("firstException");
}
}
class SecondException1 extends Exception{
SecondException1(){
super("SecondException");
}

}



Note: If a catch block handles more than one exception type, then the catch parameter is implicitly final. In this example, the catch parameter ex is final and therefore you cannot assign any values to it within the catch block.


Type Inference for Generic Instance Creation
For Collections, no need to repeat the generic typing(diamond <>).
For instance,
Map<String, List<String>> myMap = new HashMap<String, List<String>>();
In Java SE 7, you can substitute the parameterized type of the constructor with an empty set of type parameters (<>)
Map<String, List<String>> myMap = new HashMap<>();
Remember to specify the diamond otherwise the compiler generates an unchecked conversion warning because the HashMap() constructor refers to the HashMap raw type, not the Map<String, List<String>> type.
Map<String, List<String>> myMap = new HashMap(); // unchecked conversion warning


Java SE 7 supports limited type inference for generic instance creation; you can only use type inference if the parameterized type of the constructor is obvious from the context. For example, the following example does not compile:

List<Integer> list = new ArrayList<>();
list.add(12);
  // The following statement should fail since addAll expects
  // Collection<? extends Integer>
list.addAll(new ArrayList<>());

Note that the diamond often works in method calls; however, it is suggested that you use the diamond primarily for variable declarations

In comparison, the following example compiles:

// The following statements compile:
List<? extends Integer> list2 = new ArrayList<>();

list.addAll(list2);

Type Inference can be used for constructors of Generic and Non-Generic class

class MyClass<X> {
  <T> MyClass(T t) {
    ......
  }
}

In this class, constructor is generic so we can use like this in java 7 and prior versions new MyClass<Integer>("");
This create instance of parameterized type MyClass<Integer>, the constructor of this generic class contain a formal type argugment T.The compiler infers the type String for the formal type parameter, T, of the constructor of this generic class.


Prior to java7 versions,  we are able to infer the actual type parameters of generic constructors, similar to generic methods.
However, the compiler in Java SE 7 can infer the actual type parameters of the generic class being instantiated if you use the diamond (<>).

For instance,
MyClass<Integer> myObject = new MyClass<>("");

Here compiler infers the type Integer for the formal type parameter X, and it infer the type String for the formal parameter T, of the constructor of this class.


Improved Compiler Warnings and Errors When Using Non-Reifiable Formal Parameters with Varargs Methods

Java 7 has improved the compiler warning while  using non-reifiable type. For intance,
ArrayList<Number> and List<String>, are non-reifiable types.

A non-reifiable type is a type that is not completely available at runtime. At compile time, non-reifiable types undergo a process called type erasure during which the compiler removes information related to type parameters and type arguments. This ensures binary compatibility with Java libraries and applications that were created before generics. Because type erasure removes information from parameterized types at compile-time, these types are non-reifiable.

List l = new ArrayList<Number>();
List<String> ls = l; // unchecked warning
The variable ls has the parameterized type List<String>. When the List referenced by l is assigned to ls, the compiler generates an unchecked warning;the compiler is unable to determine at compile time.







Thanks for reading the post !
Please share or comment on this as this encourage me to write more :) 

1 comment: