Somehow the author keeps on reiterating this point the reason for which essentially boils down as below
- The client need not know the internal implementation/representation of the class/object
- If exposed, it would become cumbersome in the event of changing the implementation/representation of the class, which may cause several breakages in client code. On the other hand if the field was exposed through getter methods, the change in the implementation would have gone unnoticed by the client.
- Allow public access, if neccessary only in case of static final and primitive fields.(even in this case, when the field or object itself is passed from one thread to another, one needs to exercise caution - why?)
- But a final array field may not become immutable after all. In that case make it private and expose an unmodifiable public list field. Or make it private and provide a getter method which returns a copy of the array.
Totally! ######Steps for creating Immutable Classes
- Make the class final so that subclassing is not possible (the author says subclassing is possible in other ways - find how?)
- Make all fields private
- Make all fields final
- Do not provide methods that can modify the state
- Do not provide any kind of access to fields that references mutable objects
-
Generally function pointers/lambda functions are used by passing by a function caller to get a custom implementation that the caller specifically wants
-
This is achievable in Java by what the author calls function objects
-
Remember Comparator<> ?
- This is generally stateless and hence does not contain any fields
- Provide an interface which declares the method for implementation
- Provide a concrete implementation using an anonymous class and pass it. The interface provides the type
- In case if the implementation will be used repeatedly, define the implementation as a private static class inside the host class and provide a public static field of the interface type referring to the private concrete implementation
public Interface Comparator<T> { public int compare(T s1, T s2); } // Concrete implementation using an anonymous class Arrays.sort(stringArray, new Comparator<String>() { public int compare(String s1, String s2) { return s1.length() - s2.length(); } });
A class can be defined inside another class which makes the former, a nested class. If the nested class is non-static, it is an Inner class. A non static nested class aka inner class, cannot exist without an instance of the enclosure class. Example as follows:
//Static nested class
public class A {
public static class B {
}
}
In the above case, B
can instantiated by A.B b = new A.B()
//Non static nested class aka Inner class
public class A {
public class B {
}
}
In this case, an instance of B
cannot exist without an instance of A
and instantiation is done like A.B b = a.new B()
where a
is an instance of A
.
An example of a non static member class is from java.Util
classes like Set
, List
, etc. where these classes have implementation for Iterator
as non static member.
public class MySet<E> extends AbstractSet<E> {
..
public Iterator<E> iterator() {
return new MyIterator();
}
private class MyIterator implements Iterator<E> {
...
}
}
On the other hand, static members are used by Map
for implementing Entry
inside them. Having Entry
as non static would also do the job, but implementation of Entry
methods(getKey
, getValue
, etc) din't require any access of an instance of the Map
implementation. Hence having it as non static would be just a waste of resources as the author points out.