`
hxrs
  • 浏览: 25688 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

读《Practical Java》笔记

阅读更多

1.缺省情况下, classes 拥有的任何 non-private 、 non-static 函数都允许被subclasses 覆写( overridden )。 class 设计者如果希望阻止 subclasses 覆写( 修改)某个函数。则必须采取明确动作,也就是将该函数声明为 final 。

2.当新建一个数组时, 请记住,每一个元素都将依据其自身型别而被赋予缺省值。如果数组的元素是object references时, Java便不会调用default构造函数,而是将其初值设为null。

3.一旦你的程序不再参考(或说引用)某个对象,垃圾回收器就会回收这个对象所拥有的内存。当不再需要某对象时,你可以将其 references 设为 null ,以协助垃圾回收器取回内存。如果你的程序执行于一个内存受限环境中,这可能很有益处。

4.总体而言, equals() 的最佳实现方式就是搭配 getClass() ,后者可确保只有相同 class 所产生的对象才有机会被视为相等。此外, equals() 应当查看参与 比较的对象是否为同一个对象。 equals() 不必对每一个属性( attributes )进行比较,只有那些攸关 [ 相等性 ] 的属性才需要比较。

5.在equals()函数中使用getClass(),这种做法使得只有隶属于同一个class的对象才能被视为相等。如果希望derived class对象与其base class对象也可被视为相等。

6.实现 equals() 时需要遵循某些规则:
   1)如果某个 class 的两个对象即使占据不同的内存空间, 也可被视为 「 逻辑上相等」的话,那么你得为这个 class 提供一个 equals() 。
   2)请检查是否等于 this。
   3)比较这个 class 中的相关属性(值域, fields ),以判断两个对象是否相等。
   4)如果有 java.lang.Object 以外的任何 base class 实现了 equals() , 那么就应该调用super.equals()。
  在 equals() 函数中面对 getClass() 和 instanceof 进行取舍时,你要仔细斟酌以下问题:
   1)如果只允许同一个 class 所产生的对象被视为相等,则通常使用getClass()。
   2)只有在不得不「对 derived classes 对象与 base classes 对象进行比较」 的场合中,才使用 instanceof ,而且你应该明白这样做带来的可能问题和复杂性。
   3)如果使用 instanseof ,而且 derived class 和 base class 都实现有 equals() ,则一定要知道,这种比较不会展现出所谓的「对称相等性」(symmetric equality )。

7.将try/catch区段置于循环之外,这样有助于性能的提高,当不用JIT来优化的时候。

8.不要将异常用于流程控制。否则,会使得性能低下,含义模糊,而且难以维护。

9.对象构建过程中,下面事件一定会以固定顺序发生:
   1)从 heap 之中分配内存,用以存放全部的instance 变量以及这个对象连同其superclasses 的实现专属数据 (implementation-specific data) 。所谓 [ 实现专属数据 ] 包括指向“class and method data ”的指针。
   2)对象的instance 变量被初始化为其相应的缺省值。
   3)调用 most derived class( 最深层派生类 ) 的构造函数 (constructor) 。构造函数做的第一件事就是调用superclass 的构造函数。这个程序一直反复持续到java.1ang.object 构造函数被调用为止。一定 要记住,java.1ang.object 是一切 Java 对象的base class 。
   4)在构造函数本体执行之前,所有instance 变量的初始值设定式 (initializers) 和初始化区段(initialization blocks) 先获得执行,然后才执行构造函数本体。于是 base class 的构造函数最先执行, most derived class 的构造函数最后执行。这使得任何 class 的构造函数都能放心大胆地使用其任何 superclasses 的 instance 变量。

10.声明 synchronized 函数,或声明[含有 synchronized 区段]的函数,会大大降低执行性能。无论你使用 synchronized 作为修饰符,还是在函数中使用 synchronized 区段,都意味着体积增大。只有当你得代码要求同步化,而且你理解那么做的代价之后,才使用synchronized 函数。如果整个函数都需要被同步化,则为了产生体积较小且执行速度较快的代码,请优先使用函数修饰符,而不是在函数内使用synchronized 区段。

11.Java 对于instance 变量、 static 变量和 arrays 都进行了缺省的初始化动作(default Initialization) ,我们不应该因为[ 重复将这些变量和arrays初始化为缺省值] 而非必要的低效性能上的好处。

12.当synchronized被当做函数修饰符的时候,它所取得的lock将被交给函数调用者(某对象)。如果synchronized用于object  reference,则取得的lock将被交给该reference所指对象。

13.对synchronized的最后一点说明: Java 语言不允许你将构造函数声明为, synchronized( 那么做会发生编译错误 ) 。原因是当两个线程并发调用同一个构造函数时,它们各自操控的是同一个 class 的两个不同实体 ( 对象 ) 的内存 ( 也就是说 synchronized 是画蛇添足之举 ) 。然而如果在这些构造函数内包含了彼此竞争共享资源的代码,则必须同步控制那些资源以回避冲突。

14.关键词synchronized可用于static函数和class literals(类名称字面常量,eg.  Foo.class)身上,当你调用一个synchronized static 函数时,获得的lock将与[定义该函数]之class的Class 对象相关联(而不是与调用函数的那个对象相关联)。当你对一个class literal 调用其synchronized 区段时,获得的也是同样那个lock,也就是[与特定Class对象相关联]的lock。

15.Volatile or synchronized ? 这取决于多个因素。如果并发性(concurrency)很重要,而且你不需要更新很多变量,则可以考虑使用 volatile 。如果你需要更新许多变量,使用volatile 可能要比使用 synchronization 降低执行速度。记住 , 一旦变量被声明为volatile ,在每次访问它们时,它们就与主内存进行一致化。但如果使用 synchronized ,只有在取得 lock 和释放 lock 的时候,才会对变量和主内存进行一致化。如果你要更新许多变量,而且不情愿为每次访问都付出[一致化]代价,或是你因为其他什么原因打算消除并发性 (concurrency) ,可考虑使用 synchronized 。

技术

优点

缺点

Synchronized

取得和释放lock时,进行私有专用副本与主内存正本的一致化

消除了并发性的可能

volatile

允许并发行

每次访问变量,就进行稀有专用内存与对应之主内存的一致化


16.要实现一个immutable class(不可变类)时, 请遵循下列规则:
   1)声明这个 class 为 final 。
   2)声明所有数据为 private 。
   3)只提供取值函数 (getter) ,不提供设值函数 (setter) 。
   4)在构造函数中设置所有 instance 数据。
   5)如果函数返回 reference to mutable objects ,请克隆那些 mutable objects 。
   6)如果函数接受 reference to mutable objects ,请克隆那些 mutable objects 。
   7)如果缺省之浅层克隆 ( shallow clone ) 不能符合 immutable object 的正常行为,请实现出深层克隆 ( deep clone ) 。

17.immutability (不变性)技术

技术

 优点

缺点

Immutable inference 不可变(恒常)接口

简单易行。无需付出性能上的代价

有破绽,可被破坏

Common interface or base calss 公共接口或基类

没有破绽。清晰地将mutable object immutable objects 分离

需实现更多的classes,完成更深的classes 继承系

Immutable delegation class不可变(恒常)委托类

没有破绽。当你无法修改既有的mutable object 源码时,此法可用

需付出性能上的代价


18.在构造函数中调用non-final函数,要谨慎。如果这个函数在derived class中被override了的话,可能子类构造的时候会调用子类override后的这个函数。


后记: 今天一天把这本薄书(电子版)翻完了,都是一些基础的知识,但很有用。做了一些笔记,留着以后温故而知新。:)

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics