Skip to content

Instantly share code, notes, and snippets.

@scarecrow1123
Last active January 29, 2017 18:05
Show Gist options
  • Save scarecrow1123/8859119510250e5c53cfc6de629eca2d to your computer and use it in GitHub Desktop.
Save scarecrow1123/8859119510250e5c53cfc6de629eca2d to your computer and use it in GitHub Desktop.
Notes from Effective Java by Joshua Bloch aka jDheivam!

Classes

Reduce accessbility

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.
Reduce mutability

Totally! ######Steps for creating Immutable Classes

  1. Make the class final so that subclassing is not possible (the author says subclassing is possible in other ways - find how?)
  2. Make all fields private
  3. Make all fields final
  4. Do not provide methods that can modify the state
  5. Do not provide any kind of access to fields that references mutable objects
Function pointers, lambda esque in Java - (well atleast before Java8)
  • 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();
      }
    });
Inner and Nested classes:

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.

Methods

Defensive copies

Even if a member field of a class is made final, if the type of the field is mutable, it is still possible to edit the field as shown in the following example:

  public class Period {
    private final Date start;
    private final Date end;
    
    public Period (Date start, Date end) {
      this.start = start;
      this.end = end
    }
    
    public Date start() {
      return this.start;
    }
    
    public Date end() {
      return this.end
    }
  }

start and end are declared as final in Period class, but Date is mutable. Hence a non final reference can be passed to instantiate Period and the passed reference can be modified by the host class to change the state of Period even though the implementation doesn't intend to do so.

public class ExploitPeriod {
  public static void exploit() {
    Date start = new Date();
    Date end = new Date();
    Period p = new Period(start, end):
    start.setYear(383); //Oops!
  }
}
This could be overcome by copying the incoming parameters in the constructor of `Period` which the author calls _defensive copy_.
public class Period {
  private final Date start;
  private final Date end;

  public Period(Date start, Date end) {
    this.start = new Date(start.getTime());
    this.end = new Date(end.getTime());
  }
}

There again is a problem because of the accessors, which return mutable references of internal fields. Make them reuturn copies so that the returned references cannot be used to exploit the internal states.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment