Chapeter 4 Classes and Interfaces
Item 22: Favor static member classes over nonstatic
This item tells you when to use which kind of nested class and why.
-
1.Nested Class
- [Principle] A nested class should exist only to serve its enclosing class.
- [otherwise] it should be a top-level class
- [Types] 4 kinds of nested classes
- (1) static member classes
- (2) nonstatic member classes
- (3) anonymous classes
- (4) local classes
- [Note] All but the first kind are known as inner classes.
- [Principle] A nested class should exist only to serve its enclosing class.
- ###2.Static Member Class
- [comment] it is the simplest kind of nested class.
- [essential] an ordinary class that happens to be declared inside another class
- [feature] it has access to all of the enclosing class’s members, even those declared private
- [common use]
- (1) a public helper class
- (2) private static member classes is to represent components of the object
- [Example] Many Map implementations have an internal Entry object
- Entry object has getKey, getValue , and setValue
- [Example] Many Map implementations have an internal Entry object
- [For example]
- (1) an enum describing the operations supported by a calculator
- (2) The Operation enum should be a public static member class of the Calculator class.
- (3) using operation like Calculator.Operation.PLUS and Calculator.Operation.MINUS
If you declare a member class that does not require access to an enclosing instance, always put the static modifier in its declaration
- ###3.Nonstatic Member Classes
- (1) without the modifier static
- (2) it is implicitly associated with an enclosing instance of its containing class.
- (3) obtain a reference to the enclosing instance using the qualified this construct
- (4) it is impossible to create an instance of a nonstatic member class without an enclosing instance.
- [common use] define an Adapter
- it allows an instance of the outer class to be viewed as an instance of some unrelated class.
-
[For example] implementations of the Map interface typically use nonstatic member classes to implement their collection views
-
An Example: implementations of the collection interfaces, such as Set and List , typically use nonstatic member classes to implement their iterators
===========================Constant Interface=========================== // Typical use of a nonstatic member class public class MySet<E> extends AbstractSet<E> { ... // Bulk of the class omitted public Iterator<E> iterator() { return new MyIterator(); } private class MyIterator implements Iterator<E> { ... } }
Note: Storing this reference costs time and space, and can result in the enclosing instance being retained when it would otherwise be eligible for garbage collection (Item 6)
- Anonymous Classes:
- Features:
- (1) no name
- (2) not a member of its enclosing class
- (3) declared and instantiated at the point of use
- (4) if they occur in a static context, they cannot have any static members.
- Limitations:
- (1) can’t instantiate them except at the point they’re declared
- (2) can’t perform instanceof tests or do anything else that requires you to name the class.
- (3) can’t declare an anonymous class to implement multiple interfaces, tor o extend a class and implement an interface at the same time
- (4) can’t invoke any members except those it inherits from its supertype
- Recommendation
- [readability] Because anonymous classes occur in the midst of expressions, they must be kept short (<= 10 lines)
- Common Use
- (1) create function objects (Item 21)
- (2) create process objects, such as Runnable, Thread, or TimerTask instances
-
(3) within static factory methods
===============extends abstract class======================= abstract class Person { public abstract void eat(); } class Child extends Person { public void eat() { System.out.println("eat something"); } } public class Demo { public static void main(String[] args) { Person p = new Child(); p.eat(); } } ===================abstract=================================== abstract class Person { public abstract void eat(); } public class Demo { public static void main(String[] args) { Person p = new Person() { public void eat() { System.out.println("eat something"); } }; p.eat(); } } =========================interface============================ interface Person { public void eat(); } public class Demo { public static void main(String[] args) { Person p = new Person() { public void eat() { System.out.println("eat something"); } }; p.eat(); } } ==============================Thread============================= public class Demo { public static void main(String[] args) { Thread t = new Thread() { public void run() { for (int i = 1; i <= 5; i++) { System.out.print(i + " "); } } }; t.start(); } } ===============================Runnable=========================== public class Demo { public static void main(String[] args) { Runnable r = new Runnable() { public void run() { for (int i = 1; i <= 5; i++) { System.out.print(i + " "); } } }; Thread t = new Thread(r); t.start(); } }
- Features:
- Local Classes
- Less frequently used
- Features:
- Like member classes, they have names and can be used repeatedly
- Like anonymous classes, they
- (1)have enclosing instances only if defined in a nonstatic context
- (2) cannot contain static members
- (3) should be kept short so as not to harm readability.
- without the modifier public,private,protected,static
- can add final, abstract
- have access to outer class member
- NO access to enclosing function’s local variable, except final variable.
-
[Most Important] local classes are declared in functions
==========================Local Classes============================ public class outerTolocal{ public String string; public int localInt; public void outerTolocal(){} public void localMthod(final int m ,int n){ class local{ // note the variable m must have final int methodInt = m; void localInner(){ System.out.println("local method"); } } new local().localInner(); } }
-
Conclusion
- (1) [member class]If a nested class needs to be visible outside of a single method or is too long to fit comfortably inside a method, use a member class.
- If each instance of the member class needs a reference to its enclosing instance, make it nonstatic; otherwise, make it static.
- (2) [anonymous & local class] Assuming the class belongs inside a method:
- if you need to create instances from only one location and there is a preexisting type that characterizes the class, make it an anonymous class; otherwise, make it a local class.
- (1) [member class]If a nested class needs to be visible outside of a single method or is too long to fit comfortably inside a method, use a member class.