Effective Java 第九章-通用编程学习总结
发布日期:2021-06-29 16:46:10 浏览次数:2 分类:技术文章

本文共 3441 字,大约阅读时间需要 11 分钟。

                                                                                                                              作者:田超凡

版权所有,转载请注明原作者,仿冒侵权必究法律责任

 

1 局部变量作用域尽可能减小

1.1 要使局部变量的作用域最小化 ,最有力的方法就是在第一次要使用它的地方进行声明

1.2 几乎每一个局部变量的声明都应该包含一个初始化表达式

1.3 for/foreach/iterator/while应用场景

对于固定次数、迭代变量作用域仅限迭代主体,涉及到迭代索引、单元迭代的循环尽可能用for

对于固定次数、迭代变量作用域仅限迭代主体,单次迭代涉及大量业务逻辑操作且都依赖迭代项、保证较强稳定性和可读性,尽可能用foreach

对于迭代过程中涉及对迭代项的复杂操作,如频繁查询删除,则尽可能用iterator迭代器

对于不固定次数,迭代变量作用域>迭代主体,尽可能用while循环

1.4 方法中的局部变量尽可能单一化,命名要根据层次和具体作用的业务点适当进行调整,命名要按照编码规约清晰明了,提高代码可读性和可维护性。

1.5 对于方法中的局部变量需要在调用的多个方法之间来回流转时,一定要注意形参命名和实参命名尽可能保持一致,以保证调用逻辑清晰,对于需要获取返回值的情况返回值命名一定要规范

1.6 根据单一职责原则,一个方法尽可能只做一件事,因此方法中定义的局部变量尽可能不要在多个方法之间来回引用。对于需要组装多个方法实现一段业务逻辑的情况建议定义一个单独的方法作为骨架进行组装

 

 

2 多用增强型for循环(foreach),少用for/while

1 减少出错次数和概率,多用foreach循环

2 从根本上杜绝ArrayIndexOutOfRoundsException/NullPointerException,多用foreach循环

注意:以下几种情形无法使用foreach:

1 解构过滤:迭代过程中删除或更新集合元素

2 转换:根据索引获取数组/集合元素的情况

3 平行迭代:并行遍历多个集合的情况

 

※ 扩展:巧用lambda表达式实现各类集合操作

https://blog.csdn.net/bitcarmanlee/article/details/70195403

 

 

3 灵活使用第三方类库中的API,不要重复造轮子

1 通过使用标准类库,可以充分利用这些编 写标准类库的专家的知识,以及在你之前的其他人的使用经验

2 一般而言,类库的代码可能比你向己编写的代码更好一些,并且会随着时间的推移而不断改进 这并不是在质疑你作为一个程序员的能力 从经济角度的分析表明:类库代码受到的关注远远超过大多数普通程序员在同样的功能上所能给予的投入

 

 

※ 扩展:从Apache common库常用API看起

 

 

4 巧用BigDecimal实现精度控制,少用float/double

1 float double 类型尤其不适合用于货币计算

2 使用 BigDecimal 允许你完全控制舍入,每当一 个操作涉及舍入的时候,你都可以从 种舍入模式中选择其- 如果你正通过合法强制的舍 入行为进行商务计算,使用 BigDecimal 是非常方便的

3 如果数值可能超过 18 位数字,必须使用 BigDecimal

 

 

5 多用基本类型,少用包装类

1 当在一项操作中混合使用基本类型和包装类时,包装类就会自动拆箱,此时如果包装类实例是空,就会抛出NPE

2 自动装箱减少了使用装箱基本类型 性,但是并没有 少它的风 当程序用==操作符比较两个装箱基本类型时,它做 了个同一性比较,这几乎肯定不是你所希望的 当程序进行涉及装箱和拆箱基本类型的混 合类型计算时,它会进行拆箱, 当程序进行拆箱时,会抛出 NullPointerException 最后,当程序装箱了基本类型值时,会导致较高的资源消耗和不必要的对象创建。

 

 

※ 扩展:打开包装类源码一探究竟-装箱拆箱原理

 

 

6 能用具体类型声明,就不要用String

1 字符串不适合代替其他基本类型

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

3 字符串不适合代替聚合类型

4 字符串也不适合代替能力表(capabilities)

 

 

7 String拼接时的性能和安全问题

1 为连接n个字符串而重复地使用字符串连接操作符,需要n的平方级的时间(时间复杂度O(n^2)),这是由于字符串不可变特性而导致的不幸结果 当两个字符串被连接在一起时,它们的内容都要被拷贝

