对象 Effective java

57 阅读4分钟

//静态工厂方法代替构造器
//优势: 1.有名称 2.不用每次调用都创建新的对象 3.可以返回原返回类型的任何子类型对象
//4. 返回的对象可以随着每次调用而发生变化 取决于静态方法的参数值
//5. 方法返回的对象所属的类 在编写该静态工厂方法的类时可以不存在
//缺点: 1.类不含公有或受保护的构造器 就不能被子类化 鼓励使用复合而不是继承(不可变类) 2.很难被程序员发现

public static Boolean valueOf(boolean b){  
    return b?Boolean.TRUE:Boolean.FALSE;  
}  
//惯用名称  
public void test(){  
    Instant instant = null;  
    Date d=Date.from(instant);  

}
//遇到多个构造器参数时要考虑使用构造器
//参数较多时 重叠构造器可行 但是难编写难阅读
// 替代方案: 调用无参构造函数创建对象 再使用setter方法 JavaBeans模式 缺点:构造过程中JavaBean可能状态不一致 把类做成不可变的可能性不复存在
//第三种方式: 建造者模式---不直接生成想要的对象,让客户端利用所有必要的参数调用构造器(或静态工厂)得到一个builder对象 在builder对象上调用类似setter对象的方法
// 设置每个相关的可选参数 最后调用无参的build方法生成不可变的对象模拟了具名的可选参数
//建造者模式也适用于类层次结构

public class NutritionFacts{  
    private final int servingSize;  
    private final int servings;  
    private final int fat;  
  
    private final int sodium;  
  
  
    public static class Builder{  
        private final int servingSize;  
        private final int servings;  
  
        private int fat=0;  
        private int sodium=0;  
        public Builder(int servingSize,int servings){  
            this.servings=servings;  
            this.servingSize=servingSize;  
        }  
    public Builder fat(int val){  
        this.fat=val;  
        return this;  
        }  
    public Builder sodium(int val){  
        this.sodium=val;  
        return this;  
        }  
    public NutritionFacts build(){  
        return new NutritionFacts(this);  
}  
  
}  
    private NutritionFacts(Builder builder){  
        servingSize=builder.servingSize;  
        servings=builder.servings;  
        fat=builder.fat;  
        sodium=builder.sodium;  
    }  
}  
  
    public static void main(String[] args) {  
        NutritionFacts cocaCola=new NutritionFacts.Builder(240,8).sodium(10).fat(1).build();  
}  
  
//用私有构造器或枚举 强化Singleton属性 (仅被实例化一次的类)  
public class Elvis{  
private static final Elvis INSTANCE=new Elvis();  
private Elvis(){}  
public static Elvis getInstance(return INSTANCE;);  
//可序列化 防止序列化创创建新的对象  
  
private java.lang.Object readResolve(){  
return INSTANCE;  
}  
}  
//氮元素的枚举类型 实现单例化的最佳方法  
public enum Elvis{  
INSTANCE;  
}  
  

//通过私有构造器强化不可实例的能力 减少没意义的实例化的损耗
//做成抽象类是不可以的 可以被子类化然后子类可以被实例化
//让类包含一个私有构造器 它就不能被实例化了

public class UtilityClass{  
    private UtilityClass(){  
    throw new AssertionError();  
    }  
}  

//优先考虑依赖注入来引用资源 静态工具类和Singleton 不适合需要引用底层资源的类
//使用依赖注入: 当创建一个新的实例时,就将该资源传到构造器中

public class SpellChecker{  
    private final Lexicon dictionary;  
  
    private SpellChecker(Lexicon dictionary){  
        this.dictionary= Objects.requireNonNull(dictionary);  
}  
}  

//避免创建不必要的对象

//反面例子
String s=new String("aaa");

//优先使用静态工厂而不是构造器 避免创建不必要的对象
//对于复杂重复使用的对象 将其进行缓存

public class RomanNumerals{  
    private static final Pattern ROMAN=Pattern.compile("...");  
  
    static boolean isRomanNumeral(String s){  
        return ROMAN.matcher(s).matches();  
}  
}  

//优先使用基本类型而不是装箱基本类型 当心无意义的自动装箱

//消除过期的对象引用
//举例 一个栈对象 设置 当满了就把容量 *2 ,但是一个栈先增长再收缩 从栈中弹出来的对象就不会被回收 栈内部维护了其过期引用 导致内存泄露
//解决方法:一旦引用对象过期,就立即清空这些引用

public Objects pop(){  
    Objects result=elements[--size];  
    elements[size]=null;  
    return result;  
}  

//避免使用终结方法和清除方法
//注重时间的任务不应该由终结方法或者清除方法来实现 例如 关闭一个打开的文件
//终结方法和清除方法的合法途径: 1.当资源所有者忘记close时,终结或者清除方法可以充当 安全网
//2.处理本地对等体 (非Java对象)

//try-with-resource 优先于 try-finally

static String firstLineOfFile(String path) throws FileNotFoundException {  
    try(BufferedReader br=new BufferedReader(  
    new FileReader(path);  
))  
}