`

practical java & effective java 读书笔记

阅读更多

 第一章 一般技术
1.java只有唯一一种参数传递方式:by value(值传递)。对于primitive types(基本型别)很容易理解,对于object references(对象引用),传递的是object reference的拷贝。
2.polymorphism(多态)优于instanceof:instanceof很容易被误用,很多场合都应该以多态代替,无论何时看到instanceof,请判断是否可以改进以消除它。
3.避免创建重复对象。比如一个类A的某个方法新建了一个类B,且此类B不会改变,则每次建立该类A的一个对象就会新建B的对象,此时应把
B设为private static final。
4.清除过期的对象引用。
5.避免使用终结函数。因为终结函数可能得不到执行或很久后得到执行,所以要避免使用。显示的中止方法通常与try-finally结构结合使用,防止出现异常时终结函数得不到执行。
eg: Foo foo = new Foo(...);
    try{
        //do what must be done with foo   
    }finally{
        foo.terminate();
    }
6.通过私有构造函数来强化不可实例化的能力。比如一些工具类不希望被实例化,然而在缺少显示构造函数时编译器会自动提供一个默认构造函数,为防止以上情况要构造一个显示的私有的构造函数。
eg:public class UtilityClass{
     private UtilityClass(){
     }
   }
7.通过私有构造函数强化singleton属性。singleton是指这样的类,它只能实例化一次。singleton通常被用来代表那些本质上具有唯一性的系统组件,比如视频显示或者文件系统。
  eg:public class Elvis{
       public static final Elvis INSTANCE = new Elvis();
       private Elvis(){
       }
     }
8.考虑用静态工厂方法代替构造函数,但如果没有其他强烈的因素,最好还是简单的使用构造函数,毕竟它是语言规范。静态工厂方法实际上是一个简单的静态方法,他返回的是类的一个实例。
  有点:a.与构造函数不同,静态工厂方法具有名字。
        b.与构造函数不同,它们每次被调用的时候不要求非得创建一个对象。
        c.与构造函数不同,与构造函数不同,它们可以返回一个原类型的子类型对象。
第二章 所有对象都通用的方法(equals(),hashCode(),toString(),clone(),Comparable接口)
一.按规则使用equals():
1.使用equals的规则:
  a.如果一个class的两个对象占据不同的内存空间也可被视为逻辑相等的话,那么得为这个class提供一个equals()
  b.检查是否等于this
  c.比较关键域以判断两个对象是否相等
  d.如果有java.lang.Object以外的任何base class实现了equals(),那么就应该调用super.equals()
  e.如果只允许同一个class所产生的对象被视为相等,则通常使用getClass()
    eg1:一般情况
    public boolean equals(Object obj){
        if(this == obj){
          return true;
        }
        if(obj != nul && getClass() == obj.getClass()){
          Test test = (Test)obj;
          if(***){//相等条件
              return true;
          }
        }
        return false;
      }
    eg2:调用super.equals()情况
    public boolean equals(Object obj){
      if(super.equals(obj)){//已经包含了this == obj; obj !=null && getClass() == obj.getClass()的判断
        Test test = (Test)obj;
          if(***){//相等条件
              return true;
          }
        }
        return false;
      }

  f.只有在不得不对derived class对象与base classes对象进行比较的场合中,才使用instanceof,并且你应该明白这样做带来的可能问题和复杂性,并且derived class和base classes都用instanceof实现equals()时,这种比较不会展现“对称相等性”。
    Base b;Derived d;//分别表示父类、子类
    1)父类实现equals,子类继承父类的equals,b.equals(d) == d.equals(d);
    2)父类子类分别实现了equals,b.equals(d) != d.equals(b);
    3)父类未实现equals,子类实现了equals,b.equals(d) != d.equals(b);
2.对于既不是float也不是double类型的primitive types,使用==操作符;对于对象引用域,可以递归的调用equals方法;对于float域,先使用Float.floatToIntBits转换成int类型值,然后使用==操作符比较int类型的值;对于double域,先使用Double.doubleToLongBits转换成int类型的值,然后使用==操作符比较long类型的值.(这是由于存在Float.NaN、-0.0f以及类似的double类型的常量)
二.hashCode():
1。改写equals时总是要改写hashCode方法,如果不这样作,会导致该类无法与所有基于散列值(hash)的集合类在一起正常工作,这样的集合类包括HashMap、HashSet、HashTable
2。hashCode方法的简单方法:
  1。把某个非零数值(比如17),保存在int result变量里。
  2。对于对象中每一个关键域f(指equals方法中考虑的每一个域),完成以下步骤:
  a)为该域计算int类型的散列码c:
    i.该域为boolean型,c = f ? 0 : 1
    ii.byte, char, short, int型, c = (int)f
    iii.long型, c = (int)(f ^ (f >>> 32))
    iv.float型, c = Float.floatToIntBits(f)
    v.double型, Double.doubleToLongBits(f)得到long型,然后按iii计算散列值
    vi.如果是对象引用,c = (this.*** == null) ? 0 : this.***.hashCode();
    vii.如果该域是个数组,则把其中每一个元素当作单独的域来处理
   b)result = 37 * result + c;//把每个c都组合到result中
   3。返回result
   eg1:
 public int hashCode() {
     int result = 17;
     //对于关键域是id的情况
     int idValue = (this.getId() == null) ? 0 : this.getId().hashCode();
     result = (result * 37) + idValue;
     //如果还有第二个关键域name
     //int nameValue = (this.getName() == null) ? 0 : this.getName().hashCode();
     //result = (result * 37) + nameValue;
     this.hashValue = result;
 return this.hashValue;
 }
    eg2:
 如果一个类是非可变的,并且计算散列码代价较大,则应把散列码存到对象内部:
 private int hashValue = 17;//先定义hashValue,不需要get/set方法
 ........................
 public int hashCode() {//对于关键域是id的情况
     if (this.hashValue == 17) {
  int result = 17;
  int idValue = (this.getId() == null) ? 0 : this.getId().hashCode();
  result = (result * 37) + idValue;
  //如果还有第二个关键域name
  //int nameValue = (this.getName() == null) ? 0 : this.getName().hashCode();
  //result = (result * 37) + nameValue;
  this.hashValue = result;
     }
     return this.hashValue;
 }
三。toString():会使这个类用起来更加方便。
四。谨慎的改写clone()。实现拷贝的方法有两个:一是实现cloneable接口(effective java 39页,没仔细看),二是提供拷贝构造函数
  public Yum(Yum yum);
  或是上面的微小变形:提供一个静态工厂来代替构造函数:
  public static Yum newInstance(Yum yum);
五、用到搜索、排序、计算极值的情况时,考虑实现Comparable接口。
public int compareTo(Object o)//方法不需要手工检查参数的类型,如参数类型不符合会抛出ClassCastException;如参数为null,该方法抛出NullPointerException。
第三章 类和接口
1。使类和成员(变量、方法、内部类、内部接口)的可访问能力最小化。
2。private和friendly成员都是一个类实现中的一部分,并不会影响到导出API。然而,如果这些域所在的类实现了Serializable接口,那么这些成员可能会被泄漏到导出API中。
3。如果一个方法改写了超类中的一个方法,那么子类中该方法的访问级别不能低于父类中该方法的访问级别。特别是:类实现了接口,那么接口中的方法在这个类中必须声明为公有的,因为接口中方法默认为public abstract。
六、异常处理
1.决不可忽略异常,即catch后什么也不做。
2.决不可掩盖异常
try{
  e1;//异常1
  e2;//异常2
}catch(Exception e){
  e.printStackTrace()
}//只能捕获异常2
办法:要仔细分析,用栈来保存异常
3.覆写异常处理时:
父类不抛出异常时,自类不能抛出异常。
父类抛出异常时,自类三种情况:a)不抛出异常b)抛出父类异常c)抛出父类异常的派生异常。
4.只要有finally块就一定会进入,即使try-catch块有return/break/continue语句。
5.养成将try/catch块放在循环外的习惯,在不启动JIT时节省时间。

分享到:
评论

相关推荐

    Practical Unix & Internet Security, 3rd ed 2003

    Practical Unix & Internet Security, 3rd ed 2003

    Practical Java(简体中文)

    《Practical Java》和《Effective Java》正是这样两部著作,它们对Java的重要而基础的技术细节进行了详尽、深刻的介绍和剖析,每个主题独立成章,既方便读者根据需求选择性阅读,又能彼此呼应,形成一个完整的学习...

    Practical Java一书及代码

    《Practical Java》是侯捷老师的一本关于Java编程实践的书籍,旨在帮助读者深入理解Java语言,并通过实际代码示例提升编程技能。这本书涵盖了Java的基础到进阶内容,是学习和提升Java技术的重要资源。 1. **Java...

    Practical Java(含源码)

    《实用Java编程(含源码)》是一本专注于解决Java编程实际问题的书籍,它针对的是Java程序员在日常开发过程中可能会遇到的各种困扰和难题。这本书的目的是为了解答那些经常出现但又容易让人迷惑的问题,从而提升Java...

    Practical Java全书源码.rar

    《Practical Java全书源码》是一份宝贵的资源,它涵盖了J2ME(Java 2 Micro Edition)平台上的手机游戏开发。J2ME是Oracle公司为小型设备和嵌入式系统设计的一种Java平台,广泛应用于早期的移动设备,如功能手机和...

    practical java(中文版)

    《实用Java(中文版)》是一本由资深Java编程专家撰写的指南,旨在提供实际、高效且具有针对性的Java编程实践经验。这本书经过侯捷的翻译,确保了内容的准确性和可读性,对于中文读者来说,是学习和提升Java技能的...

    Practical UNIX & Internet Security

    Practical UNIX & Internet Security 英文版 chm 号称1004页 <br>一本老书,但是unix的基本原理,与网络安全的基本原理还是值得学习的 <br>Table of Contents Preface <br> Part I: Computer ...

    《Practical Java》中文版随书源码

    《Practical Java》中文版随书源码是一个包含与J2ME手机游戏开发相关的实践教程资源。这本书通过实例深入浅出地介绍了Java编程语言在移动平台上的应用,特别是针对Java Micro Edition (J2ME)环境。J2ME是Java的一个...

    Practical Java(中文版(繁体+简体))

    Practical Java viii 2 對象與相等性(Objects and Equality) 25 實踐8:區分reference type 和primitive type 25 實踐9:區分== 和 equals() 29 實踐10:不要倚賴equals()的缺省實現33 實踐11:實現equals()時必須...

    Practical Java【完整版】【PDF】【含源码】【侯捷译】

    侯捷和刘永丹合译得Practical Java,压缩包内含3个文件,其中2个pdf,一个为全简体版,虽有所删割,我还没添加书签,但排版良好,推荐。 另一个是网友合成版,前3章是侯捷发布的免费版,当然是繁体的,后面的是网上...

    practical_java.zip_practical java

    《Practical Java》是由著名程序员侯捷编写的关于Java编程实践的一部著作,该书深入浅出地探讨了Java编程的各个方面,旨在帮助开发者提升实际编程能力。在压缩包"practical_java.zip"中,包含了两个主要文件:...

    Practical Java

    ### 实践1:Java中的参数传递机制 #### 参数传递方式:值传递 vs 引用传递 在Java中,参数是以**值传递**(by value)的方式传递给方法的,而不是很多人误解的**引用传递**(by reference)。这种误解往往来源于Java...

    Practical.Java简体中文版

    《Practical Java》是一本由资深Java专家编写的实践性指南,旨在帮助读者深入理解Java编程语言,并提供改进代码质量的实用策略。这本书的核心在于68个关键主题,每个主题都针对一个特定的编程问题或最佳实践,旨在...

    Practical Java(海格尔经典之作)

    《Practical Java》是Java编程领域的一部经典之作,作者为(美)海格尔,它与《Effective Java》齐名,都是程序员提升编程技能的重要参考资料。本书深入浅出地介绍了如何编写高质量、高效的Java程序,旨在帮助开发者...

    Deep Learning: Practical Neural Networks with Java 完整高清英文azw3版

    Deep Learning: Practical Neural Networks with Java by Yusuke Sugomori English | 8 Jun. 2017 | ASIN: B071GC77N9 | 1057 Pages | AZW3 | 20.28 MB Build and run intelligent applications by leveraging key ...

    Practical Java Game Programming

    Practical Java Game Programming Chapter 1 - Java as a Game Platform Chapter 2 - Fundamentals of Game Programming Chapter 3 - 2D Graphics Programming Chapter 4 - Creating Game Audio Using Java...

    Practical Java[含源码][PDF]

    《Practical Java》是Java编程领域的一本经典教程,由著名技术翻译家侯捷先生翻译。这本书深入浅出地介绍了Java编程语言的核心概念和技术,旨在帮助读者从实践角度理解和掌握Java编程。书中涵盖的内容广泛,从基本...

Global site tag (gtag.js) - Google Analytics