Effective Java 78条军规

Effective Java, 2nd Edition

by Joshua Bloch

I, Michael Parker, own this book and took these notes to further my own learning. If you enjoy these notes, please purchase the book!

Chapter 2: Creating and Destroying Objects创建和销毁对象

Item 1: Consider static factories instead of constructors考虑使用静态工厂方法代替构造器

  • An instance-controlled class is one that uses static factories to strictly control what instances exist at any time.
  • By convention, static factory methods for an interface named Type are put in a non-instantiable class named Types.
  • When naming static factory methods, getInstance may return the same instance, while newInstance should not.
  • 静态工厂方法与构造器的第一大优势在于:他们有名称
  • 第二大优势:不必在每次调用他们的时候都创建一个新的实例
  • 第3大优势:他们可以返回任何原返回类型的任何子类型对象
  • 静态工厂方法的主要缺点1:类如果不包含public或proctected的构造器,就不能被子类化
  • 静态工厂方法的缺点2:他们与其他的静态方法实质上没有任何区别
  • 静态工厂的惯用名称:valuOf,of,getInstance,newInstance,getType,newType

Item 2: Consider a builder when faced with many constructor parameters遇到多个构造器参数时要考虑用构建器

  • The builder pattern simulates optional named parameters in Ada and Python.
  • A builder whose parameters have been set makes a fine abstract factory, assuming some generic Builder interface.
  • 重叠构造器模式是可行的,但是当有很多参数的时候,客户端代码会很难编写
  • Builder模式代码易于阅读,模拟了具名的可选参数
  • Class.newInstance破坏了编译时的异常检查
  • JavaBean模式会导致在构造过程中JavaBean可能处于不一致状态

Item 3: Enforce the singleton property with a private constructor or an enum type用私有构造器或枚举类型强化Singleton属性

  • Adding implements Serializable to a singleton class is not enough, you must declare all fields transient and provide a readResolve method.
  • A single-element enum type provides the serialization for free and is the best way to implement a singleton.
  • 现代的jvm实现几乎都能讲静态工厂方法的调用内联化
  • 为了维护并保证Singleton,必须声明所有实例域都是transient的,并提供一个readResolve方法。否则每次反序列化一个实例时都会创建一个新的实例。
  • 单元素的枚举类型已经成为实现Singleton的最佳方法

Item 4: Enforce non-instantiability with a private constructor使用私有构造器强化不可实例化的能力

  • A private constructor not only supresses instantiation, but subclassing.
  • 例如工具类不希望被实例化,实例对它没有任何意义
  • 企图通过将类做成抽象类来强制该类不可被实例化,这是行不通的。该类可以被子类化,并且该子类可以被实例化。

Item 5: Avoid creating unnecessary objects避免创建不必要的对象

  • Often lazy initialization only complicates the implementation and yields no noticeable performance increase.
  • Prefer primitives to boxed primitives, as unintentional autoboxing can lead to creating many new instances.
  • Highly optimized garbage collectors can easily outperform object pools that do not contain heavyweight objects.
  • 一般来说,最好能重用对象而不是在每次需要的时候就创建一个相同功能的新对象。
  • 延迟初始化中常见的情况会使方法的实现变得复杂,从而无法将性能显著地提高到超出已达到的水平。
  • 在Java1.5发行版中,有一种创建多余对象的新方法,成为自动封箱。
  • 要优先使用基本类型而不是装箱基本类型,当心无意识的自动封箱。

Item 6: Eliminate obsolete object references消除过期对象的引用

  • Whenever a class manages its own memory, like a stack or object pool, the programmer should be alert for memory leaks.
  • Caches, listeners, and callbacks can all be sources of memory leaks, but weak references can help.
  • 所谓过期引用,是指永远也不会再被删除的引用
  • 如果一个对象引用被无意识地保留起来了,那么,垃圾回收机制不仅不会处理这个对象,而且不会处理被这个对象所引用的所有其他对象。
  • 清空对象引用应该是一种例外,而不是一种规范行为。消除过期引用的最好方法就是让包含该引用的变量结束其生命周期。
  • 一般而言,只要类是自己管理内存,程序员就应该警惕内存泄露问题。
  • 内存泄露的另一个常见来源是缓存。可以用WeakHashMap代表缓存,当缓存中的项过期后,他们就会被自动删除。
  • 缓存应该时不时地清除掉没用的项,这项清除工作可以由一个后台线程(可能是Timer或ScheduledThreadPoolExecutor)来完成。
  • 内存泄露的第3个常见来源是监听器和其他回调。确保回调被当做垃圾回收的最佳方法时只保存他们的弱引用(weak reference),例如,只将他们保存成WeakHashMap中的键。

