Effective Java(四)

本文分享了Java编程的12条最佳实践,包括变量作用域最小化、优先使用for-each循环、利用标准类库、避免使用浮点数进行精确计算等,旨在帮助开发者写出更高效、更可靠的代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、通用程序设计

目标:局部变量的处理、控制结构、类库的用法、各种数据类型的用法、反射机制(reflection)和本地方法(native method)的用法。

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

(1)、在第一次使用变量的地方声明。

(2)、使方法小而集中。

 

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

(1)、for-each循环简洁,可预防Bug。

(2)、不能使用for-each循环情况:过滤、转换、平行迭代。

 

3、了解和使用类库

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

(2)、java.lang、java.util、java.io类库。

(3)、不要重新发明轮子,了解常用类库并使用类库,提高开发效率。

 

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

(1)、使用BigDecimal、int或者long进行货币计算。

 

5、基本类型优先于装箱基本类型(封装类型)

(1)、Java类型系统组成:基本类型(primitive),如int、double、boolean和引用类型(reference type),如String、List。

(2)、当在一项操作中混合使用基本类型和封装类型,封装类型就会自动拆箱。

(3)、在进行反射的方法调用时,必须使用装箱基本类型。

(4)、封装类型会导致高开销和不必要的对象创建。

 

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

(1)、字符串不适合代替其他的值类型、枚举类型、聚集类型、能力表(capabilities)。

 

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

(1)、为连接n个字符串而重复地使用字符串连接操作符,需要n的平方级的时间,这种场景不适合用+连接符。

(2)、可以使用StringBuilder代替+字符串连接。

(3)、StringBuilder:适用于单线程下大数据量的操作,线程不安全。

(4)、StringBuffer:适用于多线程下大数据量的操作,线程安全。

 

8、通过接口引用对象

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

 

9、接口优先于反射机制

(1)、核心反射机制(core reflection facility)java.lang.reflect,提供了“通过程序来访问关于已装载的类的信息”的能力。

(2)、反射机制允许一个类使用另一个类,即使当前者被编译的时候后者还不存在。

(3)、反射的缺点

  • 丧失了编译时类型检查的好处。
  • 执行反射访问所需的代码非常笨拙和冗长。
  • 性能损失。

 (4)、如果编写的程序要与编译时未知的类一起工作,如有可能,就应该仅仅使用反射机制来实例化对象,而访问对象时则使用编译时已知的某个接口或者超类。

 

10、谨慎地使用本地方法

(1)、本地应用方法,是指用本地程序设计语言(如C或者C++)来编写的特殊方法。本地方法在本地语言中可以执行任意的计算任务,并返回到Java程序设计语言。

(2)、本地方法的用途。提供访问特定于平台的机制的能力,如注册表、文件锁。提供访问遗留代码库的能力,从而可以访问遗留数据。通过本地语言编写应用程序中注重性能的部分。

(3)、本地语言不是安全的,且使用了本地语言会造成不能移植。

 

11、谨慎地进行优化

(1)、不要优化。

(2)、不要因为性能而牺牲合理的结构,要努力编写好的程序而不是快的程序。(建议)

(3)、必须在设计过程中考虑到性能的问题。

 

12、遵守普遍接受的命名惯例

(1)、字面的(typographical)和语法的(grammatical)。

(2)、字面惯例

包                   ——   com.google.inject, org.joda.time.format 
类或者接口     ——   Timer, FutureTask, LinkedHashMap, HttpServlet 
方法或者域     ——   remove, ensureCapacity, getCrc 
常量域            ——   MIN_VALUE, NEGATIVE_INFINITY 
局部变量        ——   i, xref, houseNumber 
类型参数        ——   T, E, K, V, X, T1, T2

 

二、异常

目标:充分发挥异常的优点,可以提高程序的可读性、可靠性和可维护性。

 

1、只针对异常的情况使用异常

(1)、异常应该只用于异常的情况下,永远不应该用于正常的控制流。

 

2、对可恢复的情况使用受检异常,对编程错误使用运行时异常。

(1)、抛出结构(throwable):受检的异常(checked exception)、运行时异常(run-time exception)、错误(error)。

(2)、如果期望调用者能够适当地恢复,对于这种情况就应该使用受检的异常。

 

3、避免不必要地使用受检的异常

(1)、可以把受检的异常变成未受检的异常,即状态测试方法。

 

4、优先使用标准的异常

(1)、异常类越少,内存印迹(footprint)越小,装载这些类的时间开销越小。

(2)、常用的异常

算术异常类:ArithmeticExecption
空指针异常类:NullPointerException
类型强制转换异常:ClassCastException
数组负下标异常:NegativeArrayException
数组下标越界异常:ArrayIndexOutOfBoundsException
违背安全原则异常:SecturityException
文件已结束异常:EOFException
文件未找到异常:FileNotFoundException
字符串转换为数字异常:NumberFormatException
操作数据库异常:SQLException
输入输出异常:IOException
方法未找到异常:NoSuchMethodException

 

5、抛出与抽象相对应的异常

(1)、异常转译(exception translation),指更高层的实现应该捕获低层的异常,同时抛出可以按照高层抽象进行解释的异常。

(2)、异常链(exception chaining)。

 

6、每个方法抛出的异常都要有文档

(1)、描述好前提条件(precondition)、通用约定(general contract)

 

7、在细节消息中包含能捕获失败的信息

 

8、努力是失败保持原子性

(1)、失败原子性(failure atomic),失败的方法调用应该使对象保持在被调用之前状态。

 

9、不要忽略异常

(1)、警钟长鸣。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值