《Effective Java》读书笔记 - 8.通用编程
Chapter 8 General Programming
Item 45: Minimize the scope of local variables
local variables应该在他们要被用的地方声明,而不应该,比如,全部声明在方法开头。而且在声明的时候,记得要初始化。有个例外,比如你的IQueryable<T> localv
需要在接下来的if else中分别初始化成不同的值,那么你可以在if之前先声明(我自己瞎举的例子)。
如果某个local variable只是这个循环需要的,那么用for(包括foreach)比while好。因为比如最经典的for(int i = 1;i<N;i++)如果用while写的话,要在while块前面先写int i = 1,这样就很不好了,因为这个i在while执行完毕后就不需要了,这时候如果你不小心把另一个变量写成了i,那么编译器并不会报错,而for就会报错(因为i的生命周期已经结束了)。
BTW,如果每次循环都需要计算某个值,而这个值每次都一样的话,可以放到for的“声明块”里去,比如:
for (int i = 0, n = expensiveComputation(); i < n; i++) {
doSomething(i);
}
Item 46: Prefer for-each loops to traditional for loops
在1.5版本之前,遍历一个集合或数组的方式如下:
// No longer the preferred idiom to iterate over a collection!
for (Iterator i = c.iterator(); i.hasNext(); ) {
doSomething((Element) i.next()); // (No generics before 1.5)
}
// No longer the preferred idiom to iterate over an array!
for (int i = 0; i < a.length; i++) {
doSomething(a[i]);
}
相比foreach的写法,上面这种老写法可读性较差,而且容易出错,foreach写法:
// The preferred idiom for iterating over collections and arrays
for (Element e : elements) {
doSomething(e);
}
特别是在嵌套多层遍历的时候,foreach的优势更能体现,如下所示:
// not preferred
for (Iterator<Suit> i = suits.iterator(); i.hasNext(); ) {
Suit suit = i.next();
for (Iterator<Rank> j = ranks.iterator(); j.hasNext(); )
deck.add(new Card(suit, j.next()));
}
// Preferred idiom for nested iteration on collections and arrays
for (Suit suit : suits)
for (Rank rank : ranks)
deck.add(new Card(suit, rank));
只要是实现Iterable<E>
接口的类,都可以用foreach去遍历,如果你写的类代表了a group of elements,那么你也可以让它实现这个接口。
以下几种情况不能用foreach:
一.如果你在遍历的时候需要删除某些元素,那么你只显式地用一个iterator,然后用它的remove方法。
二.如果你需要修改某些元素的值。
三.如果你要“平行地”遍历多个集合(或数组)的时候,比如:
for (int i = 0,j = 0; i < a.length && j < b.length; i++,j++){...}
Item 47: Know and use the libraries
书上举得例子是Random.nextInt(int n),返回一个均匀分布的0到n的随机数,如果你自己实现这个方法的话,估计肯定分布得不均匀。所以说,用标准库的好处就在于你利用了写这个库的专家的知识和其他所有用过这个库的人的经验,而且不需要你重新发明轮子。
每一个programmer都应该熟悉java.lang和java.util,最好也能掌握java.io,其他的package可以需要的时候再看。
Item 48: Avoid float and double if exact answers are required
float和double执行的是二进制浮点运算(binary floating-point arithmetic),能够提供较为精准的快速近似计算,主要用于科学计算和工程计算。所以他们并不提供精准的结果,所以不适用于需要精确结果的场合,尤其是货币。比如想要让一个float或double精确地表示0.1是不可能的,比如System.out.println(1.03 - .42)的输出结果是0.6100000000000001。解决办法是用BigDecimal, int,或long来代替,BigDecimal需要额外的性能开销和影响可读性,用int和long比较好,只是你需要自己处理好十进制小数点。但如果数值大于18位,就得用BigDecimal。
Item 49: Prefer primitive types to boxed primitives
对boxed primitives用 == 运算符几乎是肯定错误的,因为这时候比较的是identity,而不是内容。如果对一个primitive和一个boxed primitives作比较,那么boxed primitive被自动拆箱,如果它恰好是个null,那么就NullPointerException。所以说一定要分清到底是primitives还是boxed primitives。有一些情况下必须用boxed primitives:作为集合元素的是时候;作为泛型参数的时候;调用反射方法的时候。
Item 50: Avoid strings where other types are more appropriate
Strings不适合代替其他的类型。当数据从文件,网络,或键盘输入传进来的时候,经常是以字符串的形式存在,但是很多人就不管了。正确做法是应该把这种string representation转换成他们应该是的类型,比如如果是int,就转换成int。
Strings不适合代替enum类型。
如果你需要一个东西,它有多个组件,那么就老老实实写个类,别用String偷懒,比如:
String compoundKey = className + "#" + i.next();
这行代码的意思是,你需要一个key,由一个className和一个数字组成,然后由一个#作为分隔符隔开。这种做法非常的不好。
不要用string来grant access to some functionality,书上举的例子是ThreadLocal,这个我看的不是很懂,但是如果你复习到这里也不用纠结了,跳过就好,相信我。
Item 51: Beware the performance of string concatenation
这个很熟悉了不解释了,需要的时候用StringBuilder吧。
Item 52: Refer to objects by their interfaces
在head first设计模式中也提过这点,这样做是为了更好的灵活性。当然这个原则不是绝对的,有很多情况下没法满足这个原则,比如String,Random,或者有时候只能用基类(一般都是抽象的)来作为引用类型。
Item 53: Prefer interfaces to reflection
使用反射虽然很强大,但是代价是:
一.You lose all the benefits of compile-time type checking。
二.代码冗长且可读性差。
三.Performance suffers。
而这个item的意思是:如果某个类在编译时不存在,所以你不得不用反射来创建他的实例的时候,你可以用一个interface类型(当然,必须是这个类实现的interface,或者继承的某个super class)来refer to它的对象,从而既得到反射的强大,也可以从一定程度上得到编译时的好处,比如你可以先用反射创建一个对象,但用一个编译时类型来refer to它:
Set<String> s = (Set<String>)Class.forName(...).newInstance();
一旦创建完成这个对象,这里这个s就和其他任何Set<String>
类型的对象没任何区别了,你可以,比如对s进行添加元素的操作:s.add(...),而不需要用反射来调用这个方法。
Item 54: Use native methods judiciously
The Java Native Interface (JNI)允许Java应用程序调用本地方法(native methods),一般用于一些platform-specific facilities,或performance-critical parts(不建议这么做,因为JVM已经越来越成熟了)。尽量不要用本地方法,第一它们不安全,不受JVM保护;第二会影响移植性,第三难以调试并且会造成额外的性能开销(在进和出本地方法的时候)。
Item 55: Optimize judiciously
关于优化有这么一条真理:it is easy to do more harm than good。性能可能会与设计构架相冲突,不要为了性能而牺牲合理的结构,并且必须在设计过程中考虑性能(如果构架成型后,除非全部重写系统,否则很难再改进性能)。比如,如果你决定让你的API返回一个mutable的东西,那么你每次都要进行defensive copy,就会影响性能。
不要去计较性能上的一些小小的得失,在试着优化后要进行性能对比测试。
Profiling tools(性能剖析工具)可以帮助你找到那些需要优化的地方。
有很多因素会影响到性能,比如JVM的不同实现,不同的CPU等等。
你的原则应该是:do not strive to write fast programs—strive to write good ones; speed will follow。
Item 56: Adhere to generally accepted naming conventions
Package names应该是小写字母(很少包括数字),然后把你的域名反着写一下作为开头,其余部分应该精简而有含义,比如util rather than utilities,一般都应该只包含一个单词或缩写。
Class,interface names, including enum and annotation type names的首字母大写,尽量不要用缩写,如果要用的话,最好也是每个单词的首字母大写,比如HttpUrl。
Method and field names的首字母小写。
constant fields应该是全部大写,用下划线分开。enum constants就是。
Local variable与方法命名类似,并且可以使用缩写。
Type parameter一般就一个字母:T代表任意type, E代表一个集合的element,K代表key ,V代表value,X代表exception. 一堆不同的泛型参数可以用T, U, V或T1, T2, T3。
《Effective Java》读书笔记 - 8.通用编程的更多相关文章
- Effective Java 读书笔记之七 通用程序设计
一.将局部变量的作用域最小化 1.在第一次使用变量的地方声明 2.几乎每个变量的声明都应该包含一个初始化表达式:try-catch语句是一个例外 3.使方法小而集中是一个好的策略 二.for-each ...
- Effective java读书笔记
2015年进步很小,看的书也不是很多,感觉自己都要废了,2016是沉淀的一年,在这一年中要不断学习.看书,努力提升自己 计在16年要看12本书,主要涉及java基础.Spring研究.java并发.J ...
- Effective Java读书笔记完结啦
Effective Java是一本经典的书, 很实用的Java进阶读物, 提供了各个方面的best practices. 最近终于做完了Effective Java的读书笔记, 发布出来与大家共享. ...
- Effective Java 读书笔记(一):使用静态工厂方法代替构造器
这是Effective Java第2章提出的第一条建议: 考虑用静态工厂方法代替构造器 此处的静态工厂方法并不是设计模式,主要指static修饰的静态方法,关于static的说明可以参考之前的博文&l ...
- Effective Java读书笔记——第三章 对于全部对象都通用的方法
第8条:覆盖equals时请遵守通用的约定 设计Object类的目的就是用来覆盖的,它全部的非final方法都是用来被覆盖的(equals.hashcode.clone.finalize)都有通用约定 ...
- [Effective Java 读书笔记] 第8章 通用程序设计
本章主要讲了以下几条基本的JAVA编程原则: 1.将局部变量的作用域控制在最小,在使用时才定义 2.for-each优于for循环 有三个例外(1,2点主旨就是,for each只能用于读取,不能用于 ...
- [Effective Java 读书笔记] 第三章 对所有对象都通用的方法 第八 ---- 九条
这一章主要讲解Object类中的方法, Object类是所有类的父类,所以它的方法也称得上是所有对象都通用的方法 第八条 覆盖equals时需要遵守的约定 Object中的equals实现,就是直接对 ...
- Effective Java读书笔记--对所有对象都通用的方法
1.覆盖equals请遵守通用规定.不需要覆写equals的场景:a.类的每个实例都是唯一的.b.类不需要提供"逻辑相等"的测试功能.c.超类已经覆盖了equals的方法.d.类是 ...
- Effective Java 读书笔记之二 对于所有对象都通用的方法
尽管Object是一个具体的类,但设计它主要是为了扩展.它的所有非final方法都有明确的通用约定.任何一个类在override时,必须遵守这些通用约定. 一.覆盖equals时请遵守通用的约定 1. ...
随机推荐
- springboot2.0和Druid整合配置数据源
1. idea使用spring 初始化工具初始化springboot项目(要选中web) 下一步,下一步 2. 在pom.xml中,引入Druid连接池依赖: <dependency> & ...
- 手把手教你用Python搭建自己的量化回测框架【均值回归策略】
手把手教你用Python搭建自己的量化回测框架[均值回归策略] 引言 大部分量化策略都可以归类为均值回归与动量策略.事实上,只有当股票价格是均值回归或趋势的,交易策略才能盈利.否则,价格是随机游走的, ...
- myql命令行乱码问题,以及设置数据库编码
使用命令修改数据库编码格式参见:https://www.cnblogs.com/clsn/p/8047028.html#auto_id_3 命令行乱码设置修改参见:https://www.cnblog ...
- js 学习四 对象应用 吃货游戏
游戏来源于 Mdn学习网站: 该例子用于对象的理解非常有效(建议看完上面网站的内容在开始练习) 弹球 body { margin: 0; overflow: hidden; font-family: ...
- vue-cli解决兼容ie的es6+api问题
官网:https://cli.vuejs.org/zh/guide/browser-compatibility.html#usebuiltins-usage https://github.com/vu ...
- heartbeat如何避免脑裂
heartbeat避免脑裂的方法 1)增加冗余的心跳线,例如双线条线,尽量减少脑裂发生的机会 2)启用磁盘锁:正在服务的一方锁住了共享磁盘,脑裂发生时,让对方完全抢走资源,如果占用资源的一方不解锁 , ...
- 关于WPA/WPA2 4次握手
简单描述一下WPA/WPA2的4次握手中的一些关键词: WPA/WPA2使用4次握手的方式来产生所需要的密钥.四次握手通过一系列的交互,从PMK(Pairwise Master Key)生成PTK(P ...
- SQL小操作
用string.Format格式化参数 string sqlCmd = string.Format("select NO from [dbo].[SendAcerData] where BA ...
- DevExpress WPF v19.1新版亮点:Data Editors等控件新功能
行业领先的.NET界面控件DevExpress 日前正式发布v19.1版本,本站将以连载的形式介绍各版本新增内容.在本系列文章中将为大家介绍DevExpress WPFv19.1中新增的一些控件及部分 ...
- 大数据(量上GB的)查看命令
大数据查看指令 cmd中(tab键可补全) type 文件名:全部查看 more 文件名:Enter键,按一下查看一页