Effective Java By Joshua Bloch: Item1 - Static Fac

2019-01-21 09:37发布

问题:

I am reading the Effective Java by Joshua Bloch and I have question about Item1 Static Factory Method.

Quote[Bloch, p.7]

Interfaces cant have static methods, so by convention, static factory methods for an interface named Type are put in non-instantiable class named Types. For example, the Java Collections Framework, provide unmodifiable collections, synchronized collections, and the like. Nearly all of these implementations are export via static factory methods in one noninstantiable class (java.util.Collections). The classes of the returned objects are all non-public.

Ok. When look at the sources code, I see java.util.Collection interface and java.util.Collections class with private constructor (non-instantiable class). and I see that the non-instantiable class Collections has all static methods, just like what Bloch said. But i fail to see the connection between the two classes as Bloch said

Interfaces cant have static methods, so by convention, static factory methods for an interface named Type are put in non-instantiable class named Types.

  1. Can anyone point out the obvious to me?

  2. what is it mean when he said

The classes of the returned objects are all non-public

Here is where I obtain the java sources: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Collection.java?av=f

回答1:

  1. Interfaces cant have static methods, so by convention, static factory methods for an interface named Type are put in non-instantiable class named Types.

    The point is just the plural 's' on "Type[s]". So if your interface is called Foo and you want to create some implementation called MyFoo then your factory with the methods to instantiate should be called Foos by convention.

  2. The classes of the returned objects are all non-public

    This means that the classes of objects returned from the factory methods have a private or default visibility modifier as in private class MyFoo{} so that they can not be instantiated by any other means but their factory methods. Since you can't construct an Object using the new operator from private inner or package private class out of their scope (reflection aside).

e.g.:

 public interface Foo{ //interface without plural 's' (question 1)
     public void bar();
 }
 public abstract class Foos(){ // abstract factory with plural 's' (question 1)
    public static Foo createFoo(){
        return new MyFoo();
    }
    private class MyFoo implements Foo{ // a non visible implementation (question 2)
       public void bar(){}
    }
 }


回答2:

Let's say you have an interface called List and you want to use the static factory method to create different type of lists. You cannot define the static factory methods in the List interface because it's an interface. So what you have to do it have a class that return instances of classes that implement List

public class ListFactory{
  private ListFactory(){}
  public static List makeArrayList(){...}
  public static List makeLinkedList(){...}
  public static List makeCrazyList(){...}
}

You cannot do this

public interface List{
   public static List makeArrayList();
   public static List makeLinkedList();
   public static List makeCrazyList();
}

Since List is interface.



回答3:

So take for example Collections.unmodifiableList(...). It returns some implementation of List. But the implementation class's name is irrelevant. Furthermore, said class is only constructed through the static factory method.



回答4:

public interface Foo
    static public class Factory
        public Foo create(){..}

Foo foo = Foo.Factory.create();


回答5:

1) I don't understand your question here. Collection is the interface and Collections has some factory methods like emptyList

2) E.g the List instance that is returned by Collection.emptyList is an instance of a private class that implements the List interface.



回答6:

It simply means that the return type of the static factory methods in Collections (and other classes like it) are interface types (e.g. List) rather than specific implementation classes (e.g. java.util.Collections.UnmodifiableList), which are not visible to users since that would just complicate things and increase the size of the API.