现在的位置: 首页 > 综合 > 正文

Effective java 读书笔记

2017年10月27日 ⁄ 综合 ⁄ 共 10573字 ⁄ 字号 评论关闭

第二章 创建和销毁对象

规则1  考虑以”static factory mehthods”取代构造函数

提供一个公共静态工厂方法返回一个类的实例

优势:

有名字, 不需要每次都建立一个新的实例, 可以复用对象, 还可以返回类型的子类

能够保证是单例类, 能够保证不会有两个相同的实例存在

 

没有构造函数的类不能被子类化.

不容易和其他静态方法区分开

常见的是valueofgetInstance方法

 

规则2 用私有构造函数构建单例模式

 

规则 3 用私有构造函数构造工具类避免被实例化

 

规则 4 避免创建重复对象

对象如果是不可变的总是可以被复用, String就是不可变对象, 为了避免创造重复对象而使用静态工厂方法, Boolean.valueOf(String)比构造函数Boolean(String), 构造函数需要每次都建立新的对象, 而静态工厂方法则不需要.

本规则中的两个例子很好, 但关于适配器中的两个例子没有看.

适配器对象用来提供可选择的接口给返回的对象, 因为适配器没有状态, 所以没有必要建立超过一个实例, 举的keySet的例子, map接口的keySet方法返回Set, 由于Set是个接口, 所以Set虽然只有一个实例, 但可以得到不同的实现.

避免创建重复对象不意味着新建对象很昂贵或是可以避免, 相反, 建立和申明小的对象开销小, 特别是现代的JVM.

另一方面, 维护自己得对象池是个坏主意除非在对象池中的对象实在太耗资源, 

 

 

规则5 消除过期的对象

如果类管理了自己的内存, 就要注意将过期的对象销毁, 当对象被读出后, 对象的地址仍然被保存在数组中, 这些地址是不会被对象回收器回收的.

为什么垃圾回收器不能回收array管理的内存, 垃圾回收器的原理, 它能回收怎样的资源, 它在什么时候回收资源?

 

规则 6:避免finalizer

 

规则 7 //TODO

 

第三章 所有对象通用的方法

// TODO

 

第四章 对象和接口

 

规则 12把类和成员的可访问范围降到最低

应该保证类变量具有尽可能少的可视性, 常量可以申明为公共的, 一个好的模块隐藏了所有的实现细节, 这样可以把模块之间的耦合程度降到最低.

 

如果一个顶级类或是接口, 能够定义为包私有, 那就定义为包私有.

如果一个包-私有的顶级类或是接口仅仅被一个类使用, 应该考虑使它成为类的私有内部类, 当然这个并没有将顶级类该为包私有来的重要, 因为毕竟它已经是包私有的了, 通常public的类不应该有public的字段, 通常会用一个类来定义所有的常量.

以前从来没有注意过这一点, 从来都是定义类为public, 而不考虑类的使用范围.

没有定义长度的数组总是可变的, 不能定义为public static final array 字段, 客户端能够修改数组的内容,

 

public static final Type[] Values = {}; //wrong

 

private static final Type[] PRIVATE_VALUE = {};

public static final List VALUES = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUE));

 

规则 13不可修改的类更受青睐

不可修改类是指其实体不能被修改的类, 包含在类实体内的所有信息都在创建时提供, 并在生存期内固定不变, 不可变类是线程安全的, 不会因为多线程存取而破坏.

不要提供任何可供修改的方法

保证没有任何方法可以被覆写(将类定义为final)

所有类变量都必须是private

确保对任何可变组件的互斥存取

 

不可变类能够重用已经存在的类的实例, 最简单的方法是提供一个经常使用得公共常量.

 

不但可以共享不变的对象, 还可以共享他们内部资源.

不变对象为其它对象建立了很好的代码块. 不用担心他们的值在mapset中会变化.

唯一的缺点是要为每一个不同的值建立一个对象.

//TODO

 

 

需要进一步理解copyclone方法

 

规则14 优先考虑复合, 然后才是继承

 

规则 15 除非专为继承而设计并提供文件, 否则不要使用继承

 

规则 16 在接口和抽象类之间优先选择前者

抽象类和和接口最明显的区别是抽象类允许实现一部分方法, 而接口需要实现全部方法.

 

规则 17 接口只用来定义类型

当一个类继承了一个接口时, 接口作为一个类型能够用来引用类的实例, 继承接口的类用来说明类的实例可以为客户端做什么, 为其他目的定义接口是不合适的.

不应该用接口来定义常量, 实现常量接口会导致实现的细节泄漏给类的API, 如果将来类修改不再需要常量, 仍然要实现接口来保证兼容性, 如果一个非final类继承了常量接口, 所有它的子类都会有接口的这些常量.

