[JAVA] Item 24: Favor static member classes over nonstatic

24. Select a static member class from a non-static member class

Nested classes should exist for the purpose of assisting the enclosing class. If you want to use nested classes in other contexts, you should define them as top-level classes.

Nested class type

There are four types of nested classes

There is. Other than the static member classes, they are called inner classes.

This chapter describes which nested class should be used in what situations and for what reason.

static member class

The static member class is one of the static members of the enclosing class and follows the same accessibility rules as the other static members.

One of the most common uses of static member classes is as a public helper class that is only valid when used face down with the outer class. As an example, consider an enum that represents a computer operation (Item34). The operation enum should be a public static member class of the Calculator class. Calcurator users can refer to operations as Calculator.Operation.PLUS or Calculator.Operation.PLUS.

Non-static member class

Instances of non-static member classes implicitly have a reference to the enclosing instance. In an instance method in a non-static member class, you can call the method of the enclosing instance and use qualified this to get a reference to the enclosing instance. (Qualified this refers to the enclosing class .this) It is impossible to create an instance of a non-static member class without an enclosing instance, that is, if you want it to be independent, you need to select a static member class.

A reference to an instance of a non-static member class and an enclosing instance is formed when the instance of the member class is created and is not modified thereafter. References are usually formed by calling a non-static member class constructor from an instance method of an enclosing class.

A common use for non-static member classes is Adapter. Adapters can be used to make an instance of an enclosing class appear to be an instance of another class. Specifically, the collection-like appearance returned by the KeySet and values methods of Map uses non-static member classes. Like the Iterator on the List.

    public Iterator<E> iterator() {
        return new Itr();
    }

    /**
     * An optimized version of AbstractList.Itr
     */
    private class Itr implements Iterator<E> {
    ...
    }

If a member class doesn't need access to the enclosing instance, it should always be declared static. This is because it takes time and memory to generate a reference during this time, and without this reference it may be subject to garbage collection (Item 7).

private static member classes are represented as part of the components of the enclosing class. For example, consider a Map instance, many Map implementations have an Entry object as a key-value pair in the Map. Since the Entry methods (getKey, getValue, setValue) do not need to access the map methods, it is useless to make the entry a non-static class. It works even if it is non-static, but it is a waste of memory just because it adds extra references to the map.

Even if you are wondering whether to expose a nested class to the outside, it is important to choose whether to make it static or non-static. When a nested class is exposed to the outside, it cannot be changed from non-static to static. (It will violate backward compatibility)

Anonymous class

It can be said that an anonymous class is declared and instantiated at the same time when it is used, rather than belonging to another class. Anonymous classes can have instances of enclosing classes in non-static contexts. However, even if an anonymous class is written in a static context, it cannot have a static member unless it is a constant variable (primitive or String variable with final).

Anonymous class restrictions

Prior to the introduction of lambda, anonymous classes were used as a means of creating small function objects and process objects (?), But now lambda is preferred. In addition, as a main usage example of anonymous class, it is used in the implementation of static factory method. (Item20)

Local inner class

Local inner classes are declared in the same way as local variables and have the same scope. Should be kept short for readability.

Summary

There are four nested classes, each with different uses. Prepare a member class when it needs to be visible outside the method or too long to be placed inside the method. If each instance of the member class needs to access an instance of the enclosing class, it should be non-static. Other than that, it should be static.

Regarding the class in the method, use it in only one place, and if there is an existing class that regulates the behavior, use the anonymous class. Otherwise, use local inner classes.

Recommended Posts

Item 24: Favor static member classes over nonstatic
Item 29: Favor generic types