2 为了获得可以接受的性能,在不考虑线程安全的情况下,请用 StringBuilder替代String。不要使用字符串连接操作符来合并多个字符串 ,除非性能无关紧要,应该使用 StringBuilder append 方法 另一种做法是使用字符数组,或者每次只处理一个字符串,而不是将它们组合起来,字符串每次组合都会被重新拷贝

 

 

※ 扩展:带你从源码看:String类为什么声明成final?

 

 

8 接口优先于反射

反射的缺点:

1损失了编译时类型检查的优势 ,包括异常检查 如果程序企图用反射方式调用不存 在的或者不可访问的方法 在运行时它将会失败,除非采取了特别的预防措施

2 执行反射访问所需要的代码非常笨拙和冗长 编写这样的代码非常乏味,阅读起来 也很困难

3 性能损失

 

为什么优先用接口?

如果只是以非常有限的形式使用反射机制,虽然也要付出少许代价,但是可以获得许 多好处 许多程序必须用到的类在编译时是不可用的,但是在编译时存在适当的接口或者超 类,通过它们可以引用这个类。如果是这种情况,就可以 用反射方式创建实 例,然后通过它们的接口或者超类,以正常的方式访问这些实例

 

 

 

9 多用接口类型显式声明,少用子类声明,提高可读性和扩展性

1 如果有合适的接口类型存在,那么对于参数、返回值、变量和域来 说,就都应该使用接口类型进行声明 只有当你利用构造器创建某个对象的时候,才真正需 要引用这个对象的类

2 如果养成了用接口作为类型的习惯,程序将会更加灵活

3 如果没有合适的接口存在,完全可以用类而不是接口来引用对象

4 如果没有适合的接口,就用类层次结构中提供了必要功能的最小的具体类来引用对象吧

 

 

10 慎用本地方法栈(Native Method)

1 使用本地方法来提高性能的做法不值得提倡

2 在显式手动调用JDK本地方法之前务必考虑清楚,只有在极少数情况下需要使用本地方法来 提高性能 如果你必须要使用本地方法来访问底层的资獗,或者遗留代码库,也要尽可能少 用本地代码,并且要全面进行测试 本地代码中只要有一个 Bug 都可能破坏整个应用程序

3 要考虑 API 设计决策的性能后果

4 为获得好的性能而对 API 行包装,这是一种非常不好的想法

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

 

 

※ 扩展:打开JDK源码,探寻CAS的鼻祖-UnSafe魔术类

 

11 慎用代码优化,优化!=高质量

1 要努力编写好的程序而不是快的程序,优化!=高质量

2 要努力避免那些限制性能的设计决策

 

 

12 遵循约定俗成的编码规范 - Clean Code/YouZan Java Code Guide

1 Java平台命名惯例分为 两大类:字面的( typographica )和语法的( grammatical )

2 字面的命名惯例比较少,但也涉及包、类、接口、方法、域和类型变量 应该尽量不 违反这些惯例,不到万不得已,千万不要违反 如果 API 违反了这些惯例,使用起来可能 会很困难 如果实现违反了它们,可能会难以维护 在这两种情况下,违反惯例都会潜在 地给使用这些代码的其他程序员带来困惑和苦恼,并且使他们做出错误的假设,造成程序出错

3 包和模块的名称应该是层次状的,用句号分隔每个部分 每个部分都包括小写字母, 极少数情况下还有数字

4 包名称的其余部分应该包括 个或者多个描述该包的组成部分 这些组成部分应该 比较简短,通常不超过 个字符 鼓励使用有意义的缩写形式

5 类和接口的名称,包括枚举和注解类型的名称,都应该包括一个或者多个单词,每个 单词的首字母大写

6 方法和域的名称与类和接口的名称一样 ,都遵守相同的字面惯例,只不过方法或者域 的名称的第 个字母应该小写

7 把标准的命名惯例当作一种内在的机制来看待,并且学着用它们作为第 二特性 字面惯例是非常直接和明确的·语法惯例 更复杂,也更松散,但是如果长期养成的习惯用法与此不同,请不要 盲目遵从这些命名惯例

转载地址:https://supertian.blog.csdn.net/article/details/112975041 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:boost::geometry::make用法的测试程序
下一篇:boost::geometry::line_interpolate用法的测试程序

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年04月08日 01时20分30秒