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

Effective Java 第2版 笔记

阅读更多

Item 1;Consider static factoriy moehtods instead of constructors

             考虑使用静态工厂方法代替构造函数

 

Item 2:Consider a builder when faced with many constructor parameters

             当构造函数参数过多时,是否可以使用Builder

             一个builder的例子:

             医生需要开一个只包含维生素(Vitamin)的处方(Prescription),处方一定包括A,可能包括B1、B2、C、D、E等,可能这个列表还会变化。这个例子用builder pattern实现就是:

             Prescription prescriotion = new Prescription.builder(100/**mg*/).vitaminB1(20/**mg*).vitaminE(1000/**mg*/).build(); //开了一个包含100mg维生素A、20mg维生素B1、1000mg维生素E的处方(可能这个患者比较需要维生素E)。vitaminB1(20/**mg*).vitaminE(1000/**mg*/) 这种串联的方式来创建对象是一个特色,让我想起了设计模式里的decorator模式,不过decorator是把一种类型的对象不断地包装,直到得到所需要的对象。

            Sandwich sanwich = new MeatSandwich(new VegetableSandwich(new CreamSandwich()));最后我们得到了一个有肉、蔬菜和奶油的三明治。O(∩_∩)O哈哈~

 

Item 3:Enforce the singleon property with a private constructor or an enum type

            实现单例的两种方式——private的构造函数或者使用枚举(enum)? 枚举实现单例倒还没用过- -

 

Item 4:Enforce noninstantiability with a private constructor

            将构造函数设为private来防止实例化,而不是简单讲类声明为abstract,后者允许被继承,子类同样可以被实例化

 

Item 5:Avoid creating unnecessary objects

            避免创建多余的对象,比如 new String("A"); new Integer(1) // insteading using Integer.valueOf(1);

 

Item 6:Eliminate obsolete object references

             释放对象引用

 

Item 7:Avoid finalizers

            避免使用finailizer方法,原因很简单,这个方法一定会执行,但你不知道何时这个方法到底何时执行。

 

Item 8:Obey the general contact when overriding equals

            重写euqals方法时,记得遵守它的每一条规则,具体见http://salever.iteye.com/blog/733705

 

Item 9:Always override hashCode when you override equals

            永远记得在你重写equals时也重写hashCode

 

Item 10:Always override toString

             总是重写toString方法,这会使用的类更人性化

 

Item 11:Override clone judiciously

              在适当的时候重写clone方法

 

Item 12:Consider implementing Comparable

              考虑实现Comparable接口,它提供了一个排序方法,使得对象具有一定的顺序。在对象作为集合类元素的时候,实现这个接口是一个不错的选择。

 

Item 13:Minimize  the accessibility of classes and members

              最大程度的控制类和成员的访问权限,能用private的就不用protected,能用protected的就不用public

 

Item 14:In public classes, use accessor menthods, not public fields

              在public的类中,采用通过访问器来访问成员变量

 

Item 15:Minimize mutablility

              最大程度地减小可变性,让对象一旦创建就不可更改,比如String,这样的类更简单,而且天生就是线程安全的。在某些场合下,使用静态工厂方法返回经常使用的常量对象,可以避免重复创建。

              总之尽可能的减小类的成员的可变性,能用final的就用final。

 

Item 16:Favor composition over inheritance

              组合优先于继承,如果A、B之间不是is-a的关系,那么不要使用继承,组合往往更加合适。另外,分布在不同的package下的class之间最好也能避免继承。要知道,继承实际上破坏了封装性。

 

Item 17:Design and document for inheritance or else prohibit it

              要么好好的设计继承关系并书写良好的说明文档,要么禁用继承。很多情况下,继承方式成为扩展现有类的首要选择,关于继承,有几点需要注意和提高警惕:

             A:构造函数不要调用可能会重写的方法,否则将出现难以预料的逻辑错误;

             B:在类中不要轻易调用可能会重写的方法,因为这样会加大子类重写时的复杂度,使用private的帮助方法来代替它们;

             C:在遇见Cloneable和Serializable时请绕行,非要实现它们的话,请遵守A、B规则,不要在相关方法内调用可能会重写的方法;

             D:好好的制定说明文档吧

             其实Item16说的已经说的很明白了,不要万不得已,不要轻易使用继承。

 