Item 7: Avoid finalizers避免使用finalize

  • Do not think of finalizers as Java's analogue of C++ destructors -- there's no guarantee finalizers will be called at all!
  • If an uncaught exception is thrown in a finalizer, it is ignored, and the finalization abruptly terminates.
  • There is a severe performance penalty for using finalizers -- object creation and deletion increases from nanoseconds to microseconds.
  • Java语言规范并不保证哪个线程将会执行finalize方法,所以除了不使用finalize方法之外,并没有很轻便的方法能避免这样的问题。
  • Java语言规范不仅不能保证finalize方法被及时地执行,而且根本就不保证它们会被执行。结论:不应该依赖finalize方法来更新重要的持久状态。
  • 不要被System.gc和System.runFinalization这两个方法所诱惑,它们确实增加了终结方法被执行的机会,但是它们并不保证终结方法就一定会被执行。
  • 使用终结方法有一个非常严重的性能损失。用终结方法后创建和销毁对象慢了约430倍。
  • 怎样做才能不用编写finalize方法呢?只需要提供一个显示的终止方法,并要求该类的客户端在每个实例不再可用的时候调用这个方法。显示的终止方法通常与try-finally结构结合起来使用,以确保及时终止。
  • 如果子类实现者覆盖了超类的finalize方法(或者有意选择不调用超类的finalize方法),那么超类的finalize方法将永远也不会被调用到。要防范这样粗心大意或者恶意的子类是有可能的,代价就是为每个将被finalize的对象创建一个附加的对象。不是把finalize方法放在要求终结处理的类中,而是把finalize方法放在一个匿名类中,该匿名类的唯一用途就是终结它的外围实例(enclosing instance)。

Chapter 3: Methods Common to All Objects对于所有对象都通用的方法

Item 8: Obey the general contract when overriding equals覆盖equals时请遵循通用约定

  • Override equals when a class has a notion of logical equality that differs from mere object identity, and the superclass has not provided a suitable implementation.
  • For classes that represent a value, such as Integer or Date, the equals method should always be overridden.
  • There is no way to extend an instantiable class and add a value component (field) while preserving the equals contract.
  • By using composition with views to internal components, you can add value components to instantiable classes without violating the equals contract.
  • To compare float and double values, use the Float.compare and Double.compare methods to deal with NaN and -0.0 values.
  • For best performance, first compare fields that are more likely to differ, or less expensive to compare.
  • 覆盖equals时要遵循的通用约定:
  • 1-类的每个实例本质上都是唯一的。
  • 2-不关心是否提供了‘逻辑相等logical equality’的测试功能
  • 3-超类已经覆盖了equals,从超类继承过来的行为对于子类也是合适的。
  • 4-类是private的或是包级私有的,可以确定它的equals永远不会被调用。
  • equals等价关系约定
  • 自反性reflexive.x.equals(x)必须返回true
  • 对称性symmetric,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true
  • 传递性transive,如果x.equals(y)返回true,并且y.equals(z)返回true,那么x.quals(z)也必须返回true.
  • 一致性consistent,多次调用x.equals(y)都会一致地返回true或一致地返回false.
  • 里氏交换原则认为,一个类型的任何重要属性也将适用于它的子类型,因此为该类型编写的任何方法,在它的子类型上也应该运行得很好。
  • Timestamp类有一个免责声明,告诫程序员不要混用Date和Timestamp对象。
  • 实现高质量equals方法的诀窍:
  • 1-使用==操作符检查‘参数是否为这个对象的引用’
  • 2-使用instanceof检查'参数是否为正确的类型'
  • 3-把参数转换为正确的类型。因为转换之前已经做过instanceof测试,所以确保成功
  • 4-对于该类中的每个'关键significant'域,检查参数中的域是否与该对象中相应的域相匹配。
  • 5-当你编写完equals方法后,应该问下自己:它是否是对称的,传递的,一致的?
  • 覆盖equals方法时总要覆盖hashCode方法

