Rules and Standards

CAA V5 Java Coding Rules

Rules, hints and tips to write Java code
Technical Article

Abstract

This article gives you several mandatory rules to program with Java in order to improve the readability of your code and moreover to enable Dassault Systèmes tools to process your code. Besides, this article provides some tips to make your code profit from the advantages of Java and avoid its drawbacks. These tips are often sum ups of world-wide-web items to which they point by hyperlinks.


Internal Mandatory Rules

These rules are:

[Top]

Create a File for each Java Top Level Class or Interface

Create a separate .java file for each top level class and interface, and put in this file only the declaration of this entity. This file must have the same name than the entity. For example, the BitmapPanel class is written in the BitmapPanel.java file.

However, you can define nested classes, that is to say classes whose declaration occurs within the body of another class or interface if the nested class completely depends on the top level class and is meaningless without it. It avoids namespace pollution by using the enclosing type as namespace.

[Top]

Use the Single-Type-Import Import Declaration Systematically

[Top]

Do Not Expose Data Members as Public

If you do so, you give a direct access to your data members to any users of your class instances. This breaks encapsulation. Even if using methods to access private data members doesn't avoid the client application to be rebuilt if you change this data, you keep a control on your data if you enable the client application to access them using these methods.

You can nevertheless do that if performance is an issue, and if there is no added value to add a pair of methods to access your data.

[Top]

Release Your Objects When You no Longer Use Them

An object is eligible for garbage collection when there are no more references to that object. References that are held in a variable are naturally dropped when the variable goes out of scope. Two cases can be distinguished:

For instance, assume that you have a graph of 4 instances i0, i1, i2, i3. i0. Each instance has one or several instance variables that hold a reference to another instance like in the diagram near by.

Refij is a variable of instance i which references instance j.

In order for i1, i2, i3 to be eligible for garbage collection, i0 must set ref01 to null as soon as i0 is useless.

[Top]

Often Use the Class Modifier Final

As soon as you don't want a class to be derived, declare it Final. It is the only way to prevent CAA clients from deriving an exposed class.

[Top]

Advised Tips

The tips are:

[Top]

Avoid Using an Object to Refer to Class (static) Variables and Methods

Avoid using an object to access a class (static) variable or method. Use a class name instead. For example:

classMethod();             //OK
AClass.classMethod();      //OK
anObject.classMethod();    //AVOID!

Class methods are statically bound, so they don't enjoy the flexibility of polymorphism: if you derive a class and create a static method with the same name and arguments as a static method of the superclass, you don't override the superclass's method, you only hide it. When this redefined method is invoked, the JVM will select the method implementation to execute not by the class of the object at runtime, but by the type of the variable at compile-time.

