Tuesday, December 24, 2013

Static Class in Java

Consider a class with utility methods. In this case instantiating an instance every time we need those methods, does not make sense. So what exactly should be done.

Should we go with abstract class? An abstract class may not make sense as we do not expect derived classes to provide any implementation. We can go with a static class (Here I mean a class with static methods).

So, When do we need to write a static class?
When we have a bunch of utility methods and instantiation of the class seems nonsensical.

So what is the best way to write a static class?1
Enforce noninstantiability  by using private constructor (from Effective Java, Item 4)
  1. Attempting to enforce noninstantiability by making a class abstract does not work.
  2. A default constructor is generated only if a class contains no explicit constructors, so a class can be made noninstantiable by including a private constructor:
So we need: A class with private constructor and static methods.

As the constructor is private it is not accessible to outside world so there can not be any derived class. Though not needed, we can also make the class final as there is no harm in being explicit.
// Noninstantiable utility class
public class UtilityClass
{
    // Suppress default constructor for noninstantiability
    private UtilityClass() {
        throw new AssertionError();
    }
}

An Assertion Error is a good idea as it ensures us in case the constructor is invoked accidentally with in the class. As a side effect this class cannot be extended now.

We should keep in mind one thing: Static methods are death to testability. Also they do not participate in Object Oriented world and therefore are considered bad by few people.

In the above article I used the term Static class to mean the class with static methods. Otherwise only nested classes can be static.
class OuterClass{
    public static class StaticNestedClass{
    }

    public class InnerClass{
    }

    public InnerClass getAnInnerClass(){
        return new InnerClass();
    }

    //This method doesn't work
    public static InnerClass getAnInnerClassStatically(){
        return new InnerClass();
    }
}

class OtherClass{
    //Use of a static nested class:
    private OuterClass.StaticNestedClass staticNestedClass = new OuterClass.StaticNestedClass();

    //Doesn't work
    private OuterClass.InnerClass innerClass = new OuterClass.InnerClass();

    //Use of an inner class:
    private OuterClass outerclass= new OuterClass();
    private OuterClass.InnerClass innerClass2 = outerclass.getAnInnerClass();
    private OuterClass.InnerClass innerClass3 = outerclass.new InnerClass();
}
All static methods (in fact all the methods) and static variables are stored in the PermGem section of the heap, since they are part of the reflection data (class related method and not instance related). The variables (or variable definitions) are store in PermGen section but the objects they refer to get stored somewhere on the heap. More can be found here.

More about garbage collection and memory allocation can be read here and here.

No comments: