编写高质量代码:改善Java的151个建议五(类、对象、方法)31-51
该书籍PDF下载地址:http://download.csdn.net/download/muyeju/10001473
31.接口中不要存在实现代码
接口中不能存在实现代码(虽然可以实现,但是如果把实现代码写在接口中,那么接口就绑定了可能变化的因素,这就导致实现不在文档和可靠,是随时可能被抛弃,被修改,被重构的)
package jsontest; public class Salary { public static void main(String[] args) { B.a.doSomething(); } } interface A{ public void doSomething() ; } interface B{ public static final A a = new A() { public void doSomething() { System.out.println("---------接口中的实现方法"); } }; }
32.静态变量一定要先声明后赋值
静态变量的加载过程:静态变量是类初始化时首先被加载的,JVM会去查找类中的所有静态声明,然后分配空间,这时候只是完成了地址的分配,还没有赋值,JVM会根据类中的静态赋值(静态类赋值和静态块赋值)的先后顺序来执行。静态变量在内存中只有一个拷贝,其后的所以赋值操作都是改变其值,地址不会改变。
33.不要覆写静态方法(可以隐藏)
一个实例对象有2个类型,表面类型和实际类型,表面类型是声明时的类型,实际类型是对象产生时的类型。对于非静态方法,它是根据对象的实际类型来执行的。而对于静态方法,一方面静态方法不依赖实例对象,它是通过类名访问的;其次可以通过对象访问静态方法,如果是通过对象调用静态方法,JVM会通过对象的表面类型查找静态方法的入口。
隐藏:在子类中构建与父类相同的方法名、输入参数、输出参数、访问权限、并且父类和子类都是静态方法,此种行为叫隐藏
隐藏和覆写的区别:
1.隐藏用于静态方法,覆写用于非静态方法,隐藏没有@Override
2.隐藏的目地是抛弃父类方法,重现子类方法。而覆写则是增加或虚弱父类的行为,延续父类的职责
注:通过实例方法访问静态方法静态属性不是好习惯,给代码带来了坏问道,建议戒之
34.构造函数尽量简单
子类实例化的过程:首先初始化父类的变量,然后调用父类的构造方法,再初始化子类的变量,然后调用子类的构造方法,最后生成实例对象
35.不要在构造函数中初始化其它类
36.使用构造代码块精炼程序
构造代码块:在类中没有任何前缀和后缀,并使用{}括起来的代码片段
构造代码块会在每个构造函数内首先执行(需要注意的是:构造代码块不是在构造函数之前运行的,它依托于构造函数的执行)
使用场景:
初始化实例变量:如果每个构造函数都要初始化变量,可以通过构造代码块实现
初始化实例环境
37.构造代码块会想你所想
java编译器会把构造代码块插入到每一个构造函数中,但是如果遇到this关键字,则不插入构造代码块
38.使用静态内部类提高封装性
静态内部类:在类中的静态类就是静态内部类。
内部类:在类中的类
区别:
静态内部类只能访问外部类的静态方法和静态属性,而内部类有外部类的引用,可以自由访问
静态内部类独立于外部类存在,而内部类不能脱离外部类存在
普通内部类中,不能声明static的属性和方法,而静态内部类没有任何限制
39.使用匿名类的构造函数
匿名类的构造函数用构造函数块来代替
例:Apple a = new Apple{{}}
40.匿名类的构造函数很特殊
41.让多重继承成为现实
通过内部类实现(内部类去继承需要的类)
42.让工具类不可实例化
保证工具类只能通过类名访问,不能通过实例对象访问。(工具类里面的属性和方法都设为静态的)
要保证不能被实例化,就要将该类的构造方法设为私有,同时在抛异常。
例:
public class DatesUtil { private DatesUtil(){ throw new Error("不要实例化我,请通过类名调用") ; } }
43.避免对象的浅拷贝
类实现了Cloneable接口就具备了拷贝的能力,然后覆写clone方法就完全具备拷贝的能力
Object提供了一个对象的默认拷贝方法,即super.clone(),该方法有缺陷,是一种浅拷贝方式,它是有选择性的拷贝,规则如下:
1.基本类型只拷贝值
2.对象拷贝地址引用
3.String对象拷贝的是地址引用,但是修改值时它会从字符串池中重新生成新的字符串,原来的字符串保持不变,在此我们可以认为它是一个基本类型
44.推荐使用序列化实现对象的拷贝
类要实现序列化接口,然后调用序列化工具,SerializableUtils.deepCopy方法就可以实现拷贝了
45-49:实体类中建议重写toString()、equals()、hashcode()方法
alt+shift+S
equals判断的时候要考虑null的情况
equals中使用getClass()进行类判断
重写toString()是直接打印对象时能看到相关信息,例People [age=20, name=李四, sex=0],不重写的话就是类似这种jsontest.People@18f0fc6
重写equals()和hashcode()是判断是否相等时用到
HashMap的底层机制:是以数组的方式保存Map条目的,其中的关键是数组下标的处理机制:依据传入元素的hashcode的返回值来决定数组的下标,如果数组的位置上已 经有 了Map条目,且与传入的键值相等,则不处理,如果不相等就覆盖,如果传入的位置上没有条目就插入,然后放到Map条目的链表中。同理,检查键是否存在,也是根据哈西码确定位置,然后遍历查找位置。
50.使用package-info类为包服务(没细看)
51.不要主动进行垃圾回收