Effective_java边读边总结

13条:使类和成员的可访问性最小化:

1、如果一个子类覆盖了父类的一个方法,子类中的方法访问级别必须高于父类中方法的访问级别,这样可以确保任何使用父类的实例的地方也都可以使用子类的实例:

eg:

父类:

public class PerSon {
    protected  void print(){
        System.out.println(" this is a person");
    }
}

子类:

public class User extends PerSon {
   //这里覆盖的print方法的访问级别只能是protected或者public
    @Override
    public void print() {
        super.print();
    }
}

java的访问控制级别:

 

private:私有的,只有在声明该成员的内部使用;

default:缺省时的默认访问级别,只有同一个包下面的类才能访问;

protected:受保护的访问级别,2种情况下可以访问:1、同一个包下面可以访问;2、继承该类的子类可以访问;

public:公开的,顾名思义没什么限制,所有包下的所有类都可以访问;

注:我们将protected和public称作导出包的api;

2、实例域绝不能是共有的,这样就破坏了数据的封装型;

14条:在共有类中使用访问方法而非共有域:

对于包级私有的类,或者是私有的嵌套类,直接暴露数据域也并没有问题;

共有类永远不应该暴露可变的域,暴露不可变的域虽然还是有问题,但是伤害小点;

15条:使可变类最小化:

使类成为不可变的五个条件:

1、不要提供任何修改对象状态的方法;

2、保证类不会被拓展,一般将类修饰成final

3、使所有的域都是final的;

4、使所有的域都是私有的;

5、确保对于任何可变组件的互斥访问;

不可变对象比较简单,并且是线程安全的,无需手动同步,所以不可变对象可以被自由的共享;

16:符合优于继承

17:要么为继承而设计,并提供说明文档,要么就禁止继承;

父类构造器觉不能调用可被覆盖的方法;

eg:

public class Super {

    public  Super(){
        overide();
    }

    public void overide(){

    }
}

子类:

public class Sup extends Super {

    private Date date;

    Sup(){
     date = new Date();
    }

    @Override
    public void overide() {
        System.out.println(date);
    }

    public static void main(String[] args) {
        Sup sup = new Sup();
        sup.overide();
    }
}

我们可能期望的是打印2次日期,但是事实是第一次打印的是null,因为调用子类构造器之前会先调用父类Super的构造器,父类的构造器会调用Sup子类的overide覆盖方法,此时子类Sup的构造方法还没有执行,所以date对象是个null对象;

18:接口优于抽象类:

现有类可以很容易被更新,以实现新的接口;

接口是定义mixin的理想选择;

接口允许我们构造非层次结构的类型框架;

public class TestAbstract {

    static List<Integer> intArrayList(final  int [] array){
        if (array == null)
            throw  new NullPointerException();
        return new AbstractList<Integer> (){

            @Override
            public int size() {
                return array.length;
            }

            @Override
            public Integer get(int index) {
                return array[index];
            }
            @Override
            public Integer set(int i, Integer value){
                Integer oldval = array[i];
                array[i] = value;
                return oldval;
            }
        };

    }

    public static void main(String[] args) {
        int [] array = new int[]{1,2,3};
        List  list = intArrayList(array);
        System.out.println(list.get(2));
    }
}

如果无法拓展这个类,那也可以自己接实现这个接口,实现这个接口的类可以把对于接口方法的调用,转发到一个内部私有类实例,这个内部私有类拓展了骨架实现类,就像上面这样的实现,这种方法被称作模拟多重继承,它实现了多重继承的优点,同时又避免了单继承的缺点;

19:接口只用于定义类型:

常量接口不值得效仿:

public interface ConstantInterface {
    
    public static final  int CONSTANT = 0;
}

这是一个反面的例子;

20:类层次优于标签类;

21:用函数对象表示策略;

22:优先考虑静态成员类(静态类内部类);

内部类分为四种:静态内部类、成员内部类、局部内部类、匿名内部类

第五章:泛型

23:不要在新代码中使用原生态类型:

24:消除非受检警告:

尽量消除非受检警告,因为每一条非受检警告都包含一条ClassCastException,如果能够确定某条非受检警告是类型安全的,那么可以使用@SuppressWarnings("unchecked")来忽略这条警告,这个注解可以用在类,方法、局部变量上,我们应该让在尽可能让@SuppressWarnings("unchecked")的影响范围最小;

25:列表优于数组:

数组不能使用泛型

26:优先考虑泛型:

27:优先考虑泛型方法:

28:利用有限制的通配符提升API的灵活性:

29:优先使用类型安全的异构容器:

集合API说明了泛型API的一般用法,限制你每个容器只能有固定数目的类型参数,你可以将类型参数放在键上而不是容器上来避开这一限制,对于这种类型安全的异构容器,可以使用Class对象作为键;

30:用enum枚举替代int常量:

31:用实例域代替序数:

就是不要用enum的ordinal函数(返回枚举常量在类型中的数字位置),将枚举的序数保存在一个实例域中;

32:用EnumSet代替位域:

33:用EnumMap代替序数索引:

34:用接口模拟能伸缩的枚举;

35:注解优先于命名模式:

36:坚持使用@Override注解:

37:用标记接口定义类型:

38:检查参数的有效性:

在方法执行之前先进行参数的检查,比如索引不能为负数,对象不能是null等等,这样才可以抛出合适的异常,对于共有的方法,要用@Throws标签标明违反参数限制时可能抛出的异常

39:必要时进行保护性拷贝:

40:谨慎设计方法签名:

谨慎的选择方法的名称

不要过于追求提供便利的方法

避免过长的参数列表,目标是4个或者更少

41:慎用重载:

42:慎用可变参数:

43:返回零长度的数组和集合,而不是null

44:为所有导出的API编写文档的注释:

45:将局部变量的作用域最小化:

46:for-each循环要优于传统的for循环:

47:了解和使用类库:

48:如果需要精确的答案,不要使用float和double:

49:基本类型由于装箱基本类型

50:如果其它类型更合适,避免使用字符串:

51:当心字符串连接的性能:

如果进行大量的字符串连接操作时,使用StringBuffer或者StringBuilder而不是+

52:通过接口引用对象:

53:接口优于反射机制:

54:谨慎使用native方法:

55:谨慎地使用优化:

56:遵守普遍的命名习惯:

57:只针对异常的情况才使用异常:

58:对可恢复的情况使用受检异常,不可恢复的使用运行时异常:

59:避免不必要的首检异常:

60:优先使用标准的异常:

61:抛出与抽象相对应的异常:

62:每个方法抛出的异常都要有文档:

63:在细节消息中包含能捕获失败的信息:

64:努力使失败保持原子性:

65:不要忽略异常:

66:同步访问共享的可变数据:

volatile保证对象的内存可见性,但是不能保证互斥访问和线程安全;

67:避免过度同步:

68:executor和task优先与线程:

69:并发工具优先于wait和notify:

70:线程安全性的文档化:

71:慎用延迟初始化:

72:不可依赖于线程调度器:

73:避免使用线程组:

74:谨慎地实现Serializable接口:

75:考虑使用自定义的序列化方式:

76:保护性的编写readObject方法:

77:对于实例的控制,枚举类型优先于readResolve:

78:考虑用序列化代理代替序列化实例:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值