30 Java Programming Tips and Best Practices

Java is one of the most popular programming languages – be it Win applications, Web Applications, Mobile, Network, consumer electronic goods, set top box devices, Java is everywhere.

More than 3 Billion devices run on Java. According to Oracle, 5 billion Java Cards are in use.

More than 9 Million developers choose to write their code in Java and it is very popular among developers as well as being the most popular development platform.

For upcoming breed of Java developers, this blog presents a collection of best practices which have been learnt over a period of time:

1. Prefer returning Empty Collect

If a program is returning a collection which does not have any value, make sure an Empty collection is returned rather than Null elements. This saves a lot of “if else” testing on Null Elements.

2. Use Strings carefully

If two Strings are concatenated using “+” operator in a “for” loop, then it creates a new String Object, every time. This causes wastage of memory and increases performance time. Also, while instantiating a String Object, constructors should be avoided and instantiation should happen directly. For example:

3. Avoid unnecessary Objects

One of the most expensive operations (in terms of Memory Utilization) in Java is Object Creation. Thus it is recommended that Objects should only be created or initialized if necessary. Following code gives an example:

4. Dilemma between Array and ArrayList

Developers often find it difficult to decide if they should go for Array type data structure of ArrayList type. They both have their strengths and weaknesses. The choice really depends on the requirements.

  1. Arrays have fixed size but ArrayLists have variable sizes. Since the size of Array is fixed, the memory gets allocated at the time of declaration of Array type variable. Hence, Arrays are very fast. On the other hand, if we are not aware of the size of the data, then ArrayList is More data will lead to ArrayOutOfBoundException and less data will cause wastage of storage space.
  2. It is much easier to Add or Remove elements from ArrayList than Array
  3. Array can be multi-dimensional but ArrayList can be only one dimension.

5. When Finally does not get executed with Try

Consider following code snippet:

From the program, it looks like “println” inside finally block will be executed 5 times. But if the program is executed, the user will find that finally block is called only 4 times. In the fifth iteration, exit function is called and finally never gets called the fifth time. The reason is- System.exit halts execution of all the running threads including the current one. Even finally block does not get executed after try when exit is executed.

When System.exit is called, JVM performs two cleanup tasks before shut down:

First, it executes all the shutdown hooks which have been registered with Runtime.addShutdownHook. This is very useful because it releases the resources external to JVM.

Second is related to Finalizers. Either System.runFinalizersOnExit or Runtime.runFinalizersOnExit. The use of finalizers has been deprecated from a long time. Finalizers can run on live objects while they are being manipulated by other threads.This results in undesirable results or even in a deadlock.

6. Check Oddity

Have a look at the lines of code below and determine if they can be used to precisely identify if a given number is Odd?

These lines seem correct but they will return incorrect results one of every four times (Statistically speaking). Consider a negative Odd number, the remainder of division with 2 will not be 1. So, the returned result will be false which is incorrect!

This can be fixed as follows:

Using this code, not only is the problem of negative odd numbers solved, but this code is also highly optimized. Since, Arithmetic and Logical operations are much faster compared to division and multiplication, the results are achieved faster so in second snippet.

7. Difference between single quotes and double quotes

From the code, it would seem return “HaHa” is returned, but it actually returns Ha169. The reason is that if double quotes are used, the characters are treated as a string but in case of single quotes, the char -valued operands ( ‘H’ and ‘a’ ) to int values through a process known as widening primitive conversion. After integer conversion, the numbers are added and return 169.

8. Avoiding Memory leaks by simple tricks

Memory leaks often cause performance degradation of software. Since, Java manages memory automatically, the developers do not have much control. But there are still some standard practices which can be used to protect from memory leakages.

  • Always release database connections when querying is complete.
  • Try to use Finally block as often possible.
  • Release instances stored in Static Tables.

9. Avoiding Deadlocks in Java

Deadlocks can occur for many different reasons. There is no single recipe to avoid deadlocks. Normally deadlocks occur when one synchronized object is waiting for lock on resources locked by another synchronized object.

Try running the below program. This program demonstrates a Deadlock. This deadlock arises because both the threads are waiting for the resources which are grabbed by other thread. They both keep waiting and no one releases.


But if the order in which the threads are called is changed, the deadlock problem is resolved.


10. Reserve memory for Java

Some of the Java applications can be highly CPU intensive as well as they need a lot of RAM. Such applications generally run slow because of a high RAM requirement. In order to improve performance of such applications, RAM is reserved for Java. So, for example, if we have a Tomcat webserver and it has 10 GB of RAM. If we like, we can allocate RAM for Java on this machine using the following command:

  • Xms = Minimum memory allocation pool
  • Xmx = Maximum memory allocation pool
  • XX:PermSize = Initial size that will be allocated during startup of the JVM
  • XX:MaxPermSize = Maximum size that can be allocated during startup of the JVM

11. How to time operations in Java

