effective java 读书笔记_effective java 读书笔记

第二章:创建和销毁对象

第7条:避免使用终结方法

final、finally、finalize的区别:

final:修饰符,关键字,可以修饰成员、方法和类,如果类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。将变量或者方法声明为final,可以保证他们在使用中不被改变。

finally:一般是用于异常处理中,提供finally块来执行任何的清楚操作,try{} catch(){} finally{}。

finalize:用于垃圾回收,在java中,允许使用finalize()方法在垃圾收集器将对象从内存中清理出去之前做必要的清理工作。

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

第8条:覆盖equals时请遵守通用约定

使用==操作符检查“参数是否为这个对象的引用”。

使用instanceof操作符检查“参数是否为正确的类型”。

把参数转换成正确的类型。

对于该类中的每个“关键”域,检查参数中的域是否与该对象中对应域相匹配。

当覆盖玩equals方法之后,应该问自己三个问题:它是否对称的、传递的、一致的?

warning:

覆盖equals时总要覆盖hashCode;

不要企图让equals方法过于智能;

不要将equals声明中的Object对象替换为其他的类型;

public boolean equals(Myclass myclass){

.....

}

第9条:覆盖equals时总要覆盖hashCode

每个覆盖了equals方法的类中,也必须改服hashCode方法;

相等的对象必须具有相等的散列码;

为不相等的对象产生不相等的散列码;

不要试图从散列码计算中排除一个对象的关键部分来提高性能;

第10条:始终要覆盖toString()

java.lang.Object提供了一个toString()方法,其结果为类名+@+hashCode十六位无符号表示方法。覆盖toString()方法,获取简洁的类toString()结果,便于程序中类输入结果的阅读。

@Override

public String toString() {

return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);

}

第11条:谨慎地覆盖clone

如果你覆盖了非final类中的clone方法,则应该返回一个通过调用super.clone而得到的对象;

clone方法就是另一个构造器,你必须确保不会伤害到原始的对象,并确保正确地创建克隆对象中的约束条件;

第12条:考虑实现Complarable接口

Object中并没有声明compareTo()方法,compartTo()是Comparable接口的唯一方法,继承此接口的类,可以实现类内部排序;

public interface Comparable{

public int compareTo(T o);

}

其返回结果为int型,当对象小于、等于、大于指定对象T时,返回结果分别为负整数、零和正整数;

第4章:类与接口

第13条:使类和成员的可访问性最小化

尽可能地使每个类或者成员不被外界访问;

可访问性:

私有的private;

包级私有的package-private,声明该成员包内部的任何类都可以访问这个成员,不对成员做任何访问级别限制,则默认为包级私有;

受保护的protected,类及其子类可访问protected级别成员;

公开的public,在任何地方都可以访问该成员;

第14条:在公有类中使用访问方法而非公有域

公有类永远不要暴露可变的域。虽然这还是有问题,但是让公有类暴露不可变的域其危害比较小。

第15条:使可变性最小化

为了使类成为不可变,要遵循下面五条规则:

不要提供任何会修改对象状态的方法;

保证类不会被扩展;

使所有的域都是final的;

使所有的域都成为私有的;

确保对于任何可变组件的互斥访问;

第16条:复合优于继承

只有子类真正是超类的一部分时,才可以使用继承,即当子类只有包含超类的属性时才能使用继承;

继承的功能非常强大,但是由于继承违背了封装原则,因此也存在诸多问题。可以用复合和转发机制来代替继承,尤其是当存在适当的接口实现包装类时,包装类比子类更加健壮,功能也更强大;

第17条:要么为继承而设计,并提交文档说明,要么就禁止继承

第18条:接口优于抽象类

第19条:接口只用于定义类型

接口只应用于定义类型,而不应该被用来到处常量;

第20条:类层次优于标签类

标签类过于冗长,容易出错,并且效率低下;

第21条:用函数对象表示策略

第22条:优先考虑使用静态成员类

嵌套类:是指被定义在另一个类的内部的类;

嵌套类分类:静态成员类、非静态成员类、匿名类、局部类;

第6章 枚举和接口

第30条:用enum代替int常量

枚举类型:是指由一组固定的常量组合成合法值得类型,例如一年的春夏秋冬四个季节;

为了将数据与枚举常量关联起来,得声明实例域,并编写一个带有数据并将数据保存在域中的构造器。

第31条:用实例域代替序数

永远不要根据枚举的序数导出与它关联的值,而是将它保存在一个实例域中。

第32条:用EnumSet代替位域

用OR位运算将几个常量合并到一个集合中,称作位域;

EnumSet类可以有效地从单个枚举类型中提取多个枚举值;

eg:

public enum Style{

BOLD,

ITALIC,

UNDERLINE

}

Set

由于枚举类型要用在集合set中,所以没有理由用位域表示它。

第33条:用EnumMap代替序数索引

EnumMap继承AbstractMap实现Map接口,其实现Map所有操作的同时,具有获取键列表和值列表功能;

getKeyUniverse()返回键列表,values()返回值列表;

