Effective Java阅读理解

作为一个刚毕业的程序员,提升自己的技术是很必要的,听说这本书不错,看了后总结一下,也方便以后再回顾。说实话,有的原则还需要在以后的工作中才能深刻体会到了。立个flag,一年后再看一遍。

1. 好的代码应该有以下特点

  • 代码的清晰性和简洁性最为重要;
  • 代码应该被重用,而不是被拷贝;
  • 错误应该被尽早检测出来,最好是在编译时刻(fast-fail);
  • 好的代码应该是清晰,正确,可用,健壮,灵活和可维护的。

2.开发设计原则-equals,hashcode

  • 覆盖equals时需要遵守的通用约定,如果类具有自己特有的“逻辑相等”概率,我们就需要覆盖equals;
  • 覆盖equals时总要覆盖hashcode,如果两个对象用equals比是相等的 ,则两个对象的hashcode方法都必须产生相同的整数结果。
  • 始终要覆盖toString方法,覆盖这个方法主要是为了调试打印的时候看起来更舒服。
  • 谨慎地覆盖clone,如果你扩展了一个实现了Cloneable接口的类,就需要实现一个行为良好的clone方法,没必要就别这么干。
  • 考虑实现Comparable接口,底层依赖与这个方法的类有treeMap和treeSet 以及工具类Collections和Arrays等,这个一般都看情况 是否需要实现。(小于为负大于为整 等为0)

3.方法的访问权限

  • 使类和成员的可访问性最小化,对于外部的其它模块是否隐藏其内部数据和实现细节(正确的使用修饰符),应该始终尽可能降低可访问性;

  • 在公有类中使用访问方法而非共有域,就比如说 你在申明一个类属性时,为private的,然后提供的get/set方法是公有的,不应该直接暴露据域;

  • 使可变性最小化,不可变的类比可变类更加易于设计,实现和使用,简单来说就是让类不可以被修改(包括里面的数据域),这样就可以共享,也不用担心线程安全问题。
    使类成为不可变需要遵循下面五条规则:
    (1)不要提供任何会修改对象状态的方法
    (2)保证类不会被扩展(final修饰)
    (3)使所有的域都是final的
    (4)使所有的域都是final的
    (5)确保对于任务可变组件的互斥访问
    不可变对象缺点:对于每个不同的值都需要一个单独的对象。

  • 复合优先于继承。
    继承打破了封装性;
    复合:不用扩展现有的类,而是在新的类中增加一个私有域,它引用现有类的一个实例;对于两个类A和B,只有当两者之间确实存在’is-a‘的关系才用继承(栈stack并不是向量vector,所有不应该直接继承);

  • 接口优先与抽象类
    类只允许单继承,所以用抽象类受到了极大限制;现有的类可以很容易被更新,以实现新的接口;抽象类有个很大的作用就是用作骨架实现类(
    实现了一些基本的方法,自定义化程度比较高的方法就让用户继承后后自己实现),骨架实现类就是为了继承而设计的。

  • 优先考虑静态成员类
    静态成员类:最好把它看作普通的类,只是碰巧被定义在类的内部;它可以访问外部类的所有成员,包括私有的。
    非静态成员类:每个实例都包含一个额外的指向外围实例的引用(依赖外围实例,会消耗更多的资源)。
    局部类:简单来说就是在类内部,用private修饰的,不希望外面的引用。
    匿名类:没有名称,不是外围类的一个成员,在使用的时候才会被声明和实例化。

  • 泛型
    泛型是编译时检查,运行时擦除,这样也就能兼容以前的版本;
    数组是协变的,泛型是不可变的。
    数组是具体化的,在运行时才知道并检查他们的元素类型约束;泛型是在编译时强化他们的类型信息,运行时丢弃。
    简单来说就是,使用泛型更安全,容易。

4.反正就是设计原则,让自己的代码更完美

  • 方法
    应该在发生错误之后尽快检测出错误;
    必要时进行保护下拷贝(长度非零的数值总是可变的);
    谨慎设计方法签名(对与参数类型优先使用接口而不是类);
    谨慎用重载(组合优先与继承,继承破坏了灵活性);
    慎用可变参数(先创数组,然后将参数值放入数值中,将数值创给方法,每次调用都会进行一次数值分配和初始化);
    返回零长度的数值或者集合,而不是null(null很多时候都会报错);
    对API写好注释;
  • 通用程序设计
    将局部变量作用域最小化(增强代码的可读性和维护性—在第一次使用的时候再初始化);
    for-each优先与传统的for循环(简洁性,预防bug),但是有的情况还是必须用传统for循环的(过滤,转换);
    如果需要精确的答案,避免使用float和double,会丢失精度(每次传输是4字节,而它们是8字节);
    基本类型优先与装箱基本类型(基本类型比装箱基本类型更节约时间和空间,装箱基本类型默认值为null,在集合或者反射方法调用的时候只能用装箱基本类型);
    当心字符串连接的性能(两个字符串+,由于字符串是不可变的,就会拷贝成一个新的,用stringbuffer代替String);
    通过接口引用对象,更加灵活;
    谨慎使用本地方法(本地方法不是安全的-内存);
    遵守普遍接收的命名惯例
  • 异常
    只针对异常的情况才使用异常;
    对可恢复的情况使用受检异常,对编程错误使用运行时异常;
    在细节信息中包括能捕获失败的信息,便于以后分析;
    努力使失败保持原子性;
    不要忽略异常;
  • 并发
    同步访问共享的可变数据
    为了避免死锁和数据破坏,千万不要从同步区域内部调用外来方法
    executor和task优先与线程
    不可依赖于线程调度器
  • 序列化
    谨慎的实现Serializable接口(大大降低了‘改变这个类的实现’,很有必
    要声明序列号id,当然在网络传输过程中,是必需要的);
发布了42 篇原创文章 · 获赞 29 · 访问量 2558

猜你喜欢

转载自blog.csdn.net/qq_32314335/article/details/85217296
今日推荐