Item 18:Prefer interfaces to abstract classes

             优先使用interface,这个item主要讲了interface与抽象类在使用中的优缺点,并非某些参考书上一成不变的什么这个可以有变量,那个只能是有常量。

             接口提供多种实现的可能,但是相对抽象类来说,它更“死板”,也更稳定,公共接口一般不允许修改,而且实现接口不会破坏类之间的结构关系,它们之间没有继承关系。当你选择使用抽象类的时候,你就要面临it 17中讲得继承问题了。另外,给接口一个基本实现(Skeletal implementation)是一个不错的选择。

 

Item 19:Use interfaces only to define types

             不要用接口干其他的事,其中最常见的就是用它来定义常量,多方便,可以省略public static 几个关键字。但是作者不建议这么做,因为实现了这个接口的类将会用到这些常量,在未来的版本中,如果这些常量被废弃了,它让然要继续实现它,以保证程序的语法正确,这显然不合适。

            选用utility class 或者枚举来代替它吧,接口还是用来定义允许多种实现的类型吧。

 

Item 20:Prefer class hierarchies to tagged classes

             限定一个类只能创建一种实例对象,不要尝试通过添加tag来标记不同类型的实例,如果真的需要在类中使用tag 来区分不同类型的实例,那就使用继承结构。

             Tagged class,顾名思义,就是在class中使用一个或多个tag,然后

switch(tag){
    case TAG_1:
          instance = new TaggedClass(TAG_1):
    case TAG_2:
          instance = new TaggedClass(TAG_2):
    ...
}

 

Item 21:Use function objects to represent strategies

              使用对象引用来实现策略模式,看了一遍无甚感想

 

Item 22:Favor satic member classes over nonstatic

              优先使用静态内部类作为成员,这一节讲得非常好,将四种内部类分析的很透彻。

public class NestedClass {

	//static member class
	private static class StaticNested {
	}

	//nonstatic member class
	private class NonstaticNested {
	}

	protected void doSth() {
		StaticNested sn = new StaticNested();
		NonstaticNested nn = new NonstaticNested();
		//anonymous class 匿名类
		Runnable runable = new Runnable(){
			@Override
			public void run() {	}		
		};
		// local class 局部类
		class LocalClass implements Runnable, Comparable{

			@Override
			public void run() {				
			}

			@Override
			public int compareTo(Object o) {
				return 0;
			}
		}	
		LocalClass lc = new LocalClass();		
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		StaticNested nsn = new NestedClass.StaticNested();
		StaticNested sn = new StaticNested();
		NonstaticNested nn = new NestedClass().new NonstaticNested();
	}

}

上述四种内部类,从使用上说:

A,如果内部类需要从外部访问并且不要求与包含类的实例挂上关系,那么选择静态内部类,它与包含类的实例对象没有关联,可以看成一个稍微复杂一些的静态成员;

B,如果内部类的实例与包含类的示例息息相关,那么使用非静态内部类,

 new NestedClass().new NonstaticNested(); //outside
NonstaticNested nn = new NonstaticNested();//inside

注意非静态内部类因为与其包含类实例之间的关系,在资源和时间消耗上都远远超过静态类,请慎用;

C,在类不会与外界打交道,很简短而且可以确定不会拿类的名字干点啥的 ,可以选择匿名类,注意一定不要影响了代码可读性,而且匿名类不能有静态成员,只能同时实现一个接口或者继承一个基类;

D,如果匿名类很长,而且可能类名有潜在的作用,那么可以考虑使用局部类,它避免了匿名类的的一些短项,比如可以同时实现二个接口。

 

Item 23:Don't use raw types in new code

             不要使用原始类型参数,比如List,建议使用List<Object> List<?> List<String>

 

