Java Coding Standards and Best Practices

We are writing code not only for the computers but also for the other programmers who will later work on these codes. Assume we have written the unreadable code and after a few days or months, we want to modify some part of the code. In that case, we forget what we had done at the code development time and now we need to spend some time to understand what is going on in this part of the code.

Projects are developed by multiple programmers but not by a single programmer. The code may be developed by one programmer and maintained by another programmer. Hence we should write our code in such a way that anyone can understand it easily. For this, we have to follow some best practices and coding standards for Java.

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

Martin Fowler

1. Java Naming Conventions

Naming conventions of identifiers make programs more understandable. These naming suggestions are suggested by Sun Microsystems (now Oracle) and Java communities. In all Java APIs including JDK follows these naming conventions for classes, interfaces, packages, methods, variables, and constants.

According to Robert C. Martin (the author of Clean Code), an identifier should have the following characters:- Self-explanatory, meaningful distinctions, and pronounceable.

a) Packages

  • The package name should contain only lowercase ASCII letters.
  • The topmost package name should be the top-level domain names like com, edu, org, gov, net, or e.t.c.
  • The subsequent components of the package name may vary based on the organization’s own internal naming conventions.
  • Examples of the package name:- com.sun.eng, com.apple.quicktime.v2

b) Classes

  • The class name should be noun or noun phrases.
  • The class name should be in UpperCamelCase i.e the first letter of each word of the class name should be capitalized.
  • We should try to keep the class names simple and descriptive.
  • Instead of using acronyms and abbreviations, we should use whole words.
  • Examples of some class names:- Employee, ImageSprite, BufferedReader, ArrayList.

c) Interfaces

  • Similar to the class names, the interface name also should be UpperCamelCase.
  • The interface name can be noun or noun phrases but it is better to use adjectives or adjective phrases.
  • Examples of interface names:- List, Collections, Reader, Writer, Storing, Cloneable, AutoCloseable, Serializable, and e.t.c.

d) Methods

  • The method name should be verbs.
  • Method name should be in lowerCamelCase i.e. the first letter of the method name should be lowercase and the first letter of the next internal word onwards should be in uppercase.
  • Example of method names:- toString(), add(), put(), getBackground(), print(), getValue(), getEligibleItemsCount(), and e.t.c.

e) Variables

  • The variable name also should be in lowerCamelCase.
  • It should not start with digits and any special character.
  • In variable names only $ and _ symbols are allowed as special characters but it is better to use camel case instead of these special characters.
  • Only underscore (_) as the variable name is not allowed.
  • Variable names should be short and meaningful.
  • One character variable name should not be used except for the temporary variables. Generally i, j, k, m, and n for integers; c, d, and e for characters are used for temporary variables.
  • Example of variable names:- out, balance, width, myHeight, and e.t.c.

f) Constants

  • The constant names should be in all-uppercase.
  • To separate words in the constant name we can use the underscore(_) symbol.
  • Example of constant names:- MIN_WIDTH, TOTAL_RUNS, MAX_PRIORITY, NORM_PRIORITY, and e.t.c.

2. Google Java Style Guide

Google has also given Google’s coding standards for source code in the Java programming language. The main points for Java Coding Standards are:-

  1. In the import statement, don’t use wildcard imports.
  2. All static imports should be in a single block and all the non-static imports should be in another block. Both blocks should be separated with a single blank line.
  3. Braces should be used with conditional (if-else) and control flow (while, do, for-loop) statements even though it contains only one statement.
  4. Place a blank line before the first member of the class.
  5. Don’t place a blank line after the last member of the class.
  6. Write one statement per line.
  7. Don’t create local variables at the start of their containing block instead declare/initialize them close to the point they are first used, to minimize their scope.
  8. Declare only one variable per declaration.
  9. In switch case statement include the default statement even though it contains no code.
  10. The order for the class and member modifiers recommended by Java Language specification:- public => protected => private => abstract => default => static => final => transient => volatile => synchronized => native => strictfp
  11. There should be only one annotation per line for the class/method/constructor.
  12. For long valued literals always use L (uppercase letter) suffix, not the l (lowercase letter) i.e. use 50546L but not 50546l.
  13. Whenever it is an overridden method then use @Override annotation.
  14. The multiline comment style should be in /* … */ style and each subsequent line must start with *.
  15. It is extremely rare to override the finalize() method of the Object class.