Item 9: Always override hashCode when you override equals重写hashCode方法时记得重写equals方法

  • To take the hash code of float and double values, use Float.floatToIntBits and Double.doubleToLongBits, respectively.
  • Immutability offers the chance to cache hash codes if computing them is expensive.
  • Try not to specify the behavior of your hash code method in Javadoc, as that limits your options for improving it later.
  • 在每个覆盖了equals方法的类中,也必须覆盖hashCode方法
  • 如果两个对象根据equals方法比较是相等的,那么两个对象的hashCode方法必须产生相等的整数结果。相等的对象必须具有相等的散列码。
  • 一个好的散列函数通常倾向于'为不相等的对象产生不相等的散列码'。
  • 在散列码的计算过程中,可以把冗余域redundant field排除在外。
  • 习惯上都使用素数来计算散列结果。31有个很好的特性,即用移位和减法来代替乘法,可以得到更好的性能:31*i==(i << 5)-i。
  • 不要试图从散列码计算中排除掉一个对象的关键部分来提高性能。

Item 10: Always override toString始终要覆盖toString

  • If you specify the format in Javadoc, provide a static factory method accepting a String parameter so a client can convert between the two forms.
  • Provide programmatic information to all the information provided by toString, or clients may try to parse the string to retrieve it.
  • 在实际应用中,toString方法应该返回对象中包含的所有值得关注的信息
  • 实现toString时,在文档中指定返回值的格式。
  • 无论你是否指定格式,都应该在文档中明确地表明你的意图。
  • 无论是否指定格式,都为toString返回值中包含的所有信息,提供一种编程式的访问途径。

Item 12: Consider implementing Comparable考虑实现Comparable接口

  • Like the equals method, there is no way to extend and instantiable class with a new value component while preserving the compareTo contract.
  • If compareTo is consistent with equals, note that sorted collections (e.g. TreeSetTreeMap) use the equality test imposed by compareTo instead of equals and may break the interface (e.g. SetMap) contract.
  • Use methods Double.compare and Float.compare instead of relational operators, which don't obey the compareTo contract for floating point values.

Chapter 4: Classes and Interfaces类和接口

Item 13: Minimize the accessibility of classes and members使类和成员的可访问性最小化

  • Private and package-private members can "leak" into the exported API if the class implements Serializable.
  • Even a protected member is part of the class's exported API and must be supported forever.
  • With the exception of public static final fields to immutable objects, public classes should have no public fields.

Item 14: In public classes, use accessor methods, not public fields在public类中使用public方法而非public属性

  • If a class is package-private or a private nested class, there's nothing wrong with exposing its data.
  • A public class with immutable public fields is okay because it can enforce their invariants upon construction.

Item 15: Minimize mutability使可变性最小化

  • For immutable classes, the Java memory model requires that all fields be final to ensure correct behavior when passing an instance between threads without synchronization.
  • Defend against "leaking" references by making defensive copies in constructors, accessors, and readResolve methods when needed.
  • Instances of an immutable class can share internal objects with one another for efficiency.
  • If a client requires performing expensive multi-stage operations on your class, expose them as primitive methods, or provide a mutable companion class (like StringBuilder for String).

Item 16: Favor composition over inheritance复合优先于继承

  • Inheritance violates encapsulation because the subclass depends on the implementation details of the superclass for its proper function.
  • Inheritance means you inherit the scope and flaws of an API, whereas composition allows you to design a better suited one.
  • If an appropriate interface exists, using composition and forwarding allows you to instrument any implementation of the interface, instead of a single implementation through inheritance.

