• Tidak ada hasil yang ditemukan

Effective Java, 2nd Edition.pdf

N/A
N/A
Protected

Academic year: 2023

Membagikan "Effective Java, 2nd Edition.pdf"

Copied!
369
0
0

Teks penuh

James Gosling, colleague and vice president of Sun Microsystems, Inc., and inventor of the Java programming language. Gilad Bracha, renowned engineer at Cadence Design Systems, and co-author of The Java™ Language Specification, Third Edition (Addison-Wesley, 2005).

Preface to the Second Edition

Preface to the First Edition

Even if you're not developing reusable components, thinking in these terms tends to improve the quality of the software you write. My focus on API design may seem a bit unnatural to followers of new lightweight software development methodologies such as Extreme Programming [Beck99].

Acknowledgments for the Second Edition

Acknowledgments for the First Edition

Consider static factory methods instead of constructors

A class can provide a public static factory method, which is simply a static method that returns an instance of the class. The service access API is the "flexible static factory" that forms the basis of the service provider framework.

Consider a builder when faced with many constructor parametersparameters

The client then calls the setter-like methods on the builder object to set each optional parameter it is interested in. Builder parameters can be changed during object creation to make the objects change.

Enforce the singleton property with a private constructor or an enum type constructor or an enum type

The main advantage of the public field approach is that the declarations make it clear that the class is a singleton: the public static field is final and will therefore always contain the same object reference. An advantage of the factory method approach is that it gives you the flexibility to change your mind about whether the class should be a singleton without changing the API.

Enforce noninstantiability with a private constructor

Avoid creating unnecessary objects

The TheisBabyBoomer method unnecessarily creates a new calendar, timezone, and two date instances each time it is called. While creating multiple instances of the keySet view object is harmless, it is also unnecessary.

Eliminate obsolete object references

The storage pool consists of the elements of the elements array (the object reference cells, not the objects themselves). The garbage collector has no way of knowing this; for the garbage collector, all the object references in the elements array are equally valid.

Avoid finalizers

  • Use the == operator to check if the argument is a reference to this object
  • Use the instanceof operator to check if the argument has the correct type
  • When you are finished writing your equals method, ask yourself three questions: Is it symmetric? Is it transitive? Is it consistent? And don’t just

The performance of the equals method can be affected by the order in which fields are compared. If you're simply testing fields for equality, it's not hard to stick to the equals contract.

Always override hashCode when you override equals

By multiplying in step 2.b, the result depends on the order of the fields, which gives a much better hash function if the class has many similar fields. Don't be tempted to exclude important parts of the object from the hash code calculation to improve performance. This is generally not a good idea, as it severely limits your ability to improve the hash function in future releases.

Always override toString

The advantage of specifying the format is that it serves as a standard, unambiguous, human-readable representation of the object. The downside to specifying the format of the toString return value is that once you specify it, you're stuck with it for life, assuming your class is widely used. Whether or not you specify the format provides programmatic access to all the information contained in the value returned by toString.

Override clone judiciously

So if you override the clone method in a nonfinal class, you must return an object obtained by calling super.clone. Object's clone method is declared to throw CloneNotSupportedException, but overriding clone methods can omit this declaration. Object's clone method is not synchronized, so even if it is otherwise satisfactory, you may need to write a synchronized clone.

Consider implementing Comparable

If you want to add a value component to a class that implements Comparable, don't extend it; write an unrelated class that contains an instance of the first class. The final paragraph of the CompareTo contract, which is a strong suggestion rather than an actual provision, simply states that the equality test imposed by the. Also note that the parameter of the CompareTo method is a CaseInsensitive-String and not an object.

Minimize the accessibility of classes and members

But reducing the availability of a free public class is far more important than for a package-private top-level class: the public class is part of the package's API, while the package-private top-level class is already part of its implementation. Fortunately, that's not necessary either, since tests can be made to run as part of the package being tested, thus accessing its package-private elements. You can expose constants via public static final fields, provided the constants form an integral part of the abstraction from the class.

In public classes, use accessor methods, not public fields

This approach generates less visual clutter than the accessor method approach, both in the class definition and in the client code that uses it. In the case of a nested private class, the scope of the change is further limited to the enclosing class. Some classes in the Java platform libraries violate the advice that public classes should not expose fields directly.

Minimize mutability

The batch-private mutable companion class approach works well if you can predict exactly what complex multi-step operations clients will want to perform in your immutable class. Another way to make a final class immutable is to make all its constructors private or package private and to add public static factories instead of public constructors (point 1). Provide a public mutable companion class for your immutable class only after you confirm that it is necessary to achieve satisfactory performance (point 55).

Favor composition over inheritance

This design is called composition because the existing class becomes a component of the new one. Each instance method in the new class calls the corresponding method on the enclosing instance of the existing class and returns the results. Inheritance is only appropriate in circumstances where the subclass is actually a subtype of the superclass.

Design and document for inheritance or else prohibit it

In the case of the readObject method, the overriding method will run before the subclass state has been deserialized. In the case of the clone method, the overriding method will run before the subclass's clone method has a chance. Then replace each self-invocation of an overridable method with a direct call to the overridable method's private helper method.

Prefer interfaces to abstract classes

The interface still defines the type, but the skeleton implementation takes all the work out of the implementation. For most interface implementers, extending the skeleton implementation is an obvious choice, but it is strictly optional. If you export a non-trivial interface, you should strongly consider providing a skeleton implementation to accompany it.

Use interfaces only to define types

Typically, a helper class requires clients to qualify constant names with the class name, for example PhysicalConstants.AVOGADROS_NUMBER.

Prefer class hierarchies to tagged classes

Also include in each subclass the appropriate implementation of each abstract method in the main class. The code is simple and clear and contains none of the boilerplate text from the original. The compiler ensures that each class's constructor initializes its data fields, and that each class has an implementation for each abstract method declared in the root class.

Use function objects to represent strategies

In other words, we need to define a strategy interface to go with the concrete strategy class. Instead, a "host class" can export a public static field (or static factory method) whose type is the strategy interface, and the concrete strategy class can be a nested private host class. When a concrete strategy is designed for repeated use, it is generally implemented as a private static member class and exported to a final public static field whose type is the strategy interface.

Favor static member classes over nonstatic

Typical usage of a non-static member class public class MySet extends AbstractSet . Therefore, using a non-static member class to represent entries would be wasteful: a private static member class is best. If each instance of the member class needs a reference to its enclosing instance, make it non-static; otherwise, make it static.

Don’t use raw types in new code

Just what is the difference between the raw type List and the parameterized type List. If you replace the raw type List with the parameterized type List. What is the difference between the unbounded wildcard type Set and the raw type Set.

Eliminate unchecked warnings

The SuppressWarnings annotation can be used at any level of granularity, from the declaration of a single local variable to the entire class. If you find yourself using the SuppressWarnings annotation on a method or constructor that is longer than one line, you may be able to move it to a local variable declaration. If you cannot resolve an unchecked warning, and you can prove that the code that raised it is type-safe, suppress the warning with the @SuppressWarnings("unchecked") annotation to the narrowest extent possible.

Prefer lists to arrays

List array into an Object array variable, which is legal because arrays are covariant. Types like E,List and List are technically known as non-reifiable types [JLS, 4.7]. If the function multiplies two integer values, the method returns the product of the values ​​in the list.

Favor generic types

As explained in item 25, you cannot create an array of a non-returnable type, such as E. Again, you can easily prove to yourself that the unmarked cast is safe, so suppressing the warning is appropriate. The vast majority of generic types are like our Stack example in that their type parameters have no restrictions: you can create a Stack, .

Favor generic methods

Creating an instance of a parameterized type using Map> constructor anagrams. Creating an instance of a parameterized type with static factory anagrams Map> = newHashMap();. Here is a sample program that uses our generic singleton as UnaryFunction and UnaryFunction.

Use bounded wildcards to increase API flexibility

A wildcard type for a parameter that serves as a producer E static E reduce(List list, Function f, . E initVal). Note that the return type is still Set. Do not use wildcards as return types. Therefore, the parameterized type Comparable is replaced by the restricted replacement type Comparable<.

Consider typesafe heterogeneous containers

The thing to note is that the wildcard type is nested: it is not the type of card that is a wildcard type, but the type of its key. The next thing you'll notice is that the value type of the favorites card is simple. It simply checks whether the argument is an instance of the type represented by the Class object.

Use enums instead of int constants

For example, suppose you are writing an enum type to represent the operations on a basic four-function calculator, and you want Implementation of a fromString method on a private static final Map of type enum stringToEnum. It is not necessary for the set of constants in an enum type to remain fixed all the time.

Use instance fields instead of ordinals

Use EnumSet instead of bit fields

Here's what the previous example looks like when modified to use enums instead of bit fields. In summary, just because an enumerated type will be used in sets, there is no reason to represent it with bit fields. The EnumSet class combines the brevity and performance of bit fields with all the many benefits of enum types, described in Item 30.

Use EnumMap instead of ordinal indexing

Using an EnumMap to bind data to a Map enum> herbsByType. Returns the phase transition from one phase to another public static Transition from(Phase src, Phase dst). The map type is Map>, which means "map from phase (source) to map from phase (destination) to transition". The first loop in the static initializer block initializes the outer map to contain the three empty inner maps.

Emulate extensible enums with interfaces

While the enum type (BasicOperation) is not extensible, the interface type (Operation) is, and it is the interface type used to represent operations in APIs. You can define another enum type that implements this interface and use instances of that new type instead of the base type. These enums can then be used wherever the base enum type can be used, assuming the APIs are written in terms of an interface.

Prefer annotations to naming patterns

The declaration for the annotation type Test is itself annotated with the annotations Retention and Target. The four methods that are not annotated Test will be ignored by the testing tool. It is quite simple to modify the test execution tool to handle the new version of ExceptionTest.

Consistently use the Override annotation

Referensi

Dokumen terkait

19: 4-2 2017 93–103 | www.sainshumanika.utm.my | e-ISSN ISSN: 2289-6996 Full paper Sains Humanika Patient Decision Aids in Doctor-Patient Consultations: Treatment Decision