如果参数很多,会导致构造方法非常多,拓展性差,代码难编写,且难以看懂。 用 JavaBeans 模式,get 和 set 一行构造编程多行代码实现,需要使用额外机制确保一致性和线程安全。
用 builder 模式:1、5 个或者 5 个以上的成员变量 2、参数不多,但是在未来,参数会增加。
如,一些工具类提供的都是静态方法,这些类是不应该提供具体的实例的。可以参考 JDK 中的 Arrays。
好处:防止使用者 new 出多个实例。
finalizer 方法,jdk 不能保证何时执行,也不能保证一定会执行。如果有确实要释放的资源应该用 try/finally。
模块对外部其他模块来说,隐藏其内部数据和其他实现细节——封装 编写程序和设计架构,最重要的目标之一就是模块之间的解耦。使类和成员的可访问性最小化无疑是有效的途径之一。 类似于微服务。
尽量使类不可变,不可变的类比可变的类更加易于设计、实现和使用,而且更不容易出错,更安全。 常用的手段:
不提供任何可以修改对象状态的方法;
使所有的域都是 final 的。
使所有的域都是私有的。
使用写时复制机制。
继承容易破坏封装性,而且会使子类的实现依赖于父类。
复合则是在类中增加一个私有域,引用类的一个实例,这样的话就避免了依赖类的具体实现。
例如在hashset中继承它,实现一个count方法,在add、addAll时对count进行增加操作,会出现问题。
接口只有方法申明,抽象类可以写方法的实现。
java 是个单继承的(不能继承多个抽象类),但是类允许实现多个接口。 所以当发生业务变化时,新增接口,实现接口只需要新曾接口即可。但是抽象类有可能导致不需要变化的类也不得不实现新增的业务方法。
JDK 源码中常用的一种设计方法:定义一个接口,声明一个抽象的骨架类实现接口,骨架类类实现通用的方法,而实际的业务类可以同时实现接口又继承 骨架类,也可以只实现接口。
如 HashSet 实现了 implements Set 接口 但是又 extends 类 AbstractSet,而 AbstractSet 本身也实现了 Set 接口。其他如 Map,List 都是这样的设计的。
可变参数是允许传 0 个参数的
如果是参数个数在 1~多个之间的时候,要做单独的业务控制。 具体代码不优雅。
方法的结果返回 null,会导致调用方的要单独处理为 null 的情况。返回零长度,调用方可以统一处理,如使用 foreach 即可。
JDK 中也为我们提供了 Collections.EMPTY_LIST 这样的零长度集合
声明的一个枚举本质就是一个类,每个具体的枚举值就是这个枚举类的实例。
float 和 double 在 JVM 存储的时候,有部分要做整数位,有部分要做小数位,所以存在精度上的问题,可以使用 int 或者 long 以及 BigDecimal
在存在大量字符串拼接或者大型字符串拼接的时候,尽量使用 StringBuilder 和 StringBuffer
方法过大不宜与维护