ºÝºÝߣ

ºÝºÝߣShare a Scribd company logo
Effective Java                 (Second Edition)


CHAPTER 4: Classes and Interfaces


              presented by
            Chandan Benjaram
Agenda
Item 13: Minimize the accessibility of classes and members

Item 14: In public classes, use accessor methods, not public ?elds

Item 15: Minimize mutability

Item 16: Favor composition over inheritance

Item 17: Design and document for inheritance or else prohibit it

Item 18: Prefer interfaces to abstract classes

Item 19: Use interfaces only to de?ne types

Item 20: Prefer class hierarchies to tagged classes

Item 21: Use function objects to represent strategies

Item 22: Favor static member classes over non-static
Item-13: Minimize the accessibility of classes and
                    members
   A well designed API should hide all of its implementation details(a.k.a,
   internals) and thus component inter-communication should happen
   through a well declared API standards (protocols). Thus in general, it
   should encourage highest possible cohesion and loose coupling, if any!

Point-I: Make each class member as inaccessible as possible
  How you do it?
     ?use package private/public on top-outer classes
     ?use access modi?ers for members (private, package private,
     protected, public)

  Leaks?
    ?security can be leaked if class implements ¡®Serializable¡¯

  Fix:
    ?use ¡®transient¡¯ keyword
Point-II: Instance ?elds should never be public
  Problem:
     //Potential security hole!
     public static ?nal Type[] VALUES = { ... };

  Fix:
      private static ?nal Type[] PRIVATE_VALUES = { ... };
      public static ?nal List VALUES = Collections.unmodi?ableList(Arrays.asList(PRIVATE_VALUES));



Point-III: Public classes should not contain any public ?elds with the exception of
immutable public static ?nal ?elds
Item-14: Public classes should encourage use of
   accessors/mutators instead of public ?elds
  ?if a class is accessible outside its package, provide accessors
  ?incase of package private/private nested classes, it is OK to expose
  ?elds through ¡®public¡¯ access modi?ers
Item-15: Minimize mutability
What is immutable class?
 ?its a, very simple to write, class whose instance can not be
 modi?ed once initialized
 ?maintains a single state across all calls, thus thread safe by
 default

How to make a class immutable?
  ?avoid mutators (use functional approach instead!)
  ?make it non-extendable
  ?make all ?elds ?nal
  ?make all ?elds private
  ?ensure exclusive access to any mutators, if any
   Ex: Use defensive copying techniques, readObject, etc.

Note: beware of nested classes! (possible security hole)
Advantages of immutable classes:
  ?each object belongs to a single state avoiding any complex state
  transformations
  ?by default, they are thread-safe. thus no synchronization needed
  ?effective pooling, caching can be performed with the aid of
  different techniques and patterns
    Ex: Factory pattern.

Suggestion:
 ?never provide a copy constructor/clone methods (String.copy()
 violates)

Disadvantages:
   ?each distinct value object requires its own object increasing
   memory footprint and GC demand
   ?problem becomes more worse when working with complicated
   multistage operations on large objects
Solution:
 ?memory footprint and GC demand problem can be limited by
 sharing class self internals.
      Ex: BigInteger (signum-magnitude)
       public BigInteger negate()
          Returns a BigInteger whose value is (-this).
 ?nicely designed public companion classes can handle multistage
 operations problem very smoothly
   Ex: StringBuilder for immutable class, String

?nally:
 ?classes should be immutable unless there is a precise reason to
 make mutable
 ?make every ?eld as ?nal unless there is a precise reason to avoid
 ?fully initialize object with all its required invariants either using
 constructor/static factories but not with any public helpers
   Hint: Builder pattern can save your life!
Item-16: Favor Composition over Inheritance
But, why?
  ?violates encapsulation
  ?parent private ?elds can not be accessible if needed!

Solution:
 ?Use Composition pattern + Forwarding Methods, which may be seen
 as Decorator pattern (loosely speaking!)
but wait, there is a problem:
 ?it may cause wrapped object blind in viewing wrapper object. thus
 Callback frameworks fails to function as expected. A ¡®SELF problem¡¯.
When to prefer inheritance then?
 ?if you can precisely establish a ¡®is-a¡¯ relationship between sub-class
 and super-class then go for it!
      JDK violators- Properties (is-not-a HashTable), Stack (is-not-a
      Vector), etc.

