使用静态工厂方法代替构造器
优点
可以返回原类型的子类型,使用放无感知,可以直接在工厂方法中切换具体实现。工厂方法可以空值返回对象方式:单例 or 多实例 or 其他。工厂方法有名称,可以知道对象是用来做什么的。静态工厂方法所返回的对象可以随着传递的参数而发生变化。方法返回对象所属的类在编写包括该静态工厂方法的类时可以不存在缺点
类如果不含有公有/受保护的构造器,就不能被子例化。工厂方法难以被发现。工厂方法惯用名称
from:类型转换,单个参数,返回一个对应类型的实例。of:聚合方法,多个参数,返回该类型的一个实例,把参数合并起来,如:Lists.of(“A”,“B”,“C”)。valueOf:类型转换getInstance:返回实例时通过参数来描述的,但不能说与参数具有同样的值。newInstance:和getInstance类似,但是能够保证每次返回的是新的实例。如果构造器参数很多,其中少数是必传参数,多数是可选参数,考虑使用构建器模式。
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder {
// 必要参数
private final int servingSize;
private final int servings;
// 可选参数
private int calories = 0;
private int fat = 0;
private int sodium = 0;
private int carbohydrate = 0;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val) {
calories = val;
return this;
}
public Builder fat(int val) {
fat = val;
return this;
}
public Builder soduim(int val) {
sodium = val;
return this;
}
public Builder carbohydrate(int val) {
carbohydrate = val;
return this;
}
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
public NutritionFacts(Builder builder) {
servings = builder.servings;
servingSize = builder.servingSize;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
public static void main(String[] args) {
NutritionFacts facts = new NutritionFacts.Builder(10, 10).calories(10).fat(20).build();
}
}
对于单例属性,使用私有构造器或者使用枚举。
通过私有构造器来表明类不可被实例化。
使用依赖注入来引入资源(spring框架)。
避免创建不必要的对象。
局部变量尽量使用基本类型。
POJO中尽量使用装箱类型,防止序列化报错。
对于创建后不会被修改的类,后续只需服用无需创建,如Pattern。
消除过期的对象引用。
如果对象内部自己管理了内存,那么对象需要警惕及时消除过期引用,防止内存泄漏问题,如ArrayList内部管理着数据数组。
让类实现AutoCloseable接口可以在客户端不在需要该实例的时候调用close方法关闭资源,可以使用try-with-resources来保证这一点。
try-with-resources优先于try-finally。
equals方法需要满足:自反性,对称性,传递性,一致性。
覆盖equals时一定要覆盖hashcode方法。
如果俩个对象用equals方法比较是相等的,那么他们的hashcode返回值必须是相等的。
如果俩个对象equals方法比较是不相等的,那么对hashcode的返回值无要求。
始终覆盖对象的toString方法,便于调试。
当设计一个排序敏感的类时,要考虑让该类实现Comparable接口。
使类和成员的可访问性最小化,能私有就私有。
当外界需要获取类的公有域时,提供访问方法,否则后续将无法更改该公有域的实现方式。
使可变性最小,尝试设计不可变类。
复合优先于继承。
继承打破了封装性,子类和父类会互相影响。
只有is-a关系才能使用继承。
对于其他关系,在新的类中增加一个私有域,将其引用现有类的一个实例即可。(Decorator模式)。
要么设计继承并提供文档说明,要么禁止继承。
接口优于抽象类。
现有的类可以很容易实现新的接口。
接口是定义混合类型的理想选择。
接口允许构造非层次结构的类型框架。
接口使得安全地增强类功能成为可能。
为后代设计接口,因为接口设计完之后很难变更。
接口只用于定义类型。
静态成员类优先于非静态成员类
非静态成员类会保留一个指向外围对象的引用,导致外围对象无法被回收等,如果成员类不要求访问外围实例,就要始终声明为static。
用枚举代替int常量。
用实例域代替序数。
坚持使用overwrite注解。
用标记接口定义类型,如Serializable。
lambda优先于匿名类。
尽量删除lambda参数中的类型。
方法引用优先于lambda。
坚持使用标准的函数接口。
避免滥用stream,stream的操作尽量保持简单。
优先选择stream中无副作用的函数。
返回0长度的数组或者集合,而不是null。
永远不要通过返回Optional的方法返回null。
将局部变量作用域最小化。
避免使用float和double,改为使用BigDecimal。
字符串应当尽早转换为实际的类型。
不到万不得已,不要进行优化。