There are two standard ways to time operations in Java: System.currentTimeMillis() and System.nanoTime() The question is, which of these to choose and under what circumstances. In principle, they both perform the same action but are different in the following ways:

  1. System.currentTimeMillis takes somewhere between 1/1000th of a second to 15/1000th of a second (depending on the system) but System.nanoTime() takes around 1/1000,000th of a second (1,000 nanos)
  2. System.currentTimeMillis takes a few clock cycles to perform Read Operation. On the other hand, System.nanoTime() takes 100+ clock cycles.
  3. System.currentTimeMillis reflects Absolute Time (Number of millis since 1 Jan 1970 00:00 (Epoch Time)) but System.nanoTime() does not necessarily represent any reference point.

12. Choice between Float and Double

Data type Bytes used Significant figures (decimal)
Float 4 7
Double 8 15


Double is often preferred over float in software where precision is important because of the following reasons:

Most processors take nearly the same amount of processing time to perform operations on Float and Double. Double offers far more precision in the same amount of computation time.

13. Computation of power

To compute power (^), java performs Exclusive OR (XOR). In order to compute power, Java offers two options:


pow(double base, double exponent):‘pow’ method is used to calculate where multiplication is not possible (base^exponent)

Math.pow should be used ONLY when necessary. For example, exponent is a fractional value. That is because Math.pow() method is typically around 300-600 times slower than a multiplication.

14. How to handle Null Pointer Exceptions

Null Pointer Exceptions are quite common in Java. This exception occurs when we try to call a method on a Null Object Reference. For example,

If in the above example, if get a NullPointerException, then either school is null or listStudents() is Null. It’s a good idea to check Nulls early so that they can be eliminated.

15. Encode in JSON