Finally:
  ?read API docs thoroughly for any ?aws, violations, limitations, etc.,
  before implementing an interface
Item-17: Design and document for Inheritance or
                 else prohibit it
  ?class must document its self-use of override-able methods
  ?parent private ?elds can not be accessible if needed!
  ?a class designed for inheritance must be reviewed thoroughly. once
  shipped, it would be impossible to make changes without breaking
  own clients
  ?constructors must not invoke override-able methods

  Example:
  a super class
a subclass




 Finally:
   ?incase of no options other than self-use of override-able methods,
   use self speci?c code to private helpers
Item-18: Prefer interfaces to abstract classes
 ?as   java permits only single inheritance, a abstract class type
 de?nition is more constrained vs an interface de?nition
 ?abstract class hierarchies may cause ¡®combinatorial explosion¡¯
 ?on the other hand, interfaces are ideal for mixins. thus adds more
 type de?nitions to primary type
 ?existing classes can be easily retro?tted to implement new
 interface
 ?design your interface with outmost case. once it is shipped & used,
 it can not be possible to change method signature or add more
 without breaking its clients
 ?preferably, provide a ¡®skeletal implementation¡¯(abstract interface) of
 your interface to go along with it
 Ex: AbstractMap<K,V>, AbstractList<E>, etc. (many)
Item 19: Use interfaces only to de?ne types
 ?interfaces should be only used to de?ne                         mixin type
 ?avoid designing constant interfaces
Why?
  -> you are entering into a client commitment
  -> pollutes inheritance hierarchy for namespaces

  // DONT DO THIS
  // CONSTANT INTERFACE
  package edu.ej.ch14;
  public interface Interface1{
  	    static String NAME_PREFIX = "_";
  }

  //CLASS IMPLEMENTING INTERFACE
  public class Class1 implements Interface1 {
  	    @Override
  	    public String toString() {
  	    	    return NAME_PREFIX + Class1.class.getName();
  	    }
  }

  // A TEST HELPER
  class Tester1 {
  	    public static void main(String[] args) {
  	    	    Class1 clazz1 = new Class1();
  	    	    System.out.printf("Class1#toString: %1$s", clazz1.toString());
  	    }
  }

  // OUT PUT
  Class1#toString: _edu.ej.ch14.Class1
Contd...
JDK violators?
   java.io.ObjectStreamConstants

What   to do with constants?
  ->   use enum type constants
  ->   use helper constant classes
  ->   you can use ¡®static import¡¯ to avoid name quali?cations

JDK followers?
   java.lang.Integer, java.lang.Double, etc.
Item 20: Prefer class hierarchies to tagged
                  classes
?they   provide a multi datatype bene?t
Contd...
?kinda verbose, error-prone, inef?cient, and may violate inheritance
?limits the use of type detectors (¡®instanceof¡¯/¡®isassignablefrom¡¯)
?a simple ?x can be replacing tagged class with class hierarchy as:
// Class hierarchy replacement for a tagged class
abstract class Figure {
	    abstract double area();
}

class Circle extends Figure {
	    final double radius;

	   Circle(double radius) {
	   	    this.radius = radius;
	   }

	   double area() {
	   	    return Math.PI * (radius * radius);
	   }
}

class Rectangle extends Figure {
	    final double length;
	    final double width;

	   Rectangle(double length, double width) {
	   	    this.length = length;
	   	    this.width = width;
	   }

	   double area() {
	   	    return length * width;
	   }
}
Item 21: Use function objects to represent
                strategies
?function  object: an object which performs actions on other
objects using self methods
?primarily used to implement Strategy Pattern
 Strategy Pattern (GOF def):
    De?ne a family of algorithms, encapsulate each one, and make them interchangeable.
    [The] Strategy [pattern] lets the algorithm vary independently from clients that use
    it.
?help   to interchangeably operate generically
Contd...
?how     we do it?
package edu.ej.ch14.item20;

import java.io.Serializable;

// DEFINE AN INTERFACE
public interface CustomComparator<T> {
	    int compare(T arg0, T arg1);
}

class Helper{
     // STRING TYPE IMPLEMENTATION
	    private static class StringComparator implements CustomComparator<String> {
	    	    @Override
	    	    public int compare(String arg0, String arg1) {
	    	    	    // comparing lexicographically
	    	    	    return arg0.compareTo(arg1);
	    	    }
	    }

