代码规范 第一条:考虑用静态工厂方法代替构造器 原因:静态工厂方法第一大优势它们有名称,第二大优势,不必在每次调用时都创建一个新对象, 第三优势可以返回原返回类型的任何子类型的对象。 (冷不丁的想用枚举来做静态工厂实现) 第四优势在创建参数化类型实例的时候,他们使得代码变得更加简洁。 缺点当然也有:一:类如果不含共有或者受保护的构造器就不能被子类化,二:与其他静态方法没有区别。 遵守命名习惯可以弥补这一劣势,比如newtype创建新对象,gettype获取对象 所以,一般一个静态工厂方法需要有详细的注释,遵守标准的命名, 如使用getInstance、valueOf、newInstance等方法名;
第二条:遇到多个构造器参数时要考虑用构造器 第一中构造就是常见的重叠构造器,一个构造器中this(xxx)调用同名构造器,但是参数过多就容易懵了, 可以使用无参模式,build生成不可变对象。
第三条:用私有构造器或枚举类型强化Singleton属性(单例模式)
第四条:通过私有构造器强化不可实例化的能力
第五条:避免创建不必要的对象,重用不可变对象 小心自动拆装箱,要优先使用基本类型而不是装箱基本类型,要当心无意识的自动装箱。
第6条:消除过期对象的引用:下面例子引用了arraylist的remove方法, 如果没有将元素置为null的话,就会随着垃圾回收器活动的增加,或者由于内存占用不断增加,程序性能降低会逐渐表现出来。 public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work return oldValue; }
内存泄漏的另外一个常见来源是缓存,一旦你把对象引用放到缓存中,
它就很容易被遗忘掉,从而使得它不再有用之后很长时间都保留在缓存之中
如果你需要这样的缓存那么可以使用这个WeakHashMap,当缓存过期之后就会自动删除。
// 初始化3个“弱键”String w1 = new String("one");String w2 = new String("two");String w3 = new String("three");// 新建WeakHashMapMap wmap = new WeakHashMap();// 添加键值对wmap.put(w1, "w1");wmap.put(w2, "w2");wmap.put(w3, "w3");// 打印出wmap// ---- 测试 WeakHashMap 的自动回收特性 ----// 将w1设置null。// 这意味着“弱键”w1再没有被其它对象引用,调用gc时会回收WeakHashMap中与“w1”对应的键值对w1 = null;// 内存回收。这里,会回收WeakHashMap中与“w1”对应的键值对System.gc();System.out.println(wmap.toString());System.out.println(wmap.size());=========================================================================={three=w3, two=w2} 2
第七条:避免使用终结方法:首先需要强调:终结方法通常是不可预测的,也是很危险的, 一般情况下是不必要的。使用终结方法会导致行为不稳定,降低性能,以及可移植性问题
第八条:覆盖equals时请遵守通用约定,equals方法实现了等价关系,自反性,对称性,传递性,一致性。
第九条:覆盖equals时总要覆盖hashCode
第十条:始终覆盖toString
第十一条:谨慎覆盖clone
第十二条:考虑实现Comparable接口,一旦类实现此接口就可以和许多泛型算法以及依赖于该接口的集合实现进行协作。比如按照字母排序,按照数值顺序或年代顺序。
第十三条:使类和成员的可访问性最小化。一个模块不需要知道其他模块的内部工作情况,这个概念称为信息隐藏或封装。
第十四条:在公有类中使用访问方法而非公有域(就是私有参数增加公开getset方法)
第十五条:使可变性最小化 要实现不可变的类需要满足一下几点要求: 1、不要提供任何会修改对象状态的方法。(setter方法) 2、保证类不会被扩展。用final修饰类或者是私有化构造器提供公有静态工厂方法。 3、使所有的域都是final的。 4、使所有的域都成为私有的。 5、确保对于任何可变组件的互斥访问。 如果类具有指向可变对象的域,则必须确保该类的客户端无法获得指向这些对象的引用。 并且,永远不要用客户端提供的对象引用来初始化这样的域, 也不要从任何访问方法中返回该对象的引用。在构造器、访问方法和readObject中请使用保护性拷贝。 不可变对象本质上是线程安全的,他们不会要求同步。
第十六条:复合优先于继承,继承打破了封装性, 子类依赖于超类的特定功能实现细节,超类可能会随着版本不同发生变化,子类也要跟着更新而演变。
第十七条:要么为继承而设计,并提供文档说明,要么就禁止继承。 1.文档必须精确描述覆盖每个方法所带来的影响。 2.为了允许继承,类还必须遵守 其他一些约束,构造器绝不能调用可被覆盖的方法。不论直接还是间接。 两种方法禁止子类化:类声明为final,另一种所有构造变成私有,或者包级私有,并增加一些共有静态工厂来代替构造器。
第十八条:接口优于抽象类。 1.现有的类可以很容易被更新,以实现新的接口。 2接口是定义混合类型的理想选择。 3.接口允许我们构造 非层次结构的类型框架。
第十九条:接口只用于定义类型。 1.当类实现接口时,接口就充当引用这个实例的类型。 有一种接口被称为常量接口,如果有非final的类实现了常量接口, 它的所有子类命名空间也会被接口常量所污染。
第二十条:类层次优先于标签类。
第二十一条:用函数对象表示策略。
第二十二条:优先考虑静态成员类 嵌套类是指被定义在另一个类的内部的类。 嵌套类存在的目的应该只是为了它的外围类提供服务。如果嵌套类将来有可能会用于其他的某个环境,它就应该是顶层类。 嵌套类有四种:静态成员类,非静态成员类,匿名类,局部类。除了第一种,其他三种称为内部类。 静态成员类是最简单的一种嵌套类。最好把它看做是普通的类,只是碰巧被声明在另一个类的内部而已。 从语法上来讲,静态成员类和非静态成员类之间唯一的区别是,静态成员类的声明中包含修饰符static。但是静态成员类和非静态成员类之间有 很大不同。非静态成员类的实例方法内部,可以调用外围类实例(宿主)的方法,或者利用修饰过的this构造获得外围类实例(宿主)的引用。 静态成员类的实例可以独立于它的外围类的实例之外独立存在。 非静态成员类的实例不能独立于它的外围类的实例(宿主)独立存在。 当非静态成员类的实例被创建的时候,它和外围实例之间的关联关系也随之被建立起来,而且这种关联关系以后不能被修改。通常情况下, 当在外围类的某个实例方法的内部调用非静态成员类的构造器时,这种关联关系被自动建立起来。 如果声明成员类不需要访问外围实例,就始终要把static修饰符放在它的声明中。 匿名类不同于Java语言中的其他任何语法单元。匿名内部类没有名字,它不是外围类的一个成员,它并不与其他的成员一起被声明,而是在 使用的同时被声明和实例化。匿名类可以出现在代码中任何允许存在表达式的地方。匿名类的适用性受到诸多的限制。除了在它们被声明的时候 之外,是无法将它们实例化的。你无法声明一个匿名类来实现多个接口,或者继承一个类。匿名类的客户端无法调用这个匿名类中的任何方法。 由于匿名类出现在表达式中,它们,它们必须保持简短-----大约10行或者更少些------否则会影响程序的可读性。 匿名类的一种常用用法是动态的创建 函数对象。 匿名类的另一种常见用法是创建 过程对象。
第二十三条:请不要在新代码中使用原生态类型。
来源:https://www.cnblogs.com/q1359720840/p/10500394.html