Item 17: Design and document for inheritance, or else prohibit it要么为继承设计和提供文档,要么禁止继承

  • The class that allows subclassing must document its self-use of overridable methods.
  • The only way to test if a class is suitably designed for inheritance (e.g. provides all the necessary implementation hooks through protected methods) is to actually write subclasses.
  • Eliminating a class's self use of methods, typically through introducing private helper methods, can make a class safe to subclass.

Item 18: Prefer interfaces to abstract classes接口优先于抽象类

  • Use interfaces to allow construction of non-hierarchical type frameworks.
  • Simulated multiple inheritance is where a class implementing an interface can forward invocations to an instance of a private inner class that extends the skeletal implementation of that interface and hence does the bulk of the work.
  • A variant of a skeletal implementation is the simple implementation, which is a concrete class that defines the simplest possible implementation, such as AbstractMap.SimpleEntry.
  • Java只允许单继承,所以,抽象类作为类型定义受到了极大的限制。
  • 接口是定义mixin混合类型的理想选择。
  • 接口允许我们构造非层次结构的类型框架。
  • 通过包装器wrapper class模式,接口使得安全地增强类的功能成为可能。通过对你导出的每个重要接口都提供一个抽象的骨架实现skelect implementation类,把接口和抽象类的优点结合起来。接口的作用仍然是定义类型,但是骨架实现类接管了所有与接口实现相关的工作。
  • 通过接口来定义允许多个实现的类型,与使用接口相比有一个明显的优势:抽象类的演变要比接口演变要容易得多。
  • 设计公有的接口要十分谨慎。接口一旦被公开发行,并且已被广泛实现,再想改变这个接口几乎是不可能的。

Item 19: Use interfaces only to define types接口只用于定义类型

  • Don't use constant interfaces, or interfaces that define no methods but only constants, which classes implement to access the constants without fully qualifying their names.
  • If the constants are static members of a class, and you really don't want to qualify their names, use the static import facility for brevity.

Item 21: Use function objects to represent strategies用函数对象表示策略

  • Classes that implement concrete strategies, or simulate function pointers, should be stateless and made into singletons.
  • When defining a strategy as an anonymous class that is inline in a method invocation, consider extracting the object as a private static final field so a new instance is not created upon every call.

Item 22: Favor static member classes over nonstatic优先考虑静态成员类

  • Nonstatic member classes are ideal for providing adapters, or views of an outer class as an instance of some unrelated class.
  • An anonymous class have enclosing instances if and only if they occur in a non-static context.

Chapter 5: Generics

