45、将局部变量的作用域最小化

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

Java允许在任何可以出现语句的地方声明变量(C语言中局部变量要在代码块开头声明),要使局部变量的作用域最小化,最好的方法是在第一次使用它的地方声明。局部变量的作用域从它被声明的点开始扩展,一直到外围块的结束处。

如果在循环终止之后不再需要循环变量的内容,for循环就优于while循环。for循环中变量的作用域范围更小,可以避免一些复制、粘贴错误,并且for循环更简短、可读性更强。如:

  1. for(Element e : c) {
  2. doSomething(e);
  3. }
  4. Iterator<Element> i = c.iterator();
  5. while(i.hasNext()) {
  6. doSomething(i.next());
  7. }

若循环测试中涉及方法调用,并且每次迭代都返回相同的结果。应使用下面的方法避免每次迭代中执行冗余计算。

  1. for(int i=0, n=upper(); i<n; i++) {
  2. doSomething(i);
  3. }

46、for-each循环优先于传统的for循环

for-each循环,通过完全隐藏迭代器或索引变量,避免了调用时混乱和出错的可能。

例如:打印一对骰子的所有可能情况

  1. enum Face { ONE, TWO, THREE, FOUR, FIVE, SIX }
  2. ....
  3. Collection<Face> faces = Arrays.asList(Face.values());
  4. for(Iterator<Face> i=faces.iterator(); i.hasNext(); ) {
  5. for(Iterator<Face> j=faces.iterator(); j.hasNext(); ) {
  6. System.out.println(i.next() + " " + j.next());
  7. }
  8. }

这个程序不会抛出异常,而是打印6种组合(ONE ONE 到 SIX SIX),而不是36种组合。要修正这个错误,必须在外部循环的作用域中添加一个临时变量来保存外部元素。如:

  1. for(Iterator<Face> i=faces.iterator(); i.hasNext(); ) {
  2. Face temp = i.next();
  3. for(Iterator<Face> j=faces.iterator(); j.hasNext(); ) {
  4. System.out.println(temp + " " + j.next());
  5. }
  6. }

若使用嵌套的for-each循环,这个错误就可以完全避免。如:

  1. for(Face face1 : faces) {
  2. for(Face face2 : faces) {
  3. System.out.println(face1 + " " + face2);
  4. }
  5. }

for-each循环不仅可以遍历集合和数组,还可以遍历任何实现了Iterable接口的对象。但有三种常见的情况无法使用for-each循环:

  • 过滤,遍历集合或数组并删除选定的元素,需要使用显式的迭代器。
  • 转换,遍历集合或数组并替换选定的元素。
  • 平行迭代,需要平行的遍历多个集合或数组(骰子打印6种组合的情况)

47、了解和使用类库

使用标准类库的好处:

  • 可以充分利用他人的使用经验
  • 不必浪费时间在一些与工作不相关的问题上
  • 性能会随着时间的推移而不断提高
  • 可以使自己的代码融入主流

java程序员应该熟练掌握和使用java.lang,java.util,java.io包中的内容。

一句话,不要重新发明轮子。

48、如果需要精确的答案,请避免使用float和double

float和double类型在执行二进制浮点运算时,不能得到完全精确的结果,它们不应该被用于需要精确结果的场合。例如:0.4 + 0.2输出结果为0.6000000000000001。 原因可以参考这篇博客 代码之谜(五)- 浮点数(谁偷了你的精度?)

解决这个问题的办法是使用BigDecimal进行计算,或转化为int、long类型(自己处理小数点)。如:

  1. BigDecimal result = new BigDecimal("0.2").add(new BigDecimal("0.4"));

对于任何需要精确答案的计算任务,不要使用float或double。

49、基本类型优先于装箱基本类型

java中每个基本类型(int、double)都有一个对应的引用类型(Integer、Double),称作装箱基本类型。

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

  1. 基本类型是值,而装箱基本类型是对象
  2. 装箱基本类型有非功能值null
  3. 基本类型更节省时间和空间

