5.0 Ease of Development Features

Generic Types

The most common and useful place where Generic Types are used is the Collections API in Java. Prior to J2SE 5.0, if one created an instance of a LinkedList or an ArrayList of any other Collection type, the Objects that could be put into these collections, could be of Object type, which literally meant any different types of Objects could be put into a Collection. For example:

List alist = new ArrayList();
String string = new String("BT");
Integer integer = new Integer(10);
alist.add(string);
alist.add(integer);
String getStr = (alist.get(0)).toString();
Integer getInt = (Integer)alist.get(1);

The above code would run fine, but as is obvious both a String type and an Integer type could be stored in the ArrayList being used and when we needed to fetch them from the ArrayList, we must to a Type Casting.

A better more efficient way would be to customize this ArrayList and make it to either contain ONLY String types or ONLY Integer types. And let the Java Compiler make sure that the specification was not violated in the program by arranging for a compile-time type checking. This was made possible with Generic types as below:

List<String> alist = new ArrayList<String>();
alist.add("BT");
String aString = alist.get(0);
//try adding an Integer to the list
alist.add(new Integer(10)); //compiler complains with an error

 

To Summarize: Generic types enable an API designer to provide a common functionality that can be used with multiple data types and the type safety  check is done by the compiler at compile time.

More on Generics.

Autoboxing/Auto-Unboxing

The autoboxing and auto-unboxing for primitives helps produce more concise code that is easier to follow. The 5.0 version leaves the conversion of primitives to their Object counterparts (and vice versa) to the compiler. We no longer need to wrap an int into Integer (wrapper class for int primitive) or get intValue() from an Integer as below:

List<Integer> alist = new ArrayList<Integer>(0);
alist.add(new Integer(10));
int i = alist.get(1).intValue();//no need

Instead we can (in 5.0 and higher Java) do just:

 int i = alist.get(1);

And the conversion from Integer to int primitive will be taken care of, by the compiler itself.

Static Import

In order to refer to static constants from a class without needing to inherit from it, Static Import feature can be used as below:

import static java.lang.Math.PI;
double r = cos(PI * theta);

Instead of doing as below:

double r = Math.cos(Math.PI * theta);

 Varargs

Since 5.0 we can make the LAST argument of a method, a variable length array as below:

public static void main(String... args){
                 System.out.println(args.length);
}

Formatted Input/Output

java.util.Formatter provide the functionality for formatted output, so we now have the option of using printf-type feature to generate formatted output as below:

System.out.printf("name count%n");
System.out.printf("%s %5d%n", user,total);

java.util.Scanner API provides the simple ways to get input from System Console or any other data input stream as below:

Scanner scanned = new Scanner(System.in);
String strring = scanned.next(); 
int integer = scanned.nextInt(); 
scanned.close();

Concurrency Utilities

java.util.concurrent package contains numerous high-level thread constructs, including executors, which are a thread task framework, thread safe queues, Timers, locks (including atomic ones), and other synchronization primitives.

For example, Semaphores are flexible locks that allow a number of concurrent threads access, we can also test a lock before acquiring it.  The Semaphore class keeps a counter on to track the number of permits it can issue and allows multiple threads to acquire one or more permits; how the permits are used is up to us to decide. Therefore, a semaphore can be used to represent the number of locks that can be granted on a resource. More on this and other constructs in java.util.concurrent.