第34条:用接口模拟可伸缩的枚举

虽然无法编写可扩展的枚举类型,却可以通过编写接口以及实现该接口的基础枚举类型,对它进行模拟;

第35条:注解优先于命名模式

一般使用命名模式,表明有些程序需要通过某种工具或者框架进行特殊处理;

java 元注解:

1.@Target,

2.@Retention,

3.@Documented,

4.@Inherited

有了注解,就不需要再使用命名模式了;

第36条:坚持使用override注解

使用@Override注解,表示该方法覆盖超类中的方法;此注解保留源码级别,当java文件被编译后,@Override会被去除;使用此注解便于程序员对程序的理解,此外编译器会根据此注解对无意识的覆盖给予提示;

第37条:用标记接口定义类型

标记接口:是没有包含方法声明的接口,例如:Serializable就是一个标记接口,通过实现此接口,表明类可以被序列化。

第7章 方法

第38条:检查参数的有效性

对参数的任何限制都是件好事。再设计方法时,应该使它们尽可能的通用,并符合实际需要。

每当编写方式或者构造器的时候,应该考虑它的参数有哪些限制。应该把这些限制写在文档中,并且在这个方法体的开头处,通过显式的检查来实施这些限制。

第39条:必要时进行保护性拷贝

类的客户端会尽其所能来破坏这个类的约束条件,因此你必须保护性地设计程序。

保护性拷贝是在检查参数的有效性之前进行的,并且有效性检查是针对拷贝之后的对象,而不是针对原始对象。

对于参数类型可以被不可信任方子类话的参数,请不要使用clone方法进行保护性拷贝。

保护性拷贝示例

public Date start(){

return new Date(start.getTime());

}

第40条:谨慎设计方法签名

谨慎的选择方法名称,应该始终遵循标准的命名习惯;

不要过于追求提供便利的方法;

避免过长的参数列表,可以通过辅助类缩短参数列表;

第41条:慎用重载

永远不要导出两个具有相同参数目的的重载方法

第42条:慎用可变参数

在定义参数数目不定的方法时,可变参数方法时不种很方便的方法,但是它们不应该过度滥用。如果使用不当,会产生混乱的结果。

第43条:返回零长度或者集合,而不是null

返回类型为数组或集合的方法没理由返回null,应该返回零长度的数组或集合;

第44条:为所有导出的API元素编写文档注释

第八章 通过程序设计

第45条:将局部变量作用域最小化

将局部变量最小化,可以增强代码的可读性和可维护性,并降低错的可能性。

要使局部变量的作用域最小化,最有力的方法就是在第一次使用它的时候声明;

第46条:for-each循环优先于传统的for循环

java1.5发行版本中引入for-each循环,通过完全隐藏迭代器或者索引变量,便面了混乱和出错的可能。eg:

for(Element e : elements){

doSomeThing(e);

}

有三种情况无法使用for-each循环:

过滤--如果需要遍历集合或者数组,并删除指定的元素;

转换--如果需要遍历列表或者数组,并取代它不分或者全部的元素值;

平行迭代--如果需要并行地遍历多个集合,就需要显式地控制迭代器或者索引变量,以便所有迭代器或者索引量都可以得到同步前移;

第47条:了解和使用类库

java.io java.lang java.util java.util.concurrent类库是每个程序员都应该学习的;

多了解类库,多阅读类库实现原理及实现方式,类库的代码比你自己编写的代码更好一些,并随着时间推移而不断改进。

第48条:如果需要精确的答案,避免私用floate和double

使用BigDecimal代替floate和double

第49条:基本类型有限装箱基本类型

基本类型与基本装箱类型的区别:

基本类型只有值,装箱基本类型则具有它们的值不同的同一性;

基本类型只有功能完备的值,而每个装箱基本类型除了它对基本类型的所有功能值之外,还有个非功能值:null

基本类型比装箱基本类型更节约时间和空间

第50条:如果其他类型更合适,避免使用字符串

字符串不适合代替其他值类型

字符串不适合代替枚举类型

字符串不适合代替能力表

如果可以使用更加合适的数据类型,或者可以编写更加适当的数据类型,就应该避免使用字符串

第51条:当心字符串连接的性能

为了获取能够接受的性能,请使用StringBuilder代替String

第52条:通过接口引用对象

如果有合适的接口类型存在,那么对于参数、返回值、变量和域来说,就都应该使用接口类型进行声明;

第53条:接口优先于反射机制

核心反射机制:提供了“通过程序来访问关于已装载的类的信息”的能力;

第54条:谨慎地使用本地方法

本地方法是指用本地程序设计语言(c或者c++)来编写的特殊方法;

本地方法时不安全的,使用本地方法的应用程序不再能免受内存毁坏错误的影响。因为本地语言是平台相关的,使用本地方法的语言不再是可移植的。

第55条:谨慎地优化

要努力编写好的程序而不是快的程序

每次试图优化之前和之后,要对性能进行测量

第56条:要遵循普遍的命名规范

跟着项目走,写代码时重视命名规范

....未完待续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值