(Source: Designing with Static Members, http://www.artima.com/designtechniques/static.html)

[Top]

Avoid Using Finalizers

They are only useful for non-memory resources such as file handles and sockets. However:

(Source: Object Finalization and Cleanup, http://www.artima.com/designtechniques/cleanup.html)

[Top]

Avoid calling non-private methods from initializers and constructors

If an initializer or a constructor of a superclass invokes a non-private method which has been overridden in a subclass, the subclass's implementation of that method will run. If the subclass's method implementation uses instances variables explicitly declared in the subclass, those variables will still have their default initial values (their initializers and the subclass's constructor will not have been called yet).
If you invoke non-private methods from initializers and constructors, remember that later some other programmer could extend your class and override those methods.

Eg: Here is a Building class which has 5 floors of 3 flats and a BigBuilding class with 10 floors of 4 flats.

class Building
{
  protected int flatCount;
  private int floorCount = 5;
  Building()
  {
    flatCount = initFlatCount();
  }
  int initFlatCount()
  {
    return floorCount * 3;
  }
  // ...
}
class BigBuilding extends Building
{
  private int flatByFloorCount = 4;
  int initFlatCount()
  {
    return 10 * flatByFloorCount ;
  }
  // ...
}
After the constructor, flatCount = 15 After the constructor, flatCount = 0 !
because flatByFloorCount has not been initialized before the call to BigBuilding::initFlatCount by Building's constructor.

(Source: Object Initialization in Java, http://www.artima.com/designtechniques/initialization.html)

[Top]

Avoid Calling Methods from an Initializer

The compiler generates an error if an initializer refers to an instance variable declared textually after the variable being initialized. So you cannot make a direct forward reference from an initializer.

You'll never be allowed to write:

class Building
{
    private int flatCount = 3 * floorCount;
    private int floorCount = 5;
    // ...
}

But you may inadvertently circumvent the compiler's preventive restriction:

class Building
{
    private int flatCount = initFlatCount();
    private int floorCount = 5;
    private int initFlatCount()
    {
         return floorCount * 3;
    }
    // ...
}

This code compiles without an error but the Runtime result is not the expected one: flatCount equals 0.
Indeed, when initFlatCount is called, floorCount is not initialized yet, so it has its default value:0.

(Source: Object Initialization in Java, http://www.artima.com/designtechniques/initialization.html)

[Top]

Use Constants Whenever Possible

In Java, the constants must be coded as static final variables. Numerical constants (literals) should not be coded directly, except for -1, 0, and 1, which can appear in a for loop as counter values.

A static final variable:

(Source: Designing Fields and Methods, http://www.artima.com/designtechniques/coupling.html)

Moreover, static final variables enable you to define "enum" in Java.
For example the C++ statement::

enum Color {RED, GREEN, BLUE, WHITE} 

may be replaced in Java by:

public final class Color
{
    private Color() {}
    public static final Color RED = new Color();
    public static final Color GREEN = new Color();
    public static final Color BLUE = new Color();
    public static final Color WHITE = new Color();
}

(Source: Type safe constants in C++ and Java, http://www.javaworld.com/javaworld/javatips/jw-javatip27.html)

[Top]

Clone Objects before Returning Them to Prevent a Client from Modifying Them

If a method returns a reference to a private data member, the client can modify it and corrupt it.

Avoid Prefer
import java.awt.Dimension;

  public class Ground
  {
    private Dimension d = new Dimension (0, 0);

    public Dimension getDimension()
    {
      return d;
    }
  }
import java.awt.Dimension;

  public class Ground
  {
    private Dimension d = new Dimension (0, 0);

     public Dimension getDimension()
    {
        return new Dimension (d.x, d.y);
    }
 }

The following code affects only the first implementation

    Ground gr = new Ground();

    Dimension d = gr.getDimension();
    d.height = -5;
    d.width = -10;

So, if you don't want the caller method to be able to modify the original object, clone it before returning it. However, cloning may take a certain time. So you can disobey this rule if time is a critical point and if you know the possible callers (e.g., if the class is not public, the callers only belong to the same package).

In the same way, when you return an array, not only clone the array but also each object belonging to the array unless you intentionally give the client the access to the original objects.

Avoid Prefer
import java.awt.Dimension;

public class Grounds
{
  static final public int TOTAL_VALUES = 10;
  private Dimension[] d = new Dimension[TOTAL_VALUES];

  public Dimension[] getDimensions() 
      throws CloneNotSupportedException
  {
    return (Dimension[])d.clone();
  }
}
public Dimension[] getValues()
           throws CloneNotSupportedException
{
  Dimension[] copy = (Dimension[])d.clone();
  for (int i = 0; i < copy.length; ++i)
  {
    if (d[i] != null)
    {
      copy[i] = new Dimension (d[i].height, d[i].width);
    }
  }
  return copy;
}

The same problem occurs with multidimensional arrays of atomic types.

(Source: Complement testing with code inspections, http://www.javaworld.com/javaworld/javatips/jw-javatip88.html)

[Top]

Take Advantage of Immutable Objects

Java provides immutable classes, for example:

Immutable objects cannot change, so there is no need to clone them before returning them.

Avoid Prefer
public class Rope
{
  private Integer lg = new Integer(0);

  public Integer getLength()
  {
    return new Integer(lg.intValue());
  }
}
public class Rope
{
  private Integer lg = new Integer(0);

  public Integer getLength()
  {
    return lg;
  }
}

A particular type of immutable class is String which represents character strings. All string literals in Java programs, such as "abc" are implemented as instances of this class. Since String objects are immutable, they can be shared. So:

Avoid Prefer
    String str = new String("abc"); 
    String str = "abc"; 

(Source: Complement testing with code inspections, http://www.javaworld.com/javaworld/javatips/jw-javatip88.html)

[Top]

Choose the Right Exception Type to Throw

(Source: Designing with Exceptions, http://www.artima.com/designtechniques/desexcept.html)

[Top]

Use Threads Cautiously

(Source: Designing for Thread Safety, http://www.artima.com/designtechniques/threadsafety.html)

[Top]


History

Version: 1 [Sep 2000] Document created
[Top]

Copyright © 2000, Dassault Systèmes. All rights reserved.