Effective Java third edition book notes (create and destroy object 1)

1. The Java language supports four types:

Reference type: class (including Enum), interface, array

Basic types

2. Method signature consists of name and all parameter types; the signed method does not contain return type

1, Create and destroy objects

Article 1. Static factory method instead of constructor

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

1. Advantages of static factory method and constructor

1) . they have names.

For example, in the following case, if we use the constructor, it is easy to confuse the two when calling the constructor.

public class Test {
    Test(int i, String s){

    }

    Test(String s, int i){

    }
}

2) . you don't have to create a new object every time you call them.

3) . they can return objects of any subtype of the original return type.

By convention, static factory methods for interface Types are placed in a non instantiated companion class called Types. For example, there are 45 tool implementations in the collection interface of the Java Collections Framework, which provide immutable collections, synchronous collections, and so on. Almost all of these implementations are exported through the class java.util.Collections. All classes that return objects are not public.

4) . the class of the returned object can change with each call. (I understand that this is actually the same as merit 3)

5) The class of the object returned by the. Method. It can not exist when writing the class containing the static factory. (I understand this is the benefit of advantage 3)

2. Disadvantages of static factory method and constructor

1) . a class cannot be subclassed if it does not contain a public or protected constructor.

2) . hard to find.

Article 2. Consider using a builder when multiple constructor parameters are encountered

The common limitation of static factories and constructors is that they do not extend well to a large number of optional parameters.

Suppose we need to represent a table of nutrients, several of which are necessary, and more than 20 optional domains, we usually adopt the pattern of overlapping constructors.

package com.example.ownlearn;

import lombok.Data;

@Data
public class Nutrition {
    //Must fill
    private final int servingSize;
    private final int servings;
    
    //Selective filling
    private final int calories;
    private final int fat;

    
    public Nutrition(int servingSize,int servings) {
        this(servingSize,servings,0,0);
    }

    public Nutrition(int servingSize, int servings, int calories){
        this(servingSize,servings,calories,0);
    }
    
    public Nutrition(int servingSize, int servings, int calories, int fat) {
        this.servingSize = servingSize;
        this.servings = servings;
        this.calories = calories;
        this.fat = fat;
    }

}

This way is feasible, but we can see that there are no construction methods that only assign values to servings ize, services, and fat. This means that we still need to call the last constructor, which leads to the need to pass values to some parameters we don't want to set. If we have a large number of parameters, this way will not be so good.

We also have the second way, JavaBean mode. We first call a constructor without parameters to create objects, and then call the setter method to assign values to each parameter. The problem with this approach is that because the construction process is divided into several calls, JavaBeans may be in inconsistent objects during the construction process, which will lead to failure.

The third way, the builder mode, can guarantee both the security like overlapping builder mode and the readability like JavaBean.

package com.example.ownlearn;

public class NutritionFact {
    //Must fill
    private final int servingSize;
    private final int servings;

    //Selective filling
    private final int calories;
    private final int fat;

    public static class Builder{
        //Must fill
        private final int servingSize;
        private final int servings;

        //Selective filling
        private final int calories = 0;
        private final int fat = 0;

        public Builder(int servingSize,int servings){
            this.servings = servings;
            this.servingSize = servingSize;
        }


        public Builder calories(int calories){
            calories = calories;
            return this;
        }

        public Builder fat(int fat){
            fat = fat;
            return this;
        }

        public NutritionFact build(){
            return new NutritionFact(this);
        }
    }

    public NutritionFact (Builder builder){
        servingSize = builder.servingSize;
        servings = builder.servings;
        calories = builder.calories;
        fat = builder.fat;
    }




}

We call it this way

NutritionFact nutritionFact = new NutritionFact.Builder(1,1).fat(1).build();

If our class is a parent class, we can do this.

package com.example.ownlearn;

import java.util.EnumSet;
import java.util.Objects;
import java.util.Set;

public class Pizza {
    public enum Topping {HAM,HUSHROOM,ONION,PEPPER,SAUSAGE}
    final Set<Topping> toppings;

    abstract static class Builder<T extends Builder<T>>{
        EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class);
        public T addTopping(Topping topping){
            toppings.add(Objects.requireNonNull(topping));
            return self();
        }

        abstract Pizza build();

        protected abstract T self();
    }

    Pizza(Builder<?>builder){
        toppings = builder.toppings.clone();
    }
}
package com.example.ownlearn;

public class Calzone extends Pizza {

    private final boolean sauceinside;

    public static class Builder extends Pizza.Builder<Builder>{

        private boolean sauceinside = false;

        public Builder sauceInside(){
            sauceinside = true;
            return this;
        }

        @Override
        Calzone build() {
            return new Calzone(this);
        }

        @Override
        protected Builder self() {
           return this;
        }
    }

    Calzone(Builder builder) {
        super(builder);
        this.sauceinside = builder.sauceinside;
    }
}

 

package com.example.ownlearn;

import java.util.Objects;

public class NyPizza extends Pizza {

    public enum  Size{SMALL}
    private final Size size;

    public static class Builder extends Pizza.Builder<Builder>{
        private final Size size;

        public Builder(Size size){
            this.size = Objects.requireNonNull(size);
        }

        @Override
        public NyPizza build() {
            return new NyPizza(this);
        }

        @Override
        protected Builder self() {
            return this;
        }
    }

    NyPizza(Builder builder) {
        super(builder);
        size = builder.size;
    }
}

 

Published 18 original articles, won praise 3, visited 6180
Private letter follow

Tags: Java Lombok

Posted on Tue, 04 Feb 2020 04:26:51 -0500 by kylebud