    // BYTE TYPE IMPLEMENTATION
	   private static class ByteComparator implements CustomComparator<Byte>, Serializable {
	   	    @Override
	   	    public int compare(Byte arg0, Byte arg1) {
	   	    	    return arg0.compareTo(arg1);
	   	    }
	   }

	   // CACHED IMPLEMENTATIONS WRAPPED AS INTERFACE TYPE
	   public static final CustomComparator<String> STRING_COMP= new StringComparator();
	   public static final CustomComparator<Byte> BYTE_COMP= new ByteComparator();
	
}
Contd...
              ?tester
class Tester {
	    public static void main(String[] args) {
	    	    System.out.printf("STRING result: %1$d %nBYTE result: %2$d", Helper.STRING_COMP.compare("x", "x"),
	    	    	    	    Helper.BYTE_COMP.compare(Byte.valueOf("1"), Byte.valueOf("3")));
	    }
}

// OUTPUT
STRING result: 0
BYTE result: -2 (OBSERVER THIS)




               ?how I did?
                ?de?ned an interface for strategy (comparing)
                ?created 2 separate concrete strategy implementations
                   (StringComparator, ByteComparator)
                   ?I could have done anonymous implementation, but it limits my
                   mixin types
                   ?encapsulated strategy implementations and exported as helper
                   constants to strategy type.
Item 22: Favor static member classes over non-
                     static
  ?There    are 4 types of nested classes:
   1) static member classes
   2) non-static member classes
   3) anonymous classes
   4) local classes

   What are they for?
   1) static member classes:
    ?a static class that¡¯s declared inside other class(enclosing class)
    ?has access to enclosing class¡¯s members
    ?obeys general contract as static members
    ?generally used as public helpers (recall POJO Builder pattern!)

   2) non-static member classes:
      -> each instance is associated with enclosing instance
      -> a non-modi?able association to enclosing class is established
      when member classes is created
      -> you can create instance of member class in 2 ways, a) calling
      constructor of member class from enclosing class instance
      member b)outerInstance.new InnerClass(...)
Contd...
2) non-static member classes (contd...):
   -> commonly used as Adaptors for enclosing class
    Ex: java.util.Map.values()
   -> member class instance always requires an enclosing class
   instance
   -> it forces you to allocate enclosing class instance even if you
   do not need it!
   -> always prefer static member classes incase you do not have
   to access instance members!

3) anonymous classes:
   -> has no name
   -> declared and instantiated at point of use
   -> limits your type checking capabilities
   -> clients can not invoke any functions
   -> can not support multiple types
   -> generally used to create function objects, process objects,
   within static factories
   Ex: new Comparator(compare()...omitted)
Contd...
4) local classes:
    -> same as local variables in terms of place and rules
    -> ideally, should be kept under fewer lines
    -> creates instances that are tied to enclosing class
have fun

More Related Content