Item 24:Eliminate unchecked warnings

             尽可能的减少unchecked 警告信息,对于raw 类型的使用上,如果确信是类型安全的,可以使用@SuppressWarnings("unchecked")来避免警告。

 

Item 25:Prefer lists to arrays

              优先使用list。这一节对于list和array分析的很不错,主要包括以下几个方面:

              A,行为上的不同:array在运行时才确定元素的类型,而list(参数化的)在编译的时候就需要检查类型,以保证类型的安全。

              B,协同变化性(covariant),指的是array之间因存储元素的不同也会存在父子类型的关系,比如int[]是Object[]的一个子类,那么可以将int[]赋给Object[],而list<Integer>与list<Object>则是两个完全不同的集合。

              因此,无法创建泛型l的list类型的数组。

              示例:

		Object[] objs = new String[1];
		String[] strings = new String[1];
		int [] ints = new int[1];		
		objs = strings;
		objs[0] = 1; //java.lang.ArrayStoreException
		
		List<String>[] strs = new List<String>[1]; //Error:Cannot create a generic array of List<String>
		List<Long> longs = new ArrayList<Long>();
		longs.add(10L);
		Object[] objects = strs;
		objects[0] = longs;
		String element = strs[0].get(0);

            第一段代码就是针对数组的协同变化性和运行时类型检查,编译完全正确,运行时抛出java.lang.ArrayStoreException,第二段代码针对泛型list的数组,编译即出错。若不出错,想想后面的代码,strs[0].get(0)返回的是Long,而不是String,一个潜在的问题就出现了,ClassCastException。

           这里面还讲到一个概念——non-reifiable types:简单的讲一个non-reifiable type就是在运行时包含的信息要少于编译时,比如泛型的list,运行时它不会进行类型检查,而编译时则需要,当然一些特殊的list除外——List<?>。non-reifiable types都不能用来创建数组。

 

Item 26:Favor generic types

             优先考虑泛型的类和接口

 

Item 27:Favor generic methods

             优先考虑泛型的方法

 

Item28:Use bounded wildcards to increase API flexibility

             使用绑定的通配符提升API的灵活性

             读完这三个已经内牛满面了,作者Joshua Bloch不愧是Java Collection Framework的创始人,也只有他才能把泛型这个问题分析的如此透彻,很多概念和用法都还不是很了解,哎。。。。

 

Item 29:Consider typesagfe heterogeneous containers

              考虑使用类型安全的混杂容器

 

Item 30:Use enums to instead of int constants

              使用枚举代替整形常量

 

Item 31:Use instance fields instead of ordinals

              使用成员变量来代替使用自然顺序的枚举,特别是ordinal()方法的使用上,尤其要注意。

 

Item 32:Use EnumSet instead of bit fields

              使用EnumSet 代替bit类型的成员变量,就像SWT.NONE,SWT.READ_ONLY。我猜为什么SWT的实现很多都是用bit类型的成员组合,比如new Text(composite, SWT.BORDER | SWT.READ_ONLY),也许是SWT的出现比EnumSet要早缘故,先在我们就可以使用EnumSet.of(Style.BORDER, Style.READ_ONLY)来代替了。

 

Item 33:Use EnumMap instead of ordinal indexing

              EnumMap代替ordinal()方式的索引,他举了一个例子,就是液固气之间的转换,先用二维数组实现,然后用EnumMap<State, EnumMap<State, Transition>>实现,后者的确简洁很多,不过这个例子突然是我想起State模式,好像它用EnumMap实现真实绝配。

 

Item 34:Emulate extensiable enums with interfaces

             看了这一节,唯一的收获是发现enum也可以实现接口,不知道它能不能继承类呢?好像不能,只能实现接口。。。

 

