J3 Limited
 
Google
WWW J3Ltd
 
New Features In Java 5

Introduction

Sun Microsystem's release of Java 1.5 included many new features to the programming language, and its libraries. This document highlights the new features which are of most importance.

The target audience is experienced Java programmers who wish to quickly review the features introduced in Java 5.

All the example Java source files can be downloaded in a zip archive here.

Version Number

The version can be confusiong at first. Once installed, typing "java -verion" at the command prompt results in the utility reporting a version of 1.5..... And yet it is also referred to as version 5, or J2SE 5, and less often as Tiger.

Autoboxing and Unboxing

The Java interpreter can automatically encapsulate a Java primitive type into its equivalent type wrapper class, and vice versa.

Primitive Type Java Wrapper
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Char
boolean Boolean

Example class (the full source is available here):

package com.j3ltd.java15changes;


public class Autoboxing {
public static void main(String[] args) { Integer intObject = 100; Integer intObject2 = 200; intObject ++; switch (intObject) { case 101: intObject2 = intObject + intObject2; break; } System.out.println("intObject is " + intObject + " intObject2 is " + intObject2); } }

When the above class is run the console output is:

intObject is 101 intObject2 is 301

Enumeration Types

  • An enum is a special type of class.
  • It is a type for which all its possible values are known.
  • An enum cannot extend or be extended.
  • Constructors and methods can be defined in an enum
  • An enum can be used in a switch statement
  • Two special static methods are automatically generated:
    • public static E[] values() returns an array of the constants in the declaration order.
    • public static E valueOf(String name) returns the enum constant with the name given as the parameter.
  • An enum implicitly extends java.lang.Enum
  • A variable of an enum type does not need the new keyword

Example enum (the full source is available here):

enum Vehicle {
unicycle(1), bicycle(2),
motorbike(2), car(4), van(4),
truck(6), lorry(8);

int numberOfWheels;

Vehicle(int wheels) {
numberOfWheels = wheels;
}

public int getWheelNumberOfWheels() {
return numberOfWheels;
}
}

The enum can be used as follows:

		Vehicle aVehicle;

aVehicle = Vehicle.van;
if (aVehicle == Vehicle.van) {
System.out.println("Do you drive a your van in the UK?\n");
}

Generics

Generics allows a classes, interfaces and methods to have the type of data they use as a parameter. The Java collections framwork has been revamped to make use of this. Previously, for example, an ArrayList stored its members as the Object type. with Generics an ArrayList of "Integer" is possible.

A simple generic class declaration looks like this (the fuill source of the generics examples is available here):

class GenericEg1<G> {

  G genericMember;

  GenericEg1(G param) {
    genericMember = param;
  }

  G getMe() {
    return genericMember;
  }
}

To use the above class, a variable can be decalred and used as follows, note the autoboxing is also used here.

GenericEg1<Integer> value;
value = new GenericEg1<Integer>(100);

int itIs = value.getMe();

A generic type can have more than one type parameter:

class GenericExample<A, B, C>

Bounded types allow the type parameter(s) to be limited to a superclass:

class GenericEg2<A extends Number>

Wildcard type arguments can be used to state that a parameter to a method can be of any type. It is also possible to use bounding on wildcard arguments. For example (in the GenericEg2 example class):


	  public double sum(List<? extends Number> list) {
double toReturn = 0.0;
for (Number number : list) {
toReturn += number.doubleValue();
}
return toReturn;
}

In the above example, The method sum can take any list which contains Number or subtypes of Number, such as Integer. Without the '?' argument, the List must be Number.

Note: it is also possible to use the super keyword instead of extends. In such a case, the list could only be of Number or its supertypes (only Object in this case), not subtypes such as Integer.

Enhanced For Statement

The syntax of the enhanced for statement is as follows:

for (Type loop-variable : set-expression) statement

  • The set-expression must either be an array or implement the java.lang.Iterable.
  • The loop-variable is a local variable of a valid type for the set's contents.

Example (the full source is the same as the generics example, available here):

 public double sum(List<? extends Number> list) {
     double toReturn = 0.0;
     for (Number number : list) {
       toReturn += number.doubleValue();
     }
     return toReturn;
 }