Ej Chpt#4 Final

  • 1. Effective Java (Second Edition) CHAPTER 4: Classes and Interfaces presented by Chandan Benjaram
  • 2. Agenda Item 13: Minimize the accessibility of classes and members Item 14: In public classes, use accessor methods, not public ?elds Item 15: Minimize mutability Item 16: Favor composition over inheritance Item 17: Design and document for inheritance or else prohibit it Item 18: Prefer interfaces to abstract classes Item 19: Use interfaces only to de?ne types Item 20: Prefer class hierarchies to tagged classes Item 21: Use function objects to represent strategies Item 22: Favor static member classes over non-static
  • 3. Item-13: Minimize the accessibility of classes and members A well designed API should hide all of its implementation details(a.k.a, internals) and thus component inter-communication should happen through a well declared API standards (protocols). Thus in general, it should encourage highest possible cohesion and loose coupling, if any! Point-I: Make each class member as inaccessible as possible How you do it? ?use package private/public on top-outer classes ?use access modi?ers for members (private, package private, protected, public) Leaks? ?security can be leaked if class implements ¡®Serializable¡¯ Fix: ?use ¡®transient¡¯ keyword
  • 4. Point-II: Instance ?elds should never be public Problem: //Potential security hole! public static ?nal Type[] VALUES = { ... }; Fix: private static ?nal Type[] PRIVATE_VALUES = { ... }; public static ?nal List VALUES = Collections.unmodi?ableList(Arrays.asList(PRIVATE_VALUES)); Point-III: Public classes should not contain any public ?elds with the exception of immutable public static ?nal ?elds
  • 5. Item-14: Public classes should encourage use of accessors/mutators instead of public ?elds ?if a class is accessible outside its package, provide accessors ?incase of package private/private nested classes, it is OK to expose ?elds through ¡®public¡¯ access modi?ers
  • 6. Item-15: Minimize mutability What is immutable class? ?its a, very simple to write, class whose instance can not be modi?ed once initialized ?maintains a single state across all calls, thus thread safe by default How to make a class immutable? ?avoid mutators (use functional approach instead!) ?make it non-extendable ?make all ?elds ?nal ?make all ?elds private ?ensure exclusive access to any mutators, if any Ex: Use defensive copying techniques, readObject, etc. Note: beware of nested classes! (possible security hole)
  • 7. Advantages of immutable classes: ?each object belongs to a single state avoiding any complex state transformations ?by default, they are thread-safe. thus no synchronization needed ?effective pooling, caching can be performed with the aid of different techniques and patterns Ex: Factory pattern. Suggestion: ?never provide a copy constructor/clone methods (String.copy() violates) Disadvantages: ?each distinct value object requires its own object increasing memory footprint and GC demand ?problem becomes more worse when working with complicated multistage operations on large objects
  • 8. Solution: ?memory footprint and GC demand problem can be limited by sharing class self internals. Ex: BigInteger (signum-magnitude) public BigInteger negate() Returns a BigInteger whose value is (-this). ?nicely designed public companion classes can handle multistage operations problem very smoothly Ex: StringBuilder for immutable class, String ?nally: ?classes should be immutable unless there is a precise reason to make mutable ?make every ?eld as ?nal unless there is a precise reason to avoid ?fully initialize object with all its required invariants either using constructor/static factories but not with any public helpers Hint: Builder pattern can save your life!
  • 9. Item-16: Favor Composition over Inheritance But, why? ?violates encapsulation ?parent private ?elds can not be accessible if needed! Solution: ?Use Composition pattern + Forwarding Methods, which may be seen as Decorator pattern (loosely speaking!)
  • 10. but wait, there is a problem: ?it may cause wrapped object blind in viewing wrapper object. thus Callback frameworks fails to function as expected. A ¡®SELF problem¡¯.
  • 11. When to prefer inheritance then? ?if you can precisely establish a ¡®is-a¡¯ relationship between sub-class and super-class then go for it! JDK violators- Properties (is-not-a HashTable), Stack (is-not-a Vector), etc. Finally: ?read API docs thoroughly for any ?aws, violations, limitations, etc., before implementing an interface
  • 12. Item-17: Design and document for Inheritance or else prohibit it ?class must document its self-use of override-able methods ?parent private ?elds can not be accessible if needed! ?a class designed for inheritance must be reviewed thoroughly. once shipped, it would be impossible to make changes without breaking own clients ?constructors must not invoke override-able methods Example: a super class
  • 13. a subclass Finally: ?incase of no options other than self-use of override-able methods, use self speci?c code to private helpers
  • 14. Item-18: Prefer interfaces to abstract classes ?as java permits only single inheritance, a abstract class type de?nition is more constrained vs an interface de?nition ?abstract class hierarchies may cause ¡®combinatorial explosion¡¯ ?on the other hand, interfaces are ideal for mixins. thus adds more type de?nitions to primary type ?existing classes can be easily retro?tted to implement new interface ?design your interface with outmost case. once it is shipped & used, it can not be possible to change method signature or add more without breaking its clients ?preferably, provide a ¡®skeletal implementation¡¯(abstract interface) of your interface to go along with it Ex: AbstractMap<K,V>, AbstractList<E>, etc. (many)
  • 15. Item 19: Use interfaces only to de?ne types ?interfaces should be only used to de?ne mixin type ?avoid designing constant interfaces Why? -> you are entering into a client commitment -> pollutes inheritance hierarchy for namespaces // DONT DO THIS // CONSTANT INTERFACE package edu.ej.ch14; public interface Interface1{ static String NAME_PREFIX = "_"; } //CLASS IMPLEMENTING INTERFACE public class Class1 implements Interface1 { @Override public String toString() { return NAME_PREFIX + Class1.class.getName(); } } // A TEST HELPER class Tester1 { public static void main(String[] args) { Class1 clazz1 = new Class1(); System.out.printf("Class1#toString: %1$s", clazz1.toString()); } } // OUT PUT Class1#toString: _edu.ej.ch14.Class1
  • 16. Contd... JDK violators? java.io.ObjectStreamConstants What to do with constants? -> use enum type constants -> use helper constant classes -> you can use ¡®static import¡¯ to avoid name quali?cations JDK followers? java.lang.Integer, java.lang.Double, etc.
  • 17. Item 20: Prefer class hierarchies to tagged classes ?they provide a multi datatype bene?t
  • 18. Contd... ?kinda verbose, error-prone, inef?cient, and may violate inheritance ?limits the use of type detectors (¡®instanceof¡¯/¡®isassignablefrom¡¯) ?a simple ?x can be replacing tagged class with class hierarchy as: // Class hierarchy replacement for a tagged class abstract class Figure { abstract double area(); } class Circle extends Figure { final double radius; Circle(double radius) { this.radius = radius; } double area() { return Math.PI * (radius * radius); } } class Rectangle extends Figure { final double length; final double width; Rectangle(double length, double width) { this.length = length; this.width = width; } double area() { return length * width; } }
  • 19. Item 21: Use function objects to represent strategies ?function object: an object which performs actions on other objects using self methods ?primarily used to implement Strategy Pattern Strategy Pattern (GOF def): De?ne a family of algorithms, encapsulate each one, and make them interchangeable. [The] Strategy [pattern] lets the algorithm vary independently from clients that use it. ?help to interchangeably operate generically
  • 20. Contd... ?how we do it? package edu.ej.ch14.item20; import java.io.Serializable; // DEFINE AN INTERFACE public interface CustomComparator<T> { int compare(T arg0, T arg1); } class Helper{ // STRING TYPE IMPLEMENTATION private static class StringComparator implements CustomComparator<String> { @Override public int compare(String arg0, String arg1) { // comparing lexicographically return arg0.compareTo(arg1); } } // BYTE TYPE IMPLEMENTATION private static class ByteComparator implements CustomComparator<Byte>, Serializable { @Override public int compare(Byte arg0, Byte arg1) { return arg0.compareTo(arg1); } } // CACHED IMPLEMENTATIONS WRAPPED AS INTERFACE TYPE public static final CustomComparator<String> STRING_COMP= new StringComparator(); public static final CustomComparator<Byte> BYTE_COMP= new ByteComparator(); }
  • 21. Contd... ?tester class Tester { public static void main(String[] args) { System.out.printf("STRING result: %1$d %nBYTE result: %2$d", Helper.STRING_COMP.compare("x", "x"), Helper.BYTE_COMP.compare(Byte.valueOf("1"), Byte.valueOf("3"))); } } // OUTPUT STRING result: 0 BYTE result: -2 (OBSERVER THIS) ?how I did? ?de?ned an interface for strategy (comparing) ?created 2 separate concrete strategy implementations (StringComparator, ByteComparator) ?I could have done anonymous implementation, but it limits my mixin types ?encapsulated strategy implementations and exported as helper constants to strategy type.
  • 22. Item 22: Favor static member classes over non- static ?There are 4 types of nested classes: 1) static member classes 2) non-static member classes 3) anonymous classes 4) local classes What are they for? 1) static member classes: ?a static class that¡¯s declared inside other class(enclosing class) ?has access to enclosing class¡¯s members ?obeys general contract as static members ?generally used as public helpers (recall POJO Builder pattern!) 2) non-static member classes: -> each instance is associated with enclosing instance -> a non-modi?able association to enclosing class is established when member classes is created -> you can create instance of member class in 2 ways, a) calling constructor of member class from enclosing class instance member b)outerInstance.new InnerClass(...)
  • 23. Contd... 2) non-static member classes (contd...): -> commonly used as Adaptors for enclosing class Ex: java.util.Map.values() -> member class instance always requires an enclosing class instance -> it forces you to allocate enclosing class instance even if you do not need it! -> always prefer static member classes incase you do not have to access instance members! 3) anonymous classes: -> has no name -> declared and instantiated at point of use -> limits your type checking capabilities -> clients can not invoke any functions -> can not support multiple types -> generally used to create function objects, process objects, within static factories Ex: new Comparator(compare()...omitted)
  • 24. Contd... 4) local classes: -> same as local variables in terms of place and rules -> ideally, should be kept under fewer lines -> creates instances that are tied to enclosing class