Item 35:Prefer annotations to naming patterns

              优先使用注解(annotation),jdk1.5里添加了annotation这个功能,它的使用和实现与反射(reflect)关系紧密,Junit就是用annotation实现的。至于naming patterns就是说使用命名规则来区分某些特殊功能,比如test开头的函数为测试函数等。

              说道反射,突然想起一个问题,Class.forName("XX"),经常发现找不到class,为什么(联系Java Class loader机制)

 

Item 36:Consistently use the Override annotation

              随时给重写的方法加上“Override”

 

Item 37:User Marker interfaces to define types

              Marker interface 指的是没有扩展新方法的新类型,仅仅声明一下它是一个新的类型,但没有扩展行为,比如Cloneable、Serializable等,书中还提到了使用annotation添加类型说明,但是与Marker interface相比,后者的优势是,它显示定义了一种新的类型。

 

Item 38:Check parameters for validity

              检查参数的合法性

 

Item 39:Make defensive copies when needed

              使用defensive copy保护对象的不变性。对于Java来说,引用类型的常量仅限定了其不能被重新赋值,但是仍然有可能修改其属性,调用修改状态的方法,因此对于这种常量,注意使用防御性质的复制来保护其不变性。

              注意defensive copy 与 clone()方法的区别

 

Item 40:Design method signatures carefully

              函数签名设置的原则:

              1,取名,按照公认的规则取名

              2,不要在一个类中放置太多的方法

              3,避免太多的参数, 可以通过几种方法来减少参数的个数:子方法,辅助子类,build模式

              4,优先使用interface类型的参数,比如对于HashMap,使用Map就行了

              5,对于boolean类型的参数,考虑用枚举代替

 

Item 41:Use overloading judiciously

              适当的使用方法重载

 

Item 42:Use varargs judiciously

               明智的使用变长参数           

 

Item 43:Return empty arrays or collections, not nulls

              使用空集合代替null返回值,以避免额外的null检查或错误

 

Item 44:Write doc comments for all exposed API elements

             这个是关于API注释的,其中{@code} 和 {@literal} 标签比较有用,其他的暂时用不着呢。。。

 

Item 45:Minimize the scope of local variables

              缩小局部变量的作用域

 

Item 46:Prefer for-each loops to traditional for loops

              使用for-each循环代替传统的for循环

 

Item 47:Know and use the libraries

              理解和使用库,这个作者建议开发者至少熟悉java.lang.*、java.utl.*以及部分的java.io.*下的内容

(待续)

2
0
分享到:
评论
8 楼 salever 2010-10-09  
Item 76: Write readObject methods defensively
                 编写具有“防御性质”的readObject方法

Item 77:For instance control, prefer enum types to readResolve
              
Item 78:Consider serialization proxies instead of serialized instances
7 楼 salever 2010-10-08  
Item 74: Implement Serializable judiciously
               明智的使用序列化,这一节开始讲序列化,可惜不是很懂,要补补

Item 75: Consider using a custom serialized form
               考虑使用自定义的序列化,而不是默认的
6 楼 salever 2010-09-30  
Item 69:Prefer concurrency utilities to wait and notify
              尽量使用concurrency里的工具方法,而不是原始的wait和notify方法。这一节讲了两个java.util.concurrency下的工具集合:concurrenct collection和synchronizer。前者比较常用的是ConcurrentHashMap等,后者则有CountDownLatch和CyclicBarrier,用他们可以很方便的实现线程控制。

Item 70:Document thread safety
              用文档明确的说明线程的安全性,有几个级别Immutable、ThreadSafe和ThreadUnsafe。这一节还提到同步控制的几个原则:double-check,如何用private lock object防止拒绝服务攻击等

Item 71:Use lazy initialization judiciously
              明智的使用延迟初始化,延迟初始化可以提高性能,但是一定要注意使用的时机。很多时候,正常的初始化就够了。

Item 72:Don't depend on the thread scheduler
              不要依靠线程的调度机制,这里还提到线程的个数问题,这个个数与CPU的数量并没有多大的关系,只是记得:线程不要频繁的切换busy-wait状态,以及在不工作的时候停止就行了。