编程时应注意下面几种常见的错误:

  1. //1. ==操作
  2. public int compare(Integer first, Integer second) {
  3. return first < second ? -1 :(first == second ? 0 : 1); //compare(42,42)结果返回1
  4. }
  5. //2. null
  6. Integer i;
  7. if(i == 42) { //报空指针异常,i初始值为null
  8. ...
  9. }
  10. //3. 无意识的装箱
  11. Long sum = 0L; //无意识的装箱,性能严重下降
  12. for(long i=0; i<Integer.MAX_VALUE; i++ ) {
  13. sum += i;
  14. }

必须使用装箱基本类型的情况:

  • 泛型中的参数化类型
  • 进行反射的方法调用时

50、如果其他类型更适合,则尽量避免使用字符串

如果可以使用更加合适的数据类型,或者可以编写更适当的数据类型,就应该避免用字符串来表示对象。若使用不当,字符串会比其他类型更笨拙、速度更慢、也更容易出错。不要用字符串来代替基本类型、枚举类型和聚集类型。

51、当心字符串连接的性能

不要使用字符串连接操作符+来合并多个字符串,应该使用StringBuilder的append方法。第一种方法的时间复杂度为O(n2),第二种方法的时间复杂度为O(n)。

52、通过接口引用对象

若有合适的接口类型存在,那么对于参数、返回值、变量和域,应该使用接口而不是类进行声明。这将使程序更加灵活。

53、接口优先于反射机制

反射机制提供了访问编译时未知的类的能力,对于复杂的系统编程任务,它是必要的。但它也有一些缺点,比如:丧失了编译时类型的检查、代码冗长、性能较低等。若有可能应该仅仅使用反射机制来实例化对象,而访问对象则使用编译时已知的接口或超类。

54、谨慎的使用本地方法

Java Native Interface(JNI) 允许java程序可以调用本地方法—native method,本地程序设计语言(如C或C++)编写的特殊方法。

本地方法的主要用途有:访问遗留代码库、提高系统性能、访问注册表和文件锁等。本地方法是不安全的、难于调试并且不可自由移植。应该尽量少使用或不使用本地方法。

55、谨慎的进行优化

  • 不要因为性能而牺牲合理的结构。要努力编写好的程序而不是快的程序。
  • 不要进行优化,特别是不成熟的优化。

不要费力去编写快速的程序——应该努力编写好的程序。在设计API、线路层协议和永久数据格式的时候,一定要考虑性能的因素。若系统不够快,可使用性能剖析工具找到问题的根源,并设法优化相关的部分。再多的低层优化也无法弥补算法的选择不当,所以选择一个好的算法是性能优化的根本。

56、遵循普通接受的命名惯例

java的命名惯例包含在《Java编程规范》(the java language specification)中。

泛型参数类型:T表示任意的类型,E表示集合的元素类型,K和V表示映射的键和值类型,X表示异常。任何类型的序列使用T1、T2、T3。