如果常量紧密的关联类或是接口, 应该把常量加入类或接口, 如果常量可以作为一个枚举类型的成员,应该在一个类型安全的枚举类型中定义, 其他, 应该定义在一个不变的工具类中定义.

 

规则 18 在静态和非静态内部类之间选择前者

静态成员类是最简单的嵌套类, 它是最好的嵌套类的选择, (and has access to all of the enclosing class’s members, even those declared private)能够获得所有类变量, 哪怕是私有的类变量, 这句话有问题, 静态成员类只能获得外部类静态的字段, 相反非静态成员类却能获得任何字段, 所以这点不见得是优点它是类的静态成员, 具有和其他静态成员一样的可视性.

静态成员类的一个常见的应用是作为公共的辅助类, 用来连接外部的类

 

每个非静态成员类的实例都会和父类的实例相关联, 非静态成员类的方法能够调用父类的方法,

Given a reference to an instance of a nonstatic member class, it is possible to obtain a reference to the encloing instance.

在没有父类实例的情况下, 不能够建立非静态成员类的实例.

非静态成员类的一个普通应用是定义适配器.

如果定义一个成员类不需要获得父类的实例, 那么定义成静态成员类. 如果不这样做的话, 每个实例都会有一个父类的引用.

 

匿名类不像java语言里的任何东西, 它没有名字, 它不是类的成员, 只要表达式合法它能够定义在类的任何地方, 行为是否象静态类或是非静态类取决于它在哪里定义.

由于匿名类没有名字, 所以它仅仅能用在初始化后不需要再在父类引用它的场合, 它仅能实现父类或是接口的方法, 而不能申明任何新的方法, 由于他们发生在表达式中间, 所以不能太长, 太长的话会影响程序的可读性.

一个典型的引用是建立功能对象