3. Accessibility Modifier for Class Members

We should make our class members inaccessible as much as possible. The lowest possible access modifier for the member is private. This practice is used to develop encapsulation in software design.

In the below Student class all fields are public:-

public class Student {

   public int sid;
   public String sname;
   public String address;
}

Since all fields are public therefore anyone can access them directly. We should assign a private accessibility modifier so that directly other classes can’t access them. If other classes want to access these values then they can use the getter and setter methods of this class.

public class Student {

   private int sid;
   private String sname;
   private String address;
 
   public int getSid() {
      return sid;
   }

   public void setSid(int sid) {
      this.sid = sid;
   }

   public String getSname() {
      return sname;
   }

   public void setSname(String sname) {
      this.sname = sname;
   }

   public String getAddress() {
      return address;
   }

   public void setAddress(String address) {
      this.address = address;
   }   
}

3. In Concatenation Operation Using StringBuilder or StringBuffer instead of String

The string is one of the most commonly used classes in Java. The string is immutable and each modification done on a string object creates a new String object. If we are using String for modification, then unnecessary it will create many String objects which are not useful for our program. Let us understand it through a reverse() method.

class Test {

   public static void main(String[] args) {
      String string = "Hello";
      System.out.println("Original String:: " + string);
      System.out.println("Reverse of String:: " + reverse(string));
   }

   public static String reverse(String string) {
      String reverseString = new String();
      for(int i=string.length()-1; i>=0; i--){
         reverseString = reverseString + string.charAt(i);
         System.out.println(reverseString + ", " 
                  + System.identityHashCode(reverseString));
      }
      return reverseString;
  }
}

Output:-

Original String:: Hello
o, 1309552426
ol, 1943105171
oll, 1704856573
olle, 705927765
olleH, 366712642
Reverse of String:: olleH

In the above program, we can see that for each concatenation operation one new object is created because they have different hashcode values. Just to reverse “Hello” it has created 5 new objects which are not useful. Therefore it is better to use StringBuffer or StringBuilder. Both of these classes are mutable, and each modification will use an existing object rather than creating a new object.

The StringBuffer class is synchronized but the StringBuilder class is non-synchronized. Therefore if we are working with the multi-thread model application then we can go for StringBuffer else in the single-thread model application we can use StringBuilder.

We may think that since we are going to perform all the operations on the StringBuffer or StringBuilder therefore it can be better if our method accepts StringBuffer/StringBuilder and also return StringBuffer/StringBuilder instead of accepting and returning String value. But we should not do that. In that case, we will increase the burden to other programmers who will use this method in their code because they have to convert String to StringBuffer/StringBuilder then call the reverse() method and again covert the returned StringBuffer/StringBuilder value to String. Therefore we should develop our method in such a way that it should accept and return a String value.

public static String reverse(String string) {
   StringBuilder reverseString = new StringBuilder("");
   for(int i=string.length()-1; i>=0; i--){
      reverseString.append(string.charAt(i));
      System.out.println(reverseString + ", " 
                    + System.identityHashCode(reverseString));
   }
   return reverseString.toString();
}

Output:-

Original String:: Hello
o, 622488023
ol, 622488023
oll, 622488023
olle, 622488023
olleH, 622488023
Reverse of String:: olleH

4. Handle Null Pointer Exceptions Properly

NullPointerException is one of the most common exceptions in Java. This exception occurs when we are trying to use an object but the object has a null reference. When we are accessing objects from other resources like databases, servers, files, and e.t.c. In that case, there is a high chance of getting the null reference. Therefore before using these objects we should check it is null or not? And perform the operation only if it is not null. Example:-

try(Connection connection = 
           DriverManager.getConnection(url, user, password) {
   if(connection != null) {
      // perform operations
   } else {
      System.out.println("Connection doesn't established successfully.");
      return;
   }
}

If you want to learn more about Java coding standards then you can follow the below resources:-

If you enjoyed this post, share it with your friends. Do you want to share more information about the topic discussed above or you find anything incorrect? Let us know in the comments. Thank you!

Leave a Comment

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