Item 73:Avoid thread groups
              thread group 不是一个好东西,最好离它远远地。
5 楼 salever 2010-09-26  
Item 66: Synchronize access to shared mutable data
               同步访问共享的可变数据,这节开始讲同步的常见问题。

Item 67: Avoid excessive synchronization
               避免过度的使用同步,主要是在同步中避免使用alien 方法,所谓alien方法,就是可能被子类重写的,或者是可能转交对象控制权的方法(function object)

Item 68: Prefer executors and tasks to threads
               并非所有的线程都只能用Thread实现,java.util.concurrent 下面还有Executor和Task等,也可以实现新建线程处理任务,而且,Executor还提供了安全的终止任务的方法shutDown(),看来有必要好好学学java.util.concurrent
4 楼 salever 2010-09-25  
Item 61: Throws exceptions appropriate to the abstraction
               根据抽象的程度,抛出合适的异常,这里讲了一个exception translation,所谓的异常翻译,把低级别的异常处理为高级别的异常来抛出,这里的级别是对应抽象的程度而言的。

Item 62: Document all exceptions thrown by each method
               对方法抛出的所有异常,都给出详细的说明文档

Item 63: Include failure-capture information in detail messages
               在异常的信息中包括失败时的快照信息

Item 64: Strive for failure atomicity
               尽力保持程序执行失败的原子性,主要是为了保证对象的状态的正确性,一般的可以通过在方法的最开始进行参数、前置条件的检查等来保证。

Item 65: Don't ignore exceptions
               不要忽略异常,即使真的不需要处理,最好也加上注释
3 楼 salever 2010-09-21  
Item 56: Adhere to generally accepted naming conventions
               注意遵守命名规则,包括字面上和语法上的,关于Java的命名规则,很多地方都讲到了。

Item 57: Use exceptions only for exceptional conditions
               除非出现了异常的情况才使用异常(Exception),java的异常处理非常强大,但是需要主要在正确的场合下使用

Item 58: Use checked exceptions for recoverable conditions and runtime 
               exceptions for programming errors
               对于Java中的三种可以catch的类型:checked exception、runtime exception和error,作者建议在出现了异常并且异常可以恢复的,使用checked exception,这样并不影响程序的执行。而后两者的出现将暂停当前执行的线程,如果用户没有处理,那么JVM将终止当前线程,当然你可以根据情况捕获这些异常。

Item 59: Avoid unnecessary use of checked exceptions
               不要滥用checked exception

Item 60: Favor the use of standard exceptions
               多使用下标准异常吧,比较常用的有:IllegalArgumentException、IllegalStateException、NullPointException、IndexOutOfBoundsException、ConcurrentModificationException、UnsupportedOperationException等
2 楼 salever 2010-09-20  
Item 53:Prefer interfaces to reflection
              优先使用接口,而不是反射。反射机制是Java的一个特色,但是不要滥用,它相对来说比较慢,出错的几率更高,而且代码的编写和阅读更难。除非对于那些在编译的时候不能确定的class,否则不要轻易使用反射。

Item 54:Use native methods judiciously
              明智的使用本地方法
              Java提供了JNI 来调用本地方法,以补充平台相关性。有一个原则,不要以提升效率的原因去使用JNI,因为JNI 并非一个提升效率的捷径,相反它更慢,而且容易出错,而且也限制了系统的平台移植性。

Item 55:Optimize judiciously
              小心的优化
              优化一直是一个津津乐道的话题,对于优化,作者给出三条格言:
              1,许多计算机方面的错误都是因为进了没有必要的优化而导致的,包括一些极度愚蠢的错误;
              2,不要为了一些细小的效率提升而进行优化,据说97%的情况下不成熟的优化行为才是万恶之源;
              3,时刻记得2个优化原则:不要优化;除非你有了一个明确和可行的优化方案
1 楼 salever 2010-09-19  
Item 48:Avoid float and doubel if exact answers are required
              避免在精确进算的时候使用浮点数和双精度数
              System.out.println(1.03 - .42); 看看结果就知道了