Item 23: Don't use raw types in new code

  • List is read as "list of E", and List is read as "list of string", where String is the actual type parameter and E is the formal type parameter.
  • While an instance of the raw type List could be designated to hold only types of a single class but opts out of type-checking, List is typesafe because it explicitly states that it can contain objects of any type.
  • The unbound wildcard type, such as in List, represents a list of some unknown type and so forbids inserting any element other than null, unlike the raw type List which is not typesafe.
  • Item 24: Eliminate unchecked warnings

    • Always use the @SuppressWarnings annotation on the smallest scope possible, to not mask other, critical warnings.

    Item 25: Prefer lists to arrays

    • Arrays are covariant, so Sub[] is a subtype of Super[], and reified, so they retain their type-information at runtime and Super[] can throw an ArrayStoreException when given a different subclass; by contrast, List is covariant and erased.
    • Consequently, arrays provide runtime safety but not compile-time safety, while a generic type like List provides compile-time safety but not runtime safety.

    Item 27: Favor generic methods

    • You can exploit the type inference provided by generic methods and write generic static factory methods that make instances easier to create.
    • If you have an immutable, singleton instance of a generic class that could be shared across all types, make it private and of type Object, and then let a generic singleton factory method cast it to the caller's desired type.
    • The type bound > may be read as "for every type T that can be compared to itself" and is the definition of a mutually comparable type.

    Item 28: Use bounded wildcards to improve API flexibility

    • If a parameterized type represents a T producer, use ; if a parameterized type represents a T consumer, use .
    • Do not use wildcard types as return types, or clients will be forced to use wildcard types in their code.
    • Comparables and comparators are always consumers, so you should always use Comparator in preference to Comparator.
    • If a type parameter appears only once in a method declaration, replace it with a wildcard, using a private helper method to capture the type if necessary.

    Item 29: Consider typesafe heterogeneous containers优先考虑类型安全的异构容器

    • A type token is a class literal is passed among methods to communicate both compile-time and runtime type information.
    • The cast method of the Class type is the dynamic analog of Java's cast operator, throwing a ClassCastException if the operation fails.
    • The "checked" collection wrappers in java.util.Collections use this method with type tokens to enforce, at runtime, that invalid types are not added to a collection through its raw type.

    Chapter 6: Enums and Annotations枚举和注解

    Item 30: Use enum instead of int constants使用枚举代替int常量

    • You can add or reorder constants in an enum type without recompiling its clients because the constant values are not compiled into the clients as they are with the int enum pattern.
    • Enums are by their nature immutable, and so all their fields should be final.
    • If you override the toString method of an enum type, consider writing a fromString method, similar to how the static valueOf method would perform if you had not overridden toString.
    • To share a constant specific method implementations between enum values, move each implementation into a private nested enum, and pass an instance of this strategy enum to the constructor of the top-level enum.

    Item 32: Use EnumSet instead of bit fields使用EnumSet代替位域

    • An EnumSet is represented by one or more long values, and so many of its operations are effiiciently performed with bitwise arithmetic.

    Item 33: Use EnumMap instead of ordinal indexing用EnumMap代替序数索引

    • When you access an array that is indexed by the ordinal value of an enum, it is your responsibility to use the correct int value, as no type safety is afforded.
    • An EnumMap contains an array internally, offering the speed of an ordinal-indexed array with the type safety and richness of the Map interface.
    • Instead of using an array of arrays to define a mapping from two enum values, use EnumMap<..., EnumMap<...>>, which is internally represented as an array of arrays.

    Item 34: Emulate extensible enumerated types with interfaces用接口模拟可伸缩的枚举

    • If two enumerated types implement the same interface, both their classes adhere to the type  & InterfaceName>.
    • Since implementations cannot be inherited from one enum type to another, the functionality must be encapsulated in a helper class or a static helper method.

    Item 35: Prefer annotations to naming patterns注解优先于命名模式

    • Annotations like Retention and Target for annotation type declarations are called meta-annotations.
    • A marker annotation is one with no parameter and simply serves to mark some class, method, or field for interpretation by some other method or program.

    Item 36: Consistently use the Override annotation坚持使用override注解

    • There is no need to use the @Override annotation when a concrete class overrides an abstract method, i.e. implements it, because a differing signature will be caught by the compiler anyway.
    • In an abstract class or interface, annotate all methods you believe to override superclass or superinterface methods, whether concrete or abstract, to ensure that you don't accidentally introduce any new methods.

    Item 37: Use marker interfaces to define types使用标记接口定义类型

    • Use a marker interface instead of an annotation if you want to write one or more methods that accept only objects that have this marking, or implement the interface.
    • Use a marker interface instead of an annotation if you want to limit the use of the marker to elements of a particular interface, by having the marker interface extend that interface.
    • A marker annotation, however, allows marking elements other than classes and interfaces, and allows adding more information while retaining backwards compatibility through type elements with defaults.

    Chapter 7: Methods方法

    Item 38: Check parameters for validity检查参数有效性

    • Nonpublic methods should check their parameters using assertions, which are enabled with the -enableassertions command line flag, instead of explicitly throwing exceptions.
    • Skip checking a method's parameters before performing the computation if the validity check would be expensive or impractical and the validity check is performed implicitly during the computation.

    Item 39: Make defensive copies when needed必要时进行保护性拷贝

    • When making defensive copies of constructor parameters, check the validity of the copies instead of the originals to guard against malicious changes to the parameters by another thread.
    • Do not use the clone method to make a defensive copy of a constructor parameter whose type is subclassable by untrusted parties.
    • The defensive copy can be replaced by documented transfer of ownership if copying the object would be costly and the class trusts its clients not to modify the components inappropriately.

    Item 40: Design method signatures carefully谨慎设计方法签名

    • If you go over four parameters, try to break up the method into orthogonal methods with fewer parameters, introduce helper classes that bundle related parameters together, or use a builder pattern.
    • Prefer two-element enum types to boolean parameters.

    Item 41: Use overloading judiciously慎用重载

    • Beware that selection among overloaded methods is static, while selection among overridden methods is dynamic.
    • Avoid cases where the same set of parameters can be passed to different overloadings of a method by the addition of casts.
    • If a method with a primitive parameter overloads a method with a generic parameter, the two can become conflated from autoboxing.

    Item 42: Use varargs judiciously慎用可变参数

    • Don't blindly retrofit every method that has a final array parameter to use varargs; use varargs only when a call operates on a variable-length sequence of values.

    Item 43: Return empty arrays or collections, not nulls返回零长度的数组或集合而不是null

    • Returning null from an array or collection-valued method complicates the caller logic, and usually the callee's.
    • To eliminate the overhead from creating an empty collection or array, return the immutable empty collections in java.util.Collections, or create a static empty array which is necessarily immutable.

    Item 44: Write doc comments for all exposed API elements为所有导出的API元素编写文档注释

    • To include a multiline code example in a doc comment, use a Javadoc {@code} tag wrapped inside an HTML 
       tag.
    • The {@literal} tag is like the {@code} tag in that it eliminates the need to escape HTML metacharacters, but doesn't render the contents in monospaced font.
    • No two members or constructors should have the same summary description, which is the first (sometimes incomplete) sentence of a doc comment.

    Chapter 8: General Programming通用程序设计

    Item 45: Minimize the scope of local variables将局部变量的作用域最小化

    • Declare a variable at the latest point possible, typically right before it is first used, and strive to provide an initializer.
    • If the bound for a loop variable is expensive to compute on every iteration, store it in a loop variable that will fall out of scope with the counter variable.

    Item 46: Prefer for-each loops to traditional for loops for-each循环优先于传统for循环

    • If you are writing a type that represents a group of elements, have it implement the Iterable interface even if it does not implement Collection.
    • The enhanced for loop cannot be used if you need to remove elements through an iterator, reassign elements through a list iterator, or iterate over collections in parallel.

    Item 47: Know and use the libraries了解和使用类库

    • Every programmer should be familiar with the contents of java.lang and java.util (particularly the collections framework), and to a lesser extent java.io and java.util.concurrent.

    Item 48: Avoid float and double if exact answers are required需要精确的结果时避免使用float和double

    • The BigDecimal can contain decimal values of arbitrary size and provides eight rounding modes, which is ideal for business calculations with legally mandated rounding behavior.
    • If you choose to keep track of the decimal point yourself, int provides up to nine decimal digits, while long provides up to eighteen.

    Item 49: Prefer primitive types to boxed primitives基本类型优先于装箱类型

    • Never use == on two boxed primitives, because this always performs identity comparison, while the < and > operators compare the underlying primitive values.
    • When you mix primitives and boxed primitives in a single operation, the boxed primitive is auto-unboxed, which can result in NullPointerExceptions.
    • Beware of boxed primitives being implicitly unboxed and then re-boxed, which can cause performance problems.

    Item 50: Avoid strings where other types are appropriate如果其他类型更适合,避免使用String

    • Instead of using a key to represent an aggregate type, write a private static member class -- even if it only has two fields.

    Item 51: Beware the performance of string concatenation当心字符串连接的性能

    • A consequence of strings being immutable is that the time to concatenate n strings is quadratic in n.
    • An alternative to using a StringBuilder is to try processing the strings one at a time to avoid all concatenation.

    Item 52: Refer to objects by their interfaces通过接口引用对象

    • If you depend on any properties of an implementation not specified by its interface, such as its synchronization policy, use the class as a type and document the requirements.

    Item 53: Prefer interfaces to reflection接口优先于反射机制

    • If a class is unavailable at compile time but there exists an appropriate interface, create instances reflectively and access them normally through their interface.
    • If writing a package that runs against multiple versions of some other package, you can compile it against the minimal environment required to support it, and access any newer classes or methods reflectively.

    Item 55: Optimize judiciously谨慎地进行优化

    • Strive for encapsulation so that a part of the system can be rewritten for performance without changing its other parts.
    • You need to measure attempted optimization carefully on the Java platform, because the language does not have a strong performance model, or well-defined relative costs.

    Item 56: Adhere to generally accepted naming conventions遵守普遍接受的命名惯例

    • Components of a package name should be short, generally eight or fewer characters, where abbreviations are encouraged and acronyms are acceptable.
    • Names of static final fields whose values are immutable should be in uppercase with words separated by underscores.
    • Methods that convert a type have the format toType, while methods that return a view have the format asType, and methods that return a primitive representation have the format typeValue.

    Chapter 9: Exceptions异常

    Item 57: Use exceptions for exceptional conditions仅在异常情况下才使用Exception

    • Do not force clients to use exceptions for ordinary control flow, and instead offer methods to test whether an exception could be thrown, such as hasNext for class Iterator.
    • Use a distinguished return value, like null, if the object is accessed by multiple threads or if the state-testing method duplicates the work of the state-dependent method.

    Item 58: Use checked exceptions for recoverable conditions and runtime exceptions for programming errors对可恢复的情况使用受检异常,对编程性错误使用运行时异常

    • Use runtime exceptions to indicate programming errors, typically precondition violations.
    • Don't implement any new Error subclasses, and don't define a throwable that does not subclass Exception or RuntimeException.

    Item 59: Avoid unnecessary use of checked exceptions避免不必要地使用受检异常

    • When designing an API, only throw a checked exception if it can be prevented by a proper use of the API, and the programmer can take some useful action once thrown.

    Item 60: Favor the use of standard exceptions优先使用标准异常

    • Throw a NullPointerException instead of an IllegalArgumentException if a caller passes in a null parameter where prohibited.
    • Throw an IndexOutOfBoundsException instead of an IllegalArgumentException if the caller passes in an invalid index for a sequence.

    Item 61: Throw exceptions appropriate to the abstraction抛出与抽象对应的异常

    • Use exception translation, where low-level exceptions are caught and exceptions appropriate to the higher-level abstraction are thrown.
    • If an exception does not have a chaining-aware constructor, use the initCause method of Throwable.
    • Try to avoid low-level exceptions by checking the higher-level method's parameters upfront.

    Item 62: Document all exceptions thrown by each method每个抛出的异常都要有文档注释

    • Document the unchecked exceptions a method can throw, thereby documenting its preconditions.
    • Do not use the throws keyword to include unchecked exceptions in a method declaration.

    Item 63: Include failure-capture information in detail messages在消息细节中包含能捕获的失败信息

    • The toString method, or "detail message," should contain the values of all the parameters and fields contributing to the exception.
    • To capture this information easily, make them parameters to the constructor, and internally generate the detail message from them.

    Item 64: Strive for failure atomicity努力使失败保持原子性

    • A failed method invocation should leave the object in the state it was prior to the invocation.
    • Typically you can easily achieve failure atomicity by checking the parameters' validity before the operation.

    Chapter 10: Concurrency并发

    Item 66: Synchronize access to shared mutable data synchronize共享的可变数据

    • Synchronization is not just for mutual exclusion, but ensuring that a value written by one thread is seen by another.
    • Both read and write operations on mutable data must be synchronized or visibility is not guaranteed.
    • Beware that the increment and decrement operators are not atomic on volatile integers.

    Item 67: Avoid excessive synchronization避免过度同步

    • Inside a synchronized region, do not invoke a method that is provided by the client as a function object, or can be overriden.
    • Reentrant locks simplify the construction of multi-threaded object oriented programs, but can allow foreign methods to access an object in an inconsistent state.
    • Only make a mutable class thread-safe if intended for concurrent use and you can achieve better concurrency with internal locking; otherwise, punt locking to the client.

    你可能感兴趣的:(Java)