Arrays.sort(args, new Comparator(){

            Public int compare(Object o1, Object o2){

                        Return ((String)o1.length()-((String)o2).length();

}

});

另外一个应用是建立处理对象, Thread, Runnable, 或是TimerTask的实例, 第三个应用是静态工厂方法, 第四个应用是publi static final 字段的初始化.

如果一个嵌套类能够被方法外读取或是在方法体内太长, 使用成员类, 如果父类实例需要成员类的引用, 使用非静态成员类, 其他情况使用静态成员类,

 

 

 

 

 

第五章 C构造器的替代

规则 18 静态成员类超越非静态成员类

一个内嵌类是定义在其他类里面的类, 有四种内嵌类, 非静态成员类, 成员类, 匿名类, 本地类, 只有第一种被称为内部类.

每个非静态成员类和它的母类相关联, 不可能调用母类的方法, 不可能建立一个非成员类而不建立母类.

一个非成员类的普通的用法是定义适配器

 

规则 21 用类来代替枚举类型

名义上, 这个结构定义了一个枚举类型, 合法值由一组固定常数组成. 实际上, enum结构并不能很好的定义枚举类型. 它只是定义了一系列的整型常量的名字, 并没有对类型安全有很大作用

类型安全的枚举模式

public class Suit{

            private final String name;

            private Suit(String name) {this.name = name;}

            public String toString() {return name;}

 

            public static final Suit CLIBS = new Suit(“cllubs”);

            public static final Suit DIAMONDS = new Suit(“diamonds”);

}

 

 

第六章 方法

规则 23 检查参数的有效性

每次写一个方法或是构造函数的时候, 应该想想参数有什么限制, 应该将这些限制文档化, 并且要求在方法体开始前做显示的检查.

 

规则 24 在需要的时候做保护性拷贝

public class Box {

         private int length;

         public void setLength(int length){

          this.length = length;

         }                

 

         public int getLength(){

                   return this.length;

         }

}

 

public class TestJava {

         private String id;

         private int idx;

         private Box box;

         public void setId(String id){

                   this.id = id;

         }

 

         public String getId(){

                   return this.id;

         }

 

         public void setIdx(int idx){

                   this.idx = idx;

         }

 

         public int getIdx(){

                   return this.idx;

         }

 

         public void setBox(Box box){

                   this.box = box;

         }

 

         public Box getBox(){

                   return this.box;

         }

 

         public static void main(String[] args) {

                   TestJava tj = new TestJava();

                   String id = "tony";

                   int idx = 5;

                   Box aBox = new Box();

                   aBox.setLength(7);

                   tj.setId(id);

                   tj.setIdx(idx);

                   tj.setBox(aBox);

                   System.out.println(tj.getId());

                   System.out.println(tj.getIdx());

                   System.out.println(tj.getBox().getLength());

                   id = "bai";

                   idx = 6;

                   aBox.setLength(8);

                   System.out.println(tj.getId());

                   System.out.println(tj.getIdx());

                   System.out.println(tj.getBox().getLength());

         }

}

//output:

tony

5

7

tony

5

8

 

String类和Number类都是immutable, 所以Stringint类的对象会copy出一个不同于原对象的对象, 而原来的对象状态并未被修改, Box不是immutable所以被外部修改了

public void setBox(Box box){

                   this.box = new Box();

                   this.box.setLength(box.getLength());

         }

         public Box getBox(){

                   Box aBox = new Box();

                   aBox.setLength(this.box.getLength());

                  return aBox;

         }

修改后的output:

tony

5

7

tony

5

7

在实践中“为类中immutable class类型(如String和数值Number类)的field membersetter/getter时,我们不需要提供defensive copy;在为其它非immutable class类型(如上例中的Box)field membersetter/getter时,建议考虑defensive copy,以防止client对你的代码的恶意破坏”。

 

保护性拷贝应该在参数合法化检查之前.

 

规则 25 小心的设计方法签名

小心的选择方法名字

The Java Developers Almanac中包含了任何单个方法的签名. 但是没有找到具体的方法

避免太长的方法签名

三个方法名字是最长的方法签名

两种方法改变方法签名, 将一个方法变为多个方法, 建立一个静态帮助类用来放所有的参数, 但是为什么要用静态类呢? 这些帮助类是静态的成员类. //没有看明白

参数尽量使用接口

使用功能对象

需要配合规则18重看

 

规则 26 明智的使用重载

规则 27 返回0长度的数组, 而不是 njll

 

第七章 一般性编程

规则 29 将本地变量的范围降到最低

在第一次用的时候申明成员变量.

几乎所有的成员变量都需要一个初始值

如果没有足够的信息初始化一个变量, 应该推迟初始化直到获得信息为止.

For循环允许申明循环变量, 限制他们的作用范围在他们需要的区域, 因此forwhile循环更好.

For(Iterator I=c.iterator(); i.hasNext();){

            DoSomething(i.next());

}

 

Iterator I=c.iterator();

While(i.hasNext()){

            DoSomething(i.next());

}

Iterator i2 = c2.iterator();

While(i.hasNext()){

            DoSomethigElse(i2.next()); // BUG

}

第二个循环包括了一个剪切和粘贴错误

 

for(Iterator I = c.iterator(); I.hasNext();){

            doSomething(i.next());

}

// 编译错误 I 不能被解释

for(Iterator i2 = c2.iterator(); I.hasNext();){

            doSomething(i2.next());

}

第一个for循环的变量I 在第二个循环中不能编译通过.

因此, 如果使用for循环能够减少剪切和粘贴错误.

 

For(int I = 0, n = list.size(); I<n; I++){

            DoSomething(list.get(i);

}

变量n对性能是必须的, 不然每次循环都会执行一次size方法

 

规则 30 了解和使用类库

Collections.sort(v);

Vector按字母顺序排序

Collections.sort(v String.CASE_INSENSITIVE_ORDER);

System.out.println(Arrays.asList(a));

规则 32 避免字符串其他类型或许更合适

 

字符串不适合替代枚举类型, 类型安全枚举类型和int值都比字符串更适合用来表示枚举类型的常量.

 

字符串也不适合替代聚集类型,有一个更好的方法就是简单的写一个类来描述这个数据集,通常是一个私有的静态成员类最好。字符串也不适合代替能力表,总而言之,如果可以适合更加适合的数据类型,或者可以编写更加适当的数据类型,那么应该避免使用字符串来表示对象.

 

规则 33 注意string连接操作符的性能

重复的使用字符串连接操作符连接n个字符串需要n的平方的时间, 用连接字符串不适合规模较大的情况.

使用StringBuffer代替string存储字符串

public String statement(){

            String s = “”;

            For(int I = 0; I < numItems(); I++){

                        S += lineForItem(i);

}

}

public String statement(){

            StringBuffer s = new StringBuffer(numItems()*LINE_WIDTH);

            For(int I = 0; I<numItems(); I++){

                        s.append(lineForItem(i));

}

return s.toString();

}

 

规则 34 通过接口引用对象

如果你习惯用接口类型, 你的程序会更加灵活.

 

第八章 异常

规则 39 为异常情况使用异常

 

异常应该仅仅用在异常的情况下, 不能用来流程控制.

一个设计好的API不应该强制客户为控制流程使用异常

 

规则 40 为恢复条件检查异常, 为程序错误使用运行时异常

 

规则 41 避免使用不必要的异常检查

规则 42 使用标准异常

专家程序员和一般程序员的区别是专家高度的将代码复用

 

 

 

 

 

 

Effective Java word

access   control 访问控制  

  accessibility 可访问能力,可访问性  

  accessor   method 访问方法  

  adapter   pattern 适配器模式  

  anonymous   class 匿名类  

  antipattern 反模式  

  API Application   Programming   Interface,应用编程接口  

  API   element API元素  

  array 数组  

  assertion 断言  

  binary   compatibility 二进制兼容性  

  callback 回调  

  callback   framework 回调框架  

  checked   exception 被检查的异常  

  class   

  client 客户  

  comparator 比较器  

  composition 复合  

  concrete   strategy 具体策略  

  constant   interface 常量接口  

  copy   constructor 拷贝构造函数  

  custom   serialized   form 自定义的序列化形式  

  decorator   pattern   decorator模式  

  default   access 缺省访问  

  default   constructor 缺省构造函数  

  defensive   copy 保护性拷贝  

  delegation 委托  

  deserializing 反序列化  

  design   pattern 设计模式  

  discriminated   union 可区分的联合  

  doc   comment 文档注释  

  documentation   comment 文档注释  

  double-check   idiom 双重检查模式  

  encapsulation 封装  

  enclosing   instance 外围实例  

  enumerated   type 可枚举的类型  

  exception 异常  

  exception   chaining 异常链接  

  exception   translation 异常转译  

  exported   API 导出的API  

  extend 扩展  

  failure   atomicity 失败原子性  

  field   

  finalizer   guardian 终结函数守卫者  

  forwarding 转发  

  forwarding   method 转发方法  

  function   object 函数对象  

  function   pointer 函数指针  

  general   contract 通用约定  

  HTML   validity   checker HTML有效性检查器  

  idiom 习惯用法,模式  

  immutable 非可变的   

  implement 实现(用作动词)  

  implementation 实现(用作名词)  

  implementation   inheritance 实现继承  

  information   hiding 信息隐藏  

  inheritance 继承  

  inner   class 内部类  

  integral   constant 整值常量  

  interface 接口  

  interface   inheritance 接口继承  

  Java   Cryptography   Extension Java密码子系统扩展,简称JCE  

  lazy   initialization 迟缓初始化  

  local   class 局部类  

  member 成员  

  member   class 成员类  

  member   interface 成员接口  

  memory   footprint 内存印迹  

  memory   model 内存模型  

  method 方法  

  mixin 混合类型   

  module 模块  

  mutator 改变对象属性的方法  

  naming   convention 命名惯例  

  native   method 本地方法  

  native   object 本地对象  

  nested   class 嵌套类  

  nonstatic   member   class 非静态的成员类  

  object 对象  

  object   pool 对象池  

  object   serialization 对象的序列化   

  obsolete   reference 过期引用  

  open   call 开放调用  

  overload 重载  

  override 改写  

  package-private -私有  

  performance   model 性能模型  

  postcondition 后置条件  

  precondition 前提条件  

  precondition   violation 前提违例  

  primitive 原语的,原语类型  

  private 私有的  

  public 公有的  

  redundant   field 冗余域  

  reference   type 引用类型  

  reflection 映像机制  

  register 注册  

  rounding   mode 舍入模式  

  run-time   exception 运行时刻异常  

  safe   language 安全的语言  

  safety 安全性  

  semantic   compatibility 语义兼容性   

  self-use 自用()  

  serial   version   UID 序列版本UID  

  serialized   form 序列化形式  

  serializing 序列化  

  service   provider   framework 服务提供者框架  

  signature 原型  

  singleton pattern singleton模式  

  skeletal   implementation 骨架实现  

  state   transition 状态转变  

  static   factory   method 静态工厂方法  

  static   member   class 静态的成员类  

  storage   pool 存储池  

  strategy   interface 策略接口  

  strategy   pattern   策略模式  

  stream   unique   identifier 流的唯一标识符  

  subclassing 子类化  

  summary   description 概要描述  

  synthetic   field 合成域  

  thread   group 线程组  

  thread   safety 线程安全性  

  thread-compatible 线程兼容的  

  thread-safe 线程安全的  

  top-level   class 顶级类  

  typesafe   enum class 类型安全的枚举类  

  typesafe   enum pattern 类型安全的枚举模式  

  unchecked   exception 未被检查的异常  

  unintentional   object   retention 无意识的对象保持  

  utility   class 工具类  

  value   class 值类  

  value   type 值类型  

  view 视图  

  visitor   pattern visitor模式  

  wrapper   class 包装类  

 

抱歉!评论已关闭.