Item 49:Prefer primitives types to boxed primitives
              优先使用原始数据类型
              记得有一回面试的时候,面试官还煞有其事的问题box和unbox,好像很高深似地,可惜当时不怎么注意。。。
              原始数据类型仅保存值,都有默认的初始化值,而且效率更高,除非为了Collection相关的元素,一般选择使用原始类型就行了。

Item 50: Avoid strings where other types are more appropriate
               不要滥用string

Item 51: Beware of performance of string concatenation
               字符的连接操作优先使用StringBuffer

Item 52: Refer to objects by their interfaces
               除非没有对应的接口,否则使用接口来代替实际的class类型        
        
  

相关推荐

    读书笔记:Effective Java中文版 第2版.zip

    读书笔记:Effective Java中文版 第2版

    读书笔记:Effective Java 中文版(第2版)总结 (美)Joshua Bloch 著.zip

    读书笔记:Effective Java 中文版(第2版)总结 (美)Joshua Bloch 著

    effectiveJava的笔记

    这本书的第三版包含了大量更新,涵盖了Java语言和平台的新发展,如Java 8和Java 9的新特性。以下是对《Effective Java》笔记中可能涉及的关键知识点的详细解读: 1. **单例模式**:书中强调了如何正确实现单例模式...

    Effective Java.zip

    1. **第2章 创建和销毁对象** - 单例模式:讲解了如何正确实现单例类,避免多线程环境下的并发问题。 - 构造函数:强调构造函数应简洁,避免在构造过程中执行复杂操作。 - 工厂方法:介绍工厂方法模式,作为创建...

    Effective-Java读书笔记(上)

    ### Effective Java读书笔记(上) #### 第一章 引言 本书主要针对Java开发者提供了大量实用的编程指导建议,帮助读者提升代码质量和程序性能。在本章节中,我们将重点介绍对象的创建与销毁,以及一些重要的设计...

    java学习PDF下载地址全 百度云盘下载

    11. **Java EE**:如果PDF深入,可能会介绍Java企业版,包括Servlet、JSP、EJB、JDBC等Web开发技术。 12. **设计模式**:介绍常见的设计模式,如单例、工厂、观察者等,提升代码的可读性和可维护性。 此外,这份...

    java逻辑思维笔试题-effective-java-3rd-edition:有效的Java第3版注释

    第三版笔记 章节索引 02 - 创建和销毁对象 03 - 所有对象通用的方法 04 - 类和接口 05 - 泛型 06 - 枚举和注释 07 - Lambda 和流 08 - 方法 09 - 通用编程 10 - 例外 11 - 并发 12 - 序列化 第 2 章 - 创建和销毁...

    5本java学习用书

    2. **《Effective Java》**:由Joshua Bloch撰写,是Java开发者的经典之作。书中列举了23个编程实践,讲解如何编写高效、可维护的Java代码。例如,它涵盖了枚举优于常量、避免使用原始类型、优先考虑泛型、以及何时...

    java-note:Java学习笔记

    ├ data_structure 数据结构与算法分析_Java语言描述(第2版) ├ effective_java Effective Java 中文第二版 ├ jvm 深入理解Java虚拟机:JVM高级特性与最佳实践 ├ lambda JAVA 8实战 ├ netty Netty权威指南 ...

    java书籍

    3. **《Effective Java》第二版(effective-java-2)**:这是Joshua Bloch的经典之作,书中列举了23个编程项,提供了关于如何编写更高效、可读性更强的Java代码的实用建议。它涉及的主题包括枚举类型、泛型、匿名内部...

    八种编程语言毕业设计参考文献

    《Java框架设计》第一版**(2012):介绍了Java中常用的框架及其设计理念,适合希望深入了解Java框架的开发者。 9. **王映龙.《JavaEE实用教程》**(2011):提供了JavaEE的实际应用场景和解决方案,适合进行Web应用...

Global site tag (gtag.js) - Google Analytics