Effective java笔记(七),通用程序设计的更多相关文章

  1. [Effective Java]第八章 通用程序设计

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  2. Effective java笔记5--通用程序设计

    一.将局部变量的作用域最小化      本条目与前面(使类和成员的可访问能力最小化)本质上是类似的.将局部变量的作用域最小化,可以增加代码的可读性和可维护性,并降低出错的可能性. 使一个局部变量的作用 ...

  3. Effective Java笔记一 创建和销毁对象

    Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...

  4. Effective java笔记(二),所有对象的通用方法

    Object类的所有非final方法(equals.hashCode.toString.clone.finalize)都要遵守通用约定(general contract),否则其它依赖于这些约定的类( ...

  5. effective java笔记之单例模式与序列化

    单例模式:"一个类有且仅有一个实例,并且自行实例化向整个系统提供." 单例模式实现方式有多种,例如懒汉模式(等用到时候再实例化),饿汉模式(类加载时就实例化)等,这里用饿汉模式方法 ...

  6. effective java笔记之java服务提供者框架

    博主是一名苦逼的大四实习生,现在java从业人员越来越多,面对的竞争越来越大,还没走出校园,就TM可能面临失业,而且对那些增删改查的业务毫无兴趣,于是决定提升自己,在实习期间的时间还是很充裕的,期间自 ...

  7. Effective Java 读书笔记之七 通用程序设计

    一.将局部变量的作用域最小化 1.在第一次使用变量的地方声明 2.几乎每个变量的声明都应该包含一个初始化表达式:try-catch语句是一个例外 3.使方法小而集中是一个好的策略 二.for-each ...

  8. Effective java笔记6--异常

    充分发挥异常的优点,可以提高一个程序的可读性.可靠性和可维护性.如果使用不当的话,它们也会带来负面影响. 一.只针对不正常的条件才使用异常 先看一段代码: //Horrible abuse of ex ...

  9. [Effective Java]第七章 方法

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

随机推荐

  1. 多线程导出大规模excel文件

    文章有点水,和前几篇没有太大区别,但是单线程处理大文件导出会非常耗时间,用到多线程才能更加合理的利用资源.大文件也可能会超出excel工作表范围.这里也有相应处理 参考:用DataGridView导入 ...

  2. 从“差不多了”到 正式发布 -- 新浪微博WinPhone UWP版诞生记

    本文粗略记述了UWP团队从接手新浪微博项目到发布第一版的过程.本文不是技术贴,而是回顾“软件工程周期失控是一种怎样的体验”. 接手新项目:捡了个大便宜 2016年1月份,UWP team开始接手新浪微 ...

  3. ASP.Net WebForm温故知新学习笔记:二、ViewState与UpdatePanel探秘

    开篇:经历了上一篇<aspx与服务器控件探秘>后,我们了解了aspx和服务器控件背后的故事.这篇我们开始走进WebForm状态保持的一大法宝—ViewState,对其刨根究底一下.然后,再 ...

  4. [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦

    [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦 本节导读:上篇文章简单介绍了.NET面向对象中一个重要的技术反射的基本应用,它可以让我们动态的调 ...

  5. [已招满,谢谢关注]Sogou招聘C#开发人员,有意者请进

    职位名称:c#开发工程师 工作地点:搜狐网络大厦 职责:搜狗商业平台桌面产品 职位要求: 1. 计算机或者相关专业本科或以上学历 2. 精通c#,两年以上实际项目开发经验 3. 熟悉C/S开发架构和设 ...

  6. ASP.net 常用服务器控件

    新人初学,有错请指,大神轻喷. .net中有HTML控件和标准服务器控件. 老师教学用的是vs2010是这样分的,不知道15里是不是这样. 如果使用HTML控件我们就会发现页面中加载了原本HTML代码 ...

  7. Linux下修改Mysql的用户(root)的密码

    修改的用户都以root为列.一.拥有原来的myql的root的密码: 方法一:在mysql系统外,使用mysqladmin# mysqladmin -u root -p password " ...

  8. Python标准模块--linecache

    1.模块简介 linecache主要用于缓存文件内容,如果下次继续读取该文件,则不需要打开文件,直接在缓存中获取该文件内容. 2.模块使用 模块的基本方法有getline,clearcache,get ...

  9. MVC5 网站开发实践 2.2、管理员身份验证

    上次完成了管理员的登录,这次要解决对管理员登录后的验证,采用AuthorizeAttribute属性的方式.之前还要解决几个问题,然后才重写验证类,最后稍微改一下界面. 目录 MVC5 网站开发实践  ...

  10. javascript面向对象系列第四篇——选项卡的实现

    前面的话 面向对象的应用并非只是读几本书那么容易,需要有大量的工程实践做基础才能真正理解并学会使用它.本文将用面向对象的技术来制作一个简单的选项卡 图示说明 由图示结果看到,这是一个非常简单的选项卡. ...