Advertisment

Catching Java Bugs with Tiger

author-image
PCQ Bureau
New Update

Java programming language has matured tremendously over the
years. It has been able to safeguard against common programming pitfalls such as
array bounds checking, exception handling, memory leaks, dangling references
etc. But, there are still some lacunas in the language, such as typecasting and

excessive use of deployment descriptors (DD), which are processed independently
from the source code. In this article, we'll look at two popular features
namely Generics and Annotations introduced in Java SE 5 (aka Tiger) to catch
bugs early and drive agile development. Catching bugs early helps in preventing
their propagation in the later stages of the development cycle.

Advertisment
Direct
Hit!
Applies to:
Java SE/EE developers
USP:
Ensure compile-time type safety with Tiger
Links:
http://java.sun.com/j2se/1.5.0 
Google keywords:
Generics, annotations

A date with common programming bugs Java collection offers
excellent data structure support, and  is used to hold heterogeneous
objects, where the elements may have any reference type. Some common programming
bugs lead to ugly ClassCastException. For instance, when you add an integer to a
vector, while extracting the collection, an object is

returned that must be explicitly cast to an integer in order to

ensure type safety.

Vector v = new Vector();

v.add(new Integer(1));

Integer num = (Integer) v.get(0);

Advertisment

This kind of programming style makes it difficult to read
and maintain the code. Down casting is often the cause of errors as shown below.

class Facade{

//application logic

}

class MVC_View{

//client view

}

. . . .

Advertisment

Vector v = new Vector();

// Add an object of type Facade

v.add(new Facade());

// extract the object back

MVC_View b = (MVC_View) v.get(0);

Although the above code snippet compiles fine but at
runtime, it throws ClassCastException.

Advertisment

Generics to the rescue

Generics provide compile-time type safety and eliminate the need for casts.
With Generics, errors are flagged where they occur, and not later at run time.
Parametric types (eg vector, hashtable) provide an elegant way to implement
generic-utility classes that alleviates the need to cast and allow errors to be
caught at compile time. As shown in the following code snippet, with Generics,
you no longer have to keep track of what types of objects your collection
contains.

Vector v = new
Vector();



v.add(1);

int num = v.get(0);

The code snippet above uses another feature called
autoboxing introduced in Tiger. If you were to assign an extracted

element to a different type, the error would be caught at compile-time instead
of run-time.

Advertisment

This early static checking increases the type safety.
Here's another example that demonstrates how Generics can catch some potential
bugs at the compile time. This code segment will result in compilation error.

Vector v = new
Vector();

// Add an object of type Facade

v.add(new Facade());

// extract the object back

MVC_View b = (MVC_View) v.get(0);

Metadata meets Java

Metadata is data about data. It is useful in compile-time checking and code
analysis and does not directly affect the

semantics of a program. Development and deployment tools can inspect these
annotations and process them in some fashion and may produce additional source
files, such as XML documents, or other artifacts. Java SE5 lets the developer
use metadata in source code to include special directives. Lets now see how we
can put it to use.

Advertisment

Decorate your code with annotations

The metadata feature introduced in Java SE 5 is Annotations. With
Annotations, developers can dress their code to provide

documentation, code generation, and deliver container services to POJOs. Here
we'll explore some built-in annotations in Tiger. The first built-in
annotation type is Override. It indicates that the annotated method is
overriding a method in a superclass, and, it can only be applied to methods as
shown below.

public class TestOverride {

  @Override

  public String toString() {

    return super.toString() + " Testing Override
annotation";

  }

  @Override

  public int hashCode() {

    return toString().hashCode();



  }

}

If a method marked with Override annotation does not
override its super-class's method, the compiler will generate an error.

Advertisment

Next, we'll look at another marker annotation called
Deprecated. Like other deprecated methods, a method marked with this annotation
should not be used and the compiler flags a warning if such method is called.

//
TestDeprecatedAnnotation.java

public class
TestDeprecatedAnnotation {

   public static
void main(String arg<>)  {


new TestDeprecatedAnnotation();

   }

   public
TestDeprecatedAnnotation() {

   TestDeprecated
t=new TestDeprecated();


t.doDirectPurchase();

}

Delivering container services to POJOs

The real power of annotations can only be realized if one looks into the EJB 3.0
specification. With EJB 3.0, business components are developed as POJOs (Plain
Old Java Objects), and developers can use metadata annotations to specify to the
container how these beans are to be managed. With the new EJB 3.0 specification,
there's no need of boilerplate code, and DD (Deployment

Descriptors) are optional. Thanks to annotations, EJB 3.0
decreases the number of  programming artifacts that the developers need to
provide,

and eliminates/minimizes callback methods required to be implemented.
Annotations can be used to define the bean's business interface, O/R mapping
information, and inject dependencies at runtime. The following code snippet
shows how annotations help in simplifying the EJB development

experience.

@Remote

@Stateless public class HellodBean {

public String sayHello(String s){

System.out.println("Hello: "+s; }

}

It can't get simpler than this. You no longer need to
implement the javax.ejb.SessionBean interface or define separate remote (or
local) and home interface.

Even if you explicitly define one, it can be a POJI (Plain
Old Java Interface) called business interface, and, need not extend to EJBObject
or EJBLocalObject. If you do not implement an interface, a bean interface will
be generated for you. The type of generated interface, either local or remote,
is dependent on the annotation you used in the bean class. All the public
methods of the bean class will be included as part of the automatically
generated business interface.

Further, now there is no ejb-jar.xml DD required. XML files
can express complex relationships, but they are also quite verbose and less
robust. Annotations, on the other hand, are simple and concise. XML based DD
files are optional in EJB 3.0 and can be used to override annotation behavior.

Conclusion

Tiger is believed to be the biggest leap forward in Java

programming with significant extensions to the language syntax. Advanced
features such as auto-boxing and un-boxing of primitives, static imports,
variable method arguments, and enumerations are now supported.

Reflection in Java SE 5 has also been extended to support

reflecting on generic types.

In addition to using generic types, you can implement your
own types. Annotations are driving the next wave in agile

development. You can define your own custom application

specific annotations. Annotations alleviate boilerplate code and XML documents,
resulting in much cleaner and readable code. 

Kunal Jaggi

Advertisment

Stay connected with us through our social media channels for the latest updates and news!

Follow us: