编写高质量代码:改善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.不要主动进行垃圾回收

原文地址:https://www.cnblogs.com/-scl/p/7643905.html