[Read Effective Java] Chapter 2 Item 1 "Consider static factory methods instead of constructors"

Introduction

If you want to deepen your understanding of Java, read this, so I will read Effective Java while interpreting it in my own way. I am reading the second edition that I was reading. https://www.amazon.co.jp/EFFECTIVE-JAVA-Java-Joshua-Bloch/dp/4621066056/ref=pd_sbs_14_3/355-5139262-7829161?_encoding=UTF8&pd_rd_i=4621066056&pd_rd_r=ac861412-beae-43a8-872a-8b853aa69980&pd_rd_w=oIuWA&pd_rd_wg=nhmjU&pf_rd_p=7642417c-6494-4d06-a2b0-fcb0e0b3c563&pf_rd_r=HAEC02ASTQVJ4SPSM92Q&psc=1&refRID=HAEC02ASTQVJ4SPSM92Q

Consider static factory methods instead of constructors

I'm wondering if there are various things that make me happy if I replace the processing that was implemented using the constructor with a static factory method.

Sample code

Example 1



public static Boolean valueOf(boolean b){
    return b ? Boolean.TRUE : Boolean.FALSE;
}

Example 2



//Service provider framework
public interface Service{
    //Service-specific methods here
}

//Service provider interface
public interface Provider{
    Service newService();
}

//Non-instantiable class for service registration and access
public class Service{
    private Service(){} //Suppress instantiation (item 4)

    //Associate service name with service
    private static final Map<String, Provider> providers = new ConcurrentHashMap<String, Provider>();
    public static final String DEFAULT_PROVIDER_NAME = "<def>";

    //Provider registration API
    public static void registerDefaultProvider(Provider p){
        registerProvider(DEFAULT_PROVIDER_NAME,p);
    }
    public static void registerProvider(String name,Provider p){
        providers.put(name,p);
    }

    //Service access API
    public static Service newInstance(){
        return newInstance(DEFAULT_PROVIDER_NAME);
    }
    public static Service newInstance(String name){
        Provider p = providers.get(name);
        if (p == null)
            throw new IllegalArgumentException(
                    "Nn provider registered with name:" + name
            );
        return p.newService();
    }
    
}

Glossary

constructor

-Constructor is the process that is executed when creating an instance of a class.

SampleClass instanceA = new SampleClass();

↑ The description of SampleClass () after new is the call to the constructor.

-How to write the constructor: Make it the same as the class name


public class SampleClass {
  //constructor
  public SampleClass(){
    System.out.println("It's a constructor");
  }
}

↑ When new is done with this, "It's a constructor" is output as standard.

-Unlike methods, constructors do not return values (writing return will result in an error)

static -Modifiers for creating instance-independent methods and variables

static factory method

-A static factory method is just a static method that returns an object. -In Example 1, boolean basic data value (b) is converted to a Boolean object.

Factory method of design pattern

-Similar names but different from static factory methods ・ Explanation is omitted here

interface

-An interface is a description of a "variable" or "method type" without writing the specific processing of the method in the class. -The condition is that "all methods are abstract methods" and "basically they do not have any fields". -Since the processing content is not specifically written, it is only necessary to implement the processing content when you want to use it, which is convenient when processing changes may occur in the future (details can be postponed).

4 advantages and 2 disadvantages of static factory method

Advantage 1 Has a name unlike the constructor

-The constructor will be executed without permission when new, but if it is a static factory method, it will be given a nice name, so readability will improve.

For example, suppose there is a process that returns a BigInteger that is a probable prime.

-How to write in the constructor

BigInteger(int, int, Random)

-How to write with static factory method

BigInteger.probablePrime

… Which one is easier to understand?

Advantage 2 Unlike the constructor, there is no need to create a new object each time a method is called.

・ It's natural, but since it's static, it's not instantiated into anything. Must be new to call the constructor ・ It's not so good to create a lot of new objects unnecessarily.

Advantage 3 Unlike the constructor, it can return an object of any subtype of the return value type of the method.

-The constructor does not return a return value, but the static factory method is just a method, so it can be returned, so it is flexible. ・ A service provider framework like Example 2 (hiding the contents and using it as an API) will also be created.

Pros 4 Reduces the hassle of instantiating parameterized types

・ Redundant writing can be simplified For example, in the case of a constructor, what I had to write like this

Map<String, List<String>> m =
  new HashMap<String, List<String>>();

You can write this as a static factory method

Map<String, List<String>> m = HashMap.newInstance();

It ’s simple, is n’t it?

Of course, behind the scenes, the static factory method is implemented like this

public static <K, V> HashMap<K, V> newInstance() {
  return new HashMap<K. V>;
}

Disadvantage 1 Cannot create a subclass of a class that does not have a public or protected constructor

Disadvantage 2 They are not easily distinguishable from other static methods

-Unlike the constructor, Javadoc does not recognize it well

Common name for static factory method

name role
valueOf Returns an instance with the same value as the parameter. It is essentially a type conversion method.
of Alternative to valueOf. A more concise one.
getInstance Returns the instance specified by the parameter, but does not have the same value. For singletons, getInstance takes no arguments and returns its only instance.
newInstance Similar to getInstance, except that the individual instances returned by newInstance are all separate instances.
getType Similar to getInstance, but used when the factory method is in a different class than the target class. Type indicates the type of object returned by the factory method.
newType Similar to newInstance, but used when the factory method is in a different class than the target class. Type indicates the type of the object returned by the factory method.

Continue

[Read Effective Java] Chapter 2 Item 2 "Consider a builder when faced with a large number of constructor parameters" https://qiita.com/Natsukii/items/eb8fec0d8cae567f6647

Recommended Posts

[Read Effective Java] Chapter 2 Item 1 "Consider static factory methods instead of constructors"
[Read Effective Java] Chapter 2 Item 7 "Avoid Finalizers"
[Read Effective Java] Chapter 2 Item 5 "Avoid the creation of unnecessary objects"
[Read Effective Java] Chapter 3 Item 10 "Always Override toString"
[Read Effective Java] Chapter 2 Item 2 "Consider a builder when faced with a large number of constructor parameters"
[Read Effective Java] Chapter 2 Item 6 "Remove obsolete object references"
Effective Java 3rd Edition Chapter 8 Methods
[Read Effective Java] Chapter 2 Item 4 "Force uninstantiation with a private constructor"
[Read Effective Java] Chapter 3 Item 9 "When overriding equals, always override hashCode"
[Read Effective Java] Chapter 3 Item 8 "When overriding equals, follow the general contract"
Effective Java Chapter 2
Item 90: Consider serialization proxies instead of serialized instances
Effective Java Chapter 6 34-35
Method name of static factory method learned from Java 8
Effective Java Chapter 4 15-22
Effective Java Chapter 3
[Read Effective Java] Chapter 2 Item 3 "Force singleton characteristics with private constructor or enum type"
Effective Java 3rd Edition Chapter 3 Methods Common to All Objects
[Java] Classes, constructors, static members
Benefits of Java static method