Annotations

Annotations allow some information to be attached to a package, class, interface, enum, field, method... One annotation Java programmers should be familiar with is the "@Deprecated" annotation, which signifies that the declaration should not be used anymore: it has been replaced by a newer version. Another very active area for annotations is the EJB (Enterprise Java Beans) specification. In this case annotations are used to simplify the EJB developper's task by allowing EJB classes and methods to be identified as being of particular interest to the EJB container.

As an applications programmer, annotations are used but very rarely defined. Programming tool suppliers, and to some extent those in charge of the Java specification, are more likely to specify the annotations the rest of us will use.

A brief overview of defining, and using, annotations is given here, so that the reader gains a "working knowledge" of annotations.

Example (the full source is available here) :

The following annotation is defined:

enum ReleaseType {alpha, beta, production };
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@interface ClassVersion {
   String author() default "unknown";
   int majorVersion() default 1;
   int minorVersion() default 0;
   ReleaseType release() default ReleaseType.alpha;
}

Notes:

  • An enum defines the different release types for Java code: alpha, beta, production.
  • An annotation called ClassVersion is defined with the following characteristics:
    • The Retention is RUNTIME. So it can be queried at runtime, other values are SOURCE or CLASS
    • The target is TYPE and ANNOTATION_TYPE, hence this annotation can only be applied to other types (class, interface, enum) or other annotations.
    The annotation has various members that are used to attach version information.

At runtime, the class version annotation can be queried as follows:

@ClassVersion(author = "Fred", release = ReleaseType.production)
public class AnnotationExample { public static void main(String[] args) { AnnotationExample eg = new AnnotationExample(); ClassVersion version = eg.getClass().getAnnotation(ClassVersion.class); System.out.println("AnnotationExample by " + version.author() + " Version " + version.majorVersion() + '.' + version.minorVersion() + ' ' + version.release() + " release"); } }

When run, the following is output:

AnnotationExample by Fred Version 1.0 production release

Annotations do not always take parameters, sometimes they don't take any (for example the @Deprecated annotation).

Miscellaneous

Java 5 also has a few minor additions, which are worth mentioning. C and C++ programmers should not have any difficulty in recogninzing some of these new features. However, it is worth pointing out that there are slight differences, so if all else fails, it is worth reading up the finer details.

Varargs: Methods can be defined to take variable length arguments that is to say zero or more, depending on how the method is defined.

Formatted I/O: C/C++ programmers are accustomed to the printf() method. Java 5 has added the Formatter class in the java.util package. Also the java.io.PrintStream and java.io.PrintWriter classes have the printf() varargs method.

Static import: it is possible to import the static members (variable and methods) from another class. This may reduce readability though. For example, instead of coding "System.out.println()", "out.println()" could be written instead, if java.lang.System.* is imported as a static import.

The example below shows the new features just mentioned (the full source is available here):

import static java.lang.System.*;
public class Miscellaneous {
 static void print(Object...objects) {
   for (Object o : objects) {
     out.print(o);
   }
 }
   
 public static void main(String[] args) {
   // System.out.* imported as a static import
   out.printf("Demonstration of the new printf method %d\n", 10);
   print("demonstration of a varargs ", "method ", 
         "call ", 10, " \n");
 }
}

When the above is run, the output produced is as shown below:

Demonstration of the new printf method 10
demonstration of a varargs method call 10

 

Serializable: Implementation of the java.io.Serializable interface are strongly recommended to define a " private static final long serialVersionUID". If one is not defined, java tries to generate one for the Serializable class. This is used by Java to decide whether two different class files are equivalent (using the class name and serialVersionUID. Hence the version number should be renewed when the class is changed in a way that would make it incompatible with previous versions.

The method used to generate the serialVersionUID can be manual, or using one of the tools provided in the JDK, called serialver, the file is located in the jdk's bin folder.

.
  Copyright © 2006 J3 Ltd Permission is granted to reproduce material on this page, on the condition that a reference to "WWW.J3Ltd.com" is given as the source of the material.