JSON (JavaScript Object Notation) is syntax for storing and exchanging data. JSON is an easier-to-use alternative to XML. Json is becoming very popular over internet these days because of its properties and light weight. A normal data structure can be encoded into JSON and shared across web pages easily. Before beginning to write code, a JSON parser has to be installed. In below examples, we have used json.simple (https://code.google.com/p/json-simple/).

Below is a basic example of Encoding into JSON:


16. Decode from JSON

In order to decode JSON, the developer must be aware of the schema. The details can be found in below example:


The id is: 1
The type is: donut
The name is: Cake
The PPU is: 0.55
ID 1001 type Regular
ID 1002 type Chocolate
ID 1003 type Blueberry
ID 1004 type Devil's Food
ID 5001 type None
ID 5002 type Glazed
ID 5005 type Sugar
ID 5007 type Powdered Sugar
ID 5006 type Chocolate with Sprinkles
ID 5003 type Chocolate
ID 5004 type Maple

17. Simple String Search

Java offers a Library method called indexOf(). This method is used with String Object and it returns the position of index of desired string. If the string is not found then -1 is returned.

18. Listing content of a directory

In order to list the contents of a directory, below program can be used. This program simply receives the names of the all sub-directory and files in a folder in an Array and then that array is sequentially traversed to list all the contents.

19. A Simple IO

In order to read from a file and write to a file, Java offers FileInputStream and FileOutputStream Classes. FileInputStream’s constructor accepts filepath of Input File as argument and creates File Input Stream. Similarly, FileOutputStream’s constructor accepts filepath of Output File as argument and creates File Output Stream.After the file handling is done, it’s important to “close” the streams.

20. Executing a shell command from Java

Java offers Runtime class to execute Shell Commands. Since these are external commands, exception handling is really important. In below example, we illustrate this with a simple example. We are trying to open a PDF file from Shell command.

21. Using Regex

Summary of Regular Expression Constructs (Source: Oracle Website)

x The character x
\\ The backslash character
\0n The character with octal value 0n (0 <= n <= 7)
\0nn The character with octal value 0nn (0 <= n <= 7)
\0mnn The character with octal value 0mnn (0 <= m <= 3, 0 <= n <= 7)
\xhh The character with hexadecimal value 0xhh
\uhhhh The character with hexadecimal value 0xhhhh
\x{h…h} The character with hexadecimal value 0xh…h (Character.MIN_CODE_POINT <= 0xh…h <= Character.MAX_CODE_POINT)
\t The tab character (‘\u0009’)
\n The newline (line feed) character (‘\u000A’)
\r The carriage-return character (‘\u000D’)
\f The form-feed character (‘\u000C’)
\a The alert (bell) character (‘\u0007’)
\e The escape character (‘\u001B’)
\cx The control character corresponding to x


Character classes
[abc] a, b, or c (simple class)
[^abc] Any character except a, b, or c (negation)
[a-zA-Z] a through z or A through Z, inclusive (range)
[a-d[m-p]] a through d, or m through p: [a-dm-p] (union)
[a-z&&[def]] d, e, or f (intersection)
[a-z&&[^bc]] a through z, except for b and c: [ad-z] (subtraction)
[a-z&&[^m-p]] a through z, and not m through p: [a-lq-z](subtraction)


Predefined character classes
. Any character (may or may not match line terminators)
\d A digit: [0-9]
\D A non-digit: [^0-9]
\s A whitespace character: [ \t\n\x0B\f\r]
\S A non-whitespace character: [^\s]
\w A word character: [a-zA-Z_0-9]
\W A non-word character: [^\w]


Boundary matchers
^ The beginning of a line
$ The end of a line
\b A word boundary
\B A non-word boundary
\A The beginning of the input
\G The end of the previous match
\Z The end of the input but for the final terminator, if any
\z The end of the input


22. Simple Java Swing Example

With the help of Java Swing GUI can be created. Java offers Javax which contains “swing”. The GUI using swing begin with extending JFrame. Boxes are added so they can contain GUI components like Button, Radio Button, Text box, etc. These boxes are set on top of Container.

23. Play a sound with Java

Playing sound is a common requirement in Java, especially along with Games.

This demo explains how to play an Audio file along with Java code.

24. PDF Export

Export a table to PDF is a common requirement in Java programs. Using itextpdf, it becomes really easy to export PDF.

25. Sending Email from Java Code

Sending email from Java is simple. We need to install Java Mail Jar and set its path in our program’s classpath. The basic properties are set in the code and we are good to send email as mentioned in the code below:

26. Measuring time

Many applications require a very precise time measurement. For this purpose, Java provides static methods in System class:

currentTimeMillis(): Returns current time in MilliSeconds since Epoch Time, in Long.

nanoTime(): Returns the current value of the most precise available system timer, in nanoseconds, in long. nanoTime() is meant for measuring relative time interval instead of providing absolute timing.

27. Rescale Image

An image can rescaled usingAffineTransform. First of all, Image Buffer of input image is created and then scaled image is rendered.

28. Capturing Mouse Hover Coordinates

By implementing MouseMotionListner Interface, mouse events can be captured. When the mouse is entered in a specific region MouseMoved Event is triggered and motion coordinates can be captured. The following example explains it:

29. FileOutputStream Vs. FileWriter

File writing in Java is done mainly in two ways: FileOutputStream and FileWriter. Sometimes, developers struggle to choose one among them. This example helps them in choosing which one should be used under given requirements. First, let’s take a look at the implementation part:

Using FileOutputStream:

Using FileWriter:

According to Java API specifications:

FileOutputStream is meant for writing streams of raw bytes such as image data. For writing streams of characters, consider using FileWriter.

This makes it pretty clear that for image type of Data FileOutputStream should be used and for Text type of data FileWriter should be used.

Additional Suggestions

  1. Use Collections

    Java is shipped with a few collection classes – for example, Vector, Stack, Hashtable, Array. The developers are encouraged to use collections as extensively as possible for the following reasons:

    • Use of collections makes the code reusable and interoperable.
    • Collections make the code more structured, easier to understand and maintainable.
    • Out of the box collection classes are well tested so the quality of code is good.
  2. 10-50-500 Rule

    In big software packages, maintaining code becomes very challenging. Developers who join fresh ongoing support projects, often complain about: Monolithic Code, Spaghetti Code. There is a very simple rule to avoid that or keep the code clean and maintainable: 10-50-500.

    • 10: No package can have more than 10 classes.
    • 50: No method can have more than 50 lines of code.
    • 500: No class can have more than 500 lines of code.
  3. SOLID Class Design Principles

    SOLID (http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29) is an acronym for design principles coined by Robert Martin. According to this rule:

    Rule Description
    Single responsibility principle A class should have one and only one task/responsibility. If class is performing more than one task, it leads to confusion.
    Open/closed principle The developers should focus more on extending the software entities rather than modifying them.
    Liskov substitution principle It should be possible to substitute the derived class with base class.
    Interface segregation principle It’s like Single Responsibility Principle but applicable to interfaces. Each interface should be responsible for a specific task. The developers should need to implement methods which he/she doesn’t need.
    Dependency inversion principle Depend upon Abstractions- but not on concretions. This means that each module should be separated from other using an abstract layer which binds them together.
  4. Usage of Design Patterns

    Design patterns help developers to incorporate best Software Design Principles in their software. They also provide common platform for developers across the globe. They provide standard terminology which makes developers to collaborate and easier to communicate to each other.

  5. Document ideas

    Never just start writing code. Strategize, Prepare, Document, Review and Implementation. First of all, jot down your requirements. Prepare a design document. Mention assumptions properly. Get the documents peer reviewed and take a sign off on them.

  6. Use Equals over ==

    == compares object references, it checks to see if the two operands point to the same object (not equivalent objects, the same object).On the other hand, “equals” perform actual comparison of two strings.

  7. Avoid Floating Point Numbers

    Floating point numbers should be used only if they are absolutely necessary. For example, representing Rupees and Paise using Floating Point numbers can be Problematic – BigDecimal should instead be preferred. Floating point numbers are more useful in measurements.

Many thanks to Shubhra Gupta for this post

Leave a Comment: