Java Programming Tips

Tip #1 – Avoid NullPointerException situations
When comparing strings against specific values in Java, you can easily avoid the java.lang.NullPointerException problem by specifying the string constant as the first value, and the variable as the parameter.

Consider next typical situation:

if (firstName != null && firstName.equalsIgnoreCase("John")) {
    // Do something when first name is "John"...
}

When you swap the constant “John” with the variable firstName, you won’t need to worry about checking that firstName will be null. The constant “John” will never be null:

if ("John".equalsIgnoreCase(firstName)) {
    // Do something when first name is "John"...
}

Tip #2 – Avoid redundant method calls
Calling methods in Java, or any other language, is a relatively expensive task in terms of CPU cycles. Each method call involves stack space allocation and de-allocation and in some cases it may affect performance, especially in long iterations.

For instance next example will call the method size() on the Vector instance v for each iteration:

Vector v = ...
for (int i = 0; i < v.size(); i++) {
    // do stuff for each element in the Vector
}

This is how you can avoid it:

Vector v = ...
int size = v.size();
for (int i = 0; i < size; i++) {
    // do stuff for each element in the Vector
}

Tip #3 – Avoid repetitive operations or function calls
Reduce the number of repetitive tasks whenever possible.

String firstName = "George";
if ("John".equalsIgnoreCase(firstName)) {
    // do stuff for John
} else if ("Jimmie".equalsIgnoreCase(firstName)) {
    // do stuff for Jimmie
} else if ("George".equalsIgnoreCase(firstName)) {
    // do stuff for George
}

In this example, the method equalsIgnoreCase will be called 3 times until a match is found. This can be reduced to just 1 case conversion like this:

String firstName = "George";
String firstNameLc = firstName.toLowerCase();
if ("john".equals(firstNameLc)) {
    // do stuff for John
} else if ("jimmie".equals(firstNameLc)) {
     // do stuff for Jimmie
} else if ("george".equals(firstNameLc)) {
    // do stuff for George
}

Here is another example:

if (Double.valueOf(m_daily_kw[i]).doubleValue() > m_summary_daily_kw) {
  m_summary_daily_kw = Double.valueOf(m_daily_kw[i]).doubleValue();
}

Change to:

double val = Double.valueOf(m_daily_kw[i]).doubleValue();
if (val > m_summary_daily_kw) {
  m_summary_daily_kw = val;
}

Tip #4 – Avoid nesting of Exceptions or Throwables
Avoid embedding Exceptions when they only need to be propagated.

This example catches the Exception e, writes it to a log, then creates a new Exception instance with the original wrapped inside.

try {
    // stuff goes wrong and throws Exception
} catch (Exception e) {
    logger.fatal("Something failed...", e);
    throw new Exception(e);
}

This is the right way:

try {
    // stuff goes wrong and throws Exception
} catch (Exception e) {
    logger.fatal("Something failed...", e);
    throw e;
}

Tip #5 – Avoid catch block if Exception is not handled
Do not use try-catch blocks if you are not going to do anything with the Exception or Throwable.

function void doStuff() throws Exception {
    try {
        // stuff goes wrong and throws Exception
    } catch (Exception e) {
        throw e;
    }
}

When you’re not specifically handling the Exception, there’s no need to catch it and then re-throw it. Re-write to this:

function void doStuff() throws Exception {
    // stuff goes wrong and throws Exception
}

Tip #6 – Free up memory
Clean up unused variables as soon as possible by assigning null pointer. Whenever dealing with large amounts of data or long iterations, it may make sense to clean up unused variables in the process, in order to keep JVM memory usage low and to avoid OutOfMemoryException.

For instance Vector or ArrayList with thousands of elements, may not need certain elements anymore after the iteration. In that case, mark it for removal by garbage collector like this:

Vector<Object> v = ...
int size = v.size();
for (int i = 0; i < size; i++) {
    Object obj = v.elementAt(i);
    v.setElementAt(null, i); // clear element
    . . .
}

Tip #7 – Keep your code simple
Some things can be rewritten to accomplish the same result by using less and nicer looking code.

Example 1:

public boolean hasMoreItems() {
    boolean hasMore;
    m_item++;
    if (m_item < m_maxItems) {
        hasMore = true;
    } else {
        hasMore = false;
    }
    return hasMore;
}

Change to:

public boolean hasMoreItems() {
    m_item++;
    return m_item < m_maxItems;
}

Example 2:

if (record==null) {
    fields = null;
} else {
    fields = getFields(record);
}

Change to:

fields = record == null ? null : getFields(record);

Tip #8 – use StringBuffer for multiple String concatenations
If you need to do multiple String concatenations, it is best to use the StringBuffer instead of a String.

Example:

String SQL = " select id, value"
    + " from some_table"
    + " where id = " + id
    + "   and parent_id = " + parentId;

This will cause the 4 following instantions of a String class:
1) ” select id, value from some_table where id = ”
2) ” select id, value from some_table where id = ” + id
3) ” select id, value from some_table where id = ” + id + ” and parent_id = ”
4) ” select id, value from some_table where id = ” + id + ” and parent_id = ” + parentId

Change to:

StringBuffer sb = new StringBuffer();
sb.append(" select id, value"
    + " from some_table"
    + " where id = ")
   .append(id)
   .append("   and parent_id = ")
   .append(parentId);

The following example results in only 1 String instantiation and doesn’t need to be rewritten:

String SQL = " select 1"
    + " from dual";

Tip #9 – Avoid TAB characters in source code
Only use spaces to line up your source lines, for instance 4 spaces per indent. Tab widths show up differently in different source code editors, and your source code layout might look messy, in that things don’t line up anymore. Especially when you have a mix of tab characters and spaces, things tend to look like crap.

Tip #10 – Make classes final
For optimization reasons, classes should be defined as final whenever possible. Classes that are final cannot be extended anymore with new implementations. That way, the Java compiler may take the opportunity to inline all final methods, but this depends upon the compilers implementation. Performance may increase up to 50%.

Leave a Reply

Your email address will not be published. Required fields are marked *

*