Classes & Interfaces

1,102 views

Published on

Notes from Classes & Interfaces chapter, Effective Java by Joshua Bloch

Published in: Education, Technology
  • Be the first to comment

Classes & Interfaces

  1. 1. <ul><li>[ Effective Java by Joshua Bloch ] </li></ul>
  2. 2. <ul><li>Minimize the accessibility of classes and members </li></ul>
  3. 3. <ul><li>Most important factor for a well designed module </li></ul><ul><li>The degree to which it hides its internal data and other implementation details from other modules </li></ul><ul><li>Well Designed Module </li></ul><ul><li>A module that hides all of its implementation details, separating from its API </li></ul>
  4. 4. <ul><li>ADVANTAGES </li></ul><ul><li>Decouples the modules </li></ul><ul><li>Parallel Modular Development </li></ul><ul><li>Ease of maintenance </li></ul><ul><li>Effective Performance Tuning </li></ul><ul><li>Increased Software Reusability </li></ul><ul><li>Reduction of risk in building large systems </li></ul>
  5. 5. <ul><li>HOW? </li></ul><ul><li>Access Control Mechanism </li></ul><ul><li> specifies the accessibility of classes, interfaces and members </li></ul><ul><li>Accessibility </li></ul><ul><li> determined by location of declaration & access specifiers, if any </li></ul><ul><li>Rule of Thumb : </li></ul><ul><li>Make each class or members as INACCESSIBLE as possible </li></ul>
  6. 6. <ul><li>TOP LEVEL CLASSES & INTERFACES </li></ul><ul><li>Can be public </li></ul><ul><li> part of API </li></ul><ul><li> To be supported forever to maintain compatibility </li></ul><ul><li>Can be package-private/default </li></ul><ul><li> can be modified, replaced or modified in subsequent releases without fear of harming clients </li></ul><ul><li>Tip : </li></ul><ul><li>If a package-private top level class/interface is used by only one class, consider making the top level class a private nested class of the sole class that uses it. </li></ul>
  7. 7. <ul><li>For Members </li></ul><ul><li>Private: only from the top level class where it its declared </li></ul><ul><li>Package-Private/ default: from any class in the package </li></ul><ul><li>Protected: default access+ subclasses can access </li></ul><ul><li>Public: can be accessed anywhere </li></ul><ul><li>TIP </li></ul><ul><li>Both private and package-private members are part of class’ implementation & don not normally are part of its exported API, unless the class implements serializable </li></ul><ul><li>After designing our class’ public API, we should make all other members private only if another class in the same package needs to access any of these members, we remove the private modifiers , thus giving it default access. </li></ul>
  8. 8. <ul><li>PROTECTED MEMBERS </li></ul><ul><li>Part of class’ exported API and must be supported forever </li></ul><ul><li>Represent a public commitment to an implementation detail </li></ul><ul><li>If a method overrides a superclass method, it is not permitted to have a lower access level than it does in the superclass . . .Why? </li></ul>
  9. 9. <ul><li>It is necessary to ensure that instance of subclass must be usable everywhere where instance of superclass is usable </li></ul><ul><li>Caution </li></ul><ul><li>It is not acceptable to make a class, interface or a member, more accessible than package-private, i.e., a part of package’s exported API to facilitate testing. </li></ul>
  10. 10. <ul><li>Instance Fields should never be public </li></ul><ul><li>If non-final or final reference to a mutable object, it limits the values that can be stored </li></ul><ul><li>Can’t enforce invariants involving these fields </li></ul><ul><li>Classes with public mutable fields are not thread safe </li></ul><ul><li>Similarly for static fields with one exception that using public static final fields, we can specify constants specified by class </li></ul>
  11. 11. <ul><li>A nonzero-length array is always mutable, it is wrong for a class to have a public static final array field, or an accessor that returns such a field. If a class has such a field or accessor, clients will be able to modify the contents of the array. </li></ul><ul><li>public static final Thing[] VALUES = { ... }; </li></ul><ul><li>There are two ways to fix the problem. You can make the public array private and add a public immutable list: </li></ul><ul><li>private static final Thing[] PRIVATE_VALUES = { ... }; </li></ul><ul><li>public static final List<Thing> VALUES = </li></ul><ul><li>Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES)); </li></ul><ul><li>Alternatively, you can make the array private and add a public method that returns a copy of a private array: </li></ul><ul><li>private static final Thing[] PRIVATE_VALUES = { ... }; </li></ul><ul><li>public static final Thing[] values() { </li></ul><ul><li>return PRIVATE_VALUES.clone(); </li></ul><ul><li>} </li></ul>
  12. 12. <ul><li>In public classes, use accessor methods, not public fields </li></ul>
  13. 13. Sometimes we’ve to write classes that serve no purpose other than to group instance fields: class Point { public double x; public double y; }
  14. 14. <ul><li>Data accessible directly, these classes do not offer the benefits of encapsulation </li></ul><ul><li>We can’t change the representation without changing the API </li></ul><ul><li>We can’t enforce invariants, and </li></ul><ul><li>We can’t take auxiliary action when a field is accessed. </li></ul>
  15. 15. <ul><li>If a class is accessible outside its package, provide accessor methods, to preserve the flexibility to change the class’s internal representation. </li></ul><ul><li>class Point { </li></ul><ul><li>private double x; </li></ul><ul><li>private double y; </li></ul><ul><li>public Point(double x, double y) { </li></ul><ul><li>this.x = x; </li></ul><ul><li>this.y = y; </li></ul><ul><li>} </li></ul><ul><li>public double getX() { return x; } </li></ul><ul><li>public double getY() { return y; } </li></ul><ul><li>public void setX(double x) { this.x = x; } </li></ul><ul><li>public void setY(double y) { this.y = y; } </li></ul><ul><li>} </li></ul>
  16. 16. <ul><li>If a class is package-private or is a private nested class, there is nothing inherently wrong with exposing its data fields assuming they do an adequate job of describing the abstraction provided by the class </li></ul><ul><li> --less visual clutter than the accessor-method approach </li></ul><ul><li>While the client code is tied to the class’s internal representation, this code is confined to the package containing the class. If a change in representation becomes desirable, we can make the change without touching any code outside the package. </li></ul><ul><li>Public classes should never expose mutable fields. </li></ul><ul><li>It is less harmful, though still questionable, for public classes to expose immutable fields.  </li></ul><ul><li>It is, however, sometimes desirable for package-private or private nested classes to expose fields, whether mutable or immutable </li></ul>
  17. 17. <ul><li>Minimize mutability </li></ul>
  18. 18. <ul><li>IMMUTABLE CLASS </li></ul><ul><li>An immutable class is simply a class whose instances cannot be modified. All of the information contained in each instance is provided when it is created and is fixed for the lifetime of the object </li></ul><ul><li>examples-String, the boxed primitive classes, and BigInteger and BigDecimal </li></ul><ul><li>Easier to design, implement, and use than mutable classes. Less prone to error and are more secure. </li></ul>
  19. 19. <ul><li>HOW TO MAKE A CLASS IMMUTABLE </li></ul><ul><li>Don’t provide any methods that modify the object’s state </li></ul><ul><li>Ensure that the class can’t be extended. </li></ul><ul><li>Make all fields final </li></ul><ul><li>Make all fields private </li></ul><ul><li>Ensure exclusive access to any mutable </li></ul>
  20. 20. <ul><li>public final class Complex { </li></ul><ul><li>private final double re; </li></ul><ul><li>private final double im; </li></ul><ul><li>public Complex(double re, double im) { </li></ul><ul><li>this.re = re; </li></ul><ul><li>this.im = im; </li></ul><ul><li>} </li></ul><ul><li>public double realPart() { return re; } </li></ul><ul><li>public double imaginaryPart() { return im; } </li></ul><ul><li>public Complex add(Complex c) {return new Complex(re + c.re, im + c.im);} </li></ul><ul><li>public Complex subtract(Complex c) {return new Complex(re - c.re, im - c.im);} </li></ul><ul><li>public Complex multiply(Complex c) {return new Complex(re * c.re - im * c.im,re * c.im + im *c.re);} </li></ul><ul><li>public Complex divide(Complex c) { </li></ul><ul><li>double tmp = c.re * c.re + c.im * c.im; </li></ul><ul><li>return new Complex((re * c.re + im * c.im) / tmp,(im * c.re - re * c.im) / tmp); </li></ul><ul><li>} </li></ul>
  21. 21. <ul><li>@Override </li></ul><ul><li>public boolean equals(Object o) { </li></ul><ul><li>if (o == this) </li></ul><ul><li> return true; </li></ul><ul><li>if (!(o instanceof Complex)) </li></ul><ul><li> return false; </li></ul><ul><li>Complex c = (Complex) o; </li></ul><ul><li> return Double.compare(re, c.re)==0 && Double.compare(im,c.im)==0; </li></ul><ul><li> } </li></ul><ul><li>@Override </li></ul><ul><li>public int hashCode() { </li></ul><ul><li>int result = 17 + hashDouble(re); </li></ul><ul><li>result = 31 * result + hashDouble(im); </li></ul><ul><li>return result; </li></ul><ul><li>} </li></ul><ul><li>private int hashDouble(double val) { </li></ul><ul><li>long longBits = Double.doubleToLongBits(re); </li></ul><ul><li>return (int) (longBits ^ (longBits >>> 32)); </li></ul><ul><li>} </li></ul><ul><li>@Override public String toString() {return &quot;(&quot; + re + &quot; + &quot; + im + &quot;i)“;} </li></ul><ul><li>} </li></ul>
  22. 22. <ul><li>PROPERTIES OF IMMUTABLE OBJECTS </li></ul><ul><li>Immutable objects are simple </li></ul><ul><li>Immutable objects are inherently thread-safe; they require no synchronization </li></ul><ul><li>Immutable objects can be shared freely </li></ul>
  23. 23. <ul><li>An immutable class can provide static factories that cache frequently requested instances to avoid creating new instances. </li></ul><ul><li>Using such static factories causes clients to share instances instead of creating new ones, reducing memory footprint and garbage collection costs. </li></ul><ul><li>Opting for static factories over public constructors gives the flexibility to add caching later, without modifying clients. </li></ul><ul><li>Not only can you share immutable objects, but you can share their internals. </li></ul><ul><li>Immutable objects make great building blocks for other objects, whether mutable or immutable </li></ul>
  24. 24. <ul><li>The only real disadvantage of immutable classes is that they require a separate object for each distinct value. </li></ul><ul><li>For example, suppose that you have a million-bit BigInteger and you want to change its low-order bit: </li></ul><ul><li>BigInteger moby = ...; </li></ul><ul><li>moby = moby.flipBit(0); </li></ul><ul><li>The flipBit method creates a new BigInteger instance, also a million bits long, that differs from the original in only one bit. The operation requires time and space proportional to the size of the BigInteger. </li></ul><ul><li>Problem is magnified if you perform a multistep operation that generates a new object at every step. </li></ul>
  25. 25. <ul><li>Internally, the immutable class can be arbitrarily clever. For example, BigInteger has a package-private mutable “companion class” that it uses to speed up multistep operations. </li></ul><ul><li>This approach works fine if we can accurately predict which complex multistage operations clients will want to perform on our immutable class. If not, then our best bet is to provide a public mutable companion class. e.g. String class, whose mutable companion is StringBuilder and BitSet plays the role of mutable companion to BigInteger under certain circumstances. </li></ul>
  26. 26. <ul><li>To guarantee immutability, a class must not permit itself to be subclassed. </li></ul><ul><li>Typically this is done by making the class final, but there is another, more flexible way to do it,i.e., make all of its constructors private or package-private, and to add public static factories in place of the public constructors </li></ul><ul><li>public class Complex { </li></ul><ul><li>private final double re; </li></ul><ul><li>private final double im; </li></ul><ul><li>private Complex(double re, double im) { </li></ul><ul><li>this.re = re; </li></ul><ul><li>this.im = im; </li></ul><ul><li>} </li></ul><ul><li>public static Complex valueOf(double re, double im) {return new Complex(re, im);} </li></ul><ul><li>... </li></ul><ul><li>} </li></ul><ul><li>To its clients that reside outside its package, the immutable class is effectively final because it is impossible to extend a class that comes from another package and that lacks a public or protected constructor. </li></ul>
  27. 27. <ul><li>Advantage of static factory </li></ul><ul><li>If we want to have two constructors with same signature, say we want to construct a complex number, for construction from polar coordinates and from Cartesian coordinates, we will have similar constructor Complex(double, double). It’ll not be possible using constructors. But we can have two static factories one for Cartesian system and one for polar system. </li></ul>
  28. 28. <ul><li>If we choose to have immutable class implement Serializable and it contains one or more fields that refer to mutable objects, we must provide an explicit readObject or readResolve method, or use the ObjectOutputStream.writeUnshared and ObjectInputStream.readUnshared methods, even if the default serialized form is acceptable. Otherwise an attacker could create a mutable instance of your not quite-immutable class. </li></ul><ul><li>There are some classes for which immutability is impractical. </li></ul><ul><li>If a class cannot be made immutable, limit its mutability as much as possible. </li></ul>
  29. 29. <ul><li>Favor Composition over Inheritance </li></ul>
  30. 30. <ul><li>Inheritance </li></ul><ul><li>Powerful way to achieve code reuse but not a good idea always </li></ul><ul><li>When? </li></ul><ul><li>When the subclass and the super class implementations are under the control of the same programmers </li></ul><ul><li>When extending classes specifically designed and documented for extension </li></ul><ul><li>When Not? </li></ul><ul><li>Inheriting from ordinary concrete classes across package boundaries </li></ul>
  31. 31. <ul><li>Use interfaces only to define types </li></ul>
  32. 32. <ul><li>When a class implements an interface, the interface serves as a type that can be used to refer to instances of the class. </li></ul><ul><li>Class provides implementation of methods declared in interface to tell that what a client can do with the instances. </li></ul><ul><li>Interface shouldn’t be used for any other purposes. </li></ul><ul><li>One of the interfaces- which does not conforms to this is Constant Interface. </li></ul><ul><li>contains no methods; it consists solely of static final fields, each exporting a constant. </li></ul><ul><li>public interface PhysicalConstants { </li></ul><ul><li>// Avogadro's number (1/mol) </li></ul><ul><li>static final double AVOGADROS_NUMBER = 6.02214199e23; </li></ul><ul><li>// Boltzmann constant (J/K) </li></ul><ul><li>static final double BOLTZMANN_CONSTANT = 1.3806503e-23; </li></ul><ul><li>// Mass of the electron (kg) </li></ul><ul><li>static final double ELECTRON_MASS = 9.10938188e-31; </li></ul><ul><li>} </li></ul>
  33. 33. <ul><li>Implementing a constant interface causes this implementation detail to leak into the class’s exported API. It is of no consequence to the users of a class. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a non final class implements a constant interface, all of its subclasses will have their namespaces polluted by the constants in the interface.  </li></ul><ul><li>There are several constant interfaces in the Java platform libraries, such as java.io.ObjectStreamConstants. These interfaces should be regarded as anomalies and should not be emulated. </li></ul>
  34. 34. <ul><li>ALTERNATIVES </li></ul><ul><li>If the constants are strongly tied to an existing class or interface, you should add them to the class or interface. For example, all of the boxed numerical primitive classes, such as Integer and Double, export MIN_VALUE and MAX_VALUE constants.  </li></ul><ul><li>If the constants are best viewed as members of an enumerated type, export them with an enum type   </li></ul><ul><li>Otherwise, you should export the constants with a non instantiable utility class </li></ul><ul><li>Normally a utility class requires clients to qualify constant names with a class name, for example, PhysicalConstants.AVOGADROS_NUMBER. </li></ul><ul><li>If we make heavy use of the constants exported by a utility class, we can avoid the need for qualifying the constants with the class name by making use of the static import facility. </li></ul>
  35. 35. <ul><li>Prefer class hierarchies to tagged classes </li></ul>
  36. 36. <ul><li>// Tagged class - vastly inferior to a class hierarchy! </li></ul><ul><li>class Figure { </li></ul><ul><li>enum Shape { RECTANGLE, CIRCLE }; </li></ul><ul><li>// Tag field - the shape of this figure </li></ul><ul><li>final Shape shape; </li></ul><ul><li>// These fields are used only if shape is RECTANGLE </li></ul><ul><li>double length; </li></ul><ul><li>double width; </li></ul><ul><li>// This field is used only if shape is CIRCLE </li></ul><ul><li>double radius; </li></ul><ul><li>// Constructor for circle </li></ul><ul><li>Figure(double radius) {shape = Shape.CIRCLE;this.radius = radius;} </li></ul><ul><li>// Constructor for rectangle </li></ul><ul><li>Figure(double length, double width) {shape = Shape.RECTANGLE;this.length = length;this.width = width;} </li></ul><ul><li>double area() { </li></ul><ul><li>switch(shape) { </li></ul><ul><li>case RECTANGLE: </li></ul><ul><li> return length * width; </li></ul><ul><li>case CIRCLE: </li></ul><ul><li> return Math.PI * (radius * radius); </li></ul><ul><li>default: </li></ul><ul><li> throw new AssertionError(); </li></ul><ul><li> } </li></ul><ul><li> } </li></ul><ul><li>} </li></ul>
  37. 37. <ul><li>Use function objects to represent strategies </li></ul>
  38. 38. <ul><li>What are function objects? </li></ul><ul><li>An instance of a class whose methods perform operation , on other objects passed explicitly to them e.g. </li></ul><ul><li>class StringLengthComparator { </li></ul><ul><li>public int compare(String s1, String s2) { </li></ul><ul><li>return s1.length() - s2.length(); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>A reference to a StringLengthComparator object serves as “function pointer” to the comparator, allowing it to be invoked on arbitrary pair of strings. </li></ul><ul><li>This class is now concrete strategy for string comparision </li></ul>
  39. 39. <ul><li>Typically, a concrete strategy class is stateless, it has no fields, hence all instances of the class are finally equivalent. </li></ul><ul><li>Thus, it should be a singleton to save on unnecessary object creation costs. </li></ul><ul><li>class StringLengthComparator { </li></ul><ul><li>private StringLengthComparator() { } </li></ul><ul><li>public static final StringLengthComparator </li></ul><ul><li>INSTANCE = new StringLengthComparator(); </li></ul><ul><li>public int compare(String s1, String s2) { </li></ul><ul><li>return s1.length() - s2.length(); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>Concrete classes are often declared using anonymous classes </li></ul><ul><li>Arrays.sort(stringArray, new Comparator<String>() { </li></ul><ul><li>public int compare(String s1, String s2) { </li></ul><ul><li>return s1.length() - s2.length(); </li></ul><ul><li>} </li></ul><ul><li>}); </li></ul>
  40. 40. <ul><li>But note that using an anonymous class in this way will create a new instance each time the call is executed. If it is to be executed repeatedly, consider storing the function object in a private static final field and reusing it. </li></ul><ul><li>Another advantage of doing this is that you can give the field a descriptive name for the function object. </li></ul>
  41. 41. <ul><li>Because the strategy interface serves as a type for all of its concrete strategy instances, a concrete strategy class needn’t be made public to export a concrete strategy. Instead, a “host class” can export a public static field (or static factory method) whose type is the strategy interface, and the concrete strategy class can be a private nested class of the host. In the example that follows, a static member class is used in preference to an anonymous class to allow the concrete strategy class to implement a second interface, Serializable: </li></ul><ul><li>// Exporting a concrete strategy </li></ul><ul><li>class Host { </li></ul><ul><li>private static class StrLenCmp implements Comparator<String>, Serializable { </li></ul><ul><li>public int compare(String s1, String s2) {return s1.length() - s2.length();} </li></ul><ul><li>} </li></ul><ul><li>// Returned comparator is serializable </li></ul><ul><li>public static final Comparator<String> </li></ul><ul><li>STRING_LENGTH_COMPARATOR = new StrLenCmp(); </li></ul><ul><li>...//Bulk of class omitted </li></ul><ul><li>} </li></ul><ul><li>The String class uses this pattern to export a case-independent string comparator via its CASE_INSENSITIVE_ORDER field. </li></ul>
  42. 42. <ul><li>Favor static member classes over non static </li></ul>
  43. 43. <ul><li>A nested class should exist only to serve its existing class </li></ul><ul><li>Four types of nested classes </li></ul><ul><li>Static member class </li></ul><ul><li>Non static member class </li></ul><ul><li>Anonymous class </li></ul><ul><li>Local class </li></ul><ul><li>All but the first kind are known as Inner class </li></ul>
  44. 44. <ul><li>A static member class of its enclosing class and obeys the same accessibility rules as other static members. </li></ul><ul><li>Static member class has access to all of the enclosing class’ members, even those declared private </li></ul><ul><li>Static member class, if declared private, is accessible only within enclosing class </li></ul><ul><li>Common use: a public helper class for outer class </li></ul><ul><li>Each instance of a non static member class is implicitly associated with an enclosing instance of its containing class. </li></ul><ul><li>Within instance methods of a non static member class, we can invoke methods on the enclosing instance or obtain a reference to the encloasing instance using the qualified this construct </li></ul><ul><li>If an instance of a nested class can exist in isolation from an instance of its enclosing class, then the nested class must be a static member class: it is impossible to create an instance of a nonstatic member class without an enclosing instance. </li></ul>
  45. 45. <ul><li>The association between a nonstatic member class instance & its enclosing instance is established when the former is created, it can’t be modifies thereafter </li></ul><ul><li>This association: 1) established automatically by invoking a nonstatic member class constructor from within an instance method 2)possible manually too: enclosingInstance.newMemberClass(args) 3) takes up space in the nonstatic member class interface & adds time to its construction. </li></ul><ul><li>Use: To define an Adapter that allows an instance of outer class to be viewed as an instance of some unrelated class. e.g. In a Map interface, non static member classes are used to obtain keyset, entry set and values. Similarly, Iterators are implemented using nonstatic member classes </li></ul><ul><li>TIP: If we declare a member class that does not require access to an enclosing instance, always put the static modifier in its declaration </li></ul>
  46. 46. <ul><li>If we omit this modifier, each instance will have an extraneous reference, to its enclosing instance. Storing this costs time & space, & can result in the enclosing instance being retained when it would otherwise be eligible for GC </li></ul><ul><li>Non static member class: instances are required to have an enclosing instance, we can’t allocate an instance without its enclosing instance. </li></ul><ul><li>USE: To represent components of the objects represented by their enclosing class e.g. in Map, we have an entry object, methods on entry object need not to access the map </li></ul><ul><li>IMPORTANT To choose between static & nonstatic, if the class is a member of an exported class. </li></ul>

×