• Tidak ada hasil yang ditemukan

Buku Effective Java Third Edition

N/A
N/A
Charlie Purnomo

Academic year: 2023

Membagikan "Buku Effective Java Third Edition"

Copied!
413
0
0

Teks penuh

For example, the Java programming language is object-oriented with single inheritance and supports an imperative (statement-oriented) coding style within each method. Likewise, there are dozens of books on the libraries and APIs associated with the Java programming language.

Preface to the Third Edition

Preface to the Second Edition

Preface to the First Edition

My focus on API design may seem a bit unnatural to enthusiasts of the new lightweight software development methodologies, such as Extreme Programming. I hope this book reflects my enthusiasm and allows you to use the language more effectively and enjoyably.

Acknowledgments for the Third Edition

Acknowledgments for the Second Edition

Acknowledgments for the First Edition

Consider static factory methods instead of constructors

The service access API is the flexible static factory that forms the basis of the service provider framework. A second shortcoming of static factory methods is that they are difficult for programmers to find.

Consider a builder when faced with many constructor parametersparameters

Then the client calls setter-like methods on the builder object to set each optional parameter of interest. The parameters of the builder can be adjusted between invocations of the build method to vary the objects that are created.

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

An advantage of the static factory approach is that it gives you the flexibility to change your mind about whether the class is a singleton without changing its API. A second advantage is that you can write a generic singleton factory if your application requires it (item 30).

Enforce noninstantiability with a private constructor

Prefer dependency injection to hardwiring resources

The dependency injection pattern is so simple that many programmers use it for years without knowing it has a name. This mess is almost eliminated by using a dependency injection framework like Dagger [Dagger], Guice [Guice] or Spring [Spring].

Avoid creating unnecessary objects

If a class containing an enhanced version of the isRomanNumeral method is initialized but the method is never called, the ROMAN field will be initialized unnecessarily. Although creating multiple instances of the keySet view object is mostly harmless, it is unnecessary and has no benefit.

Eliminate obsolete object references

A memory pool consists of the elements of an array of elements (object reference cells, not the objects themselves). The scavenger cannot possibly know this; for the garbage collector, all object references in the element array are equally valid.

Avoid finalizers and cleaners

While there's no guarantee that the cleaner or finalizer will work immediately (or at all), it's better to release the resource late than never if the client fails to do so. In this case, it's simply the numJunkPiles field, which represents the amount of junk in the room.

Prefer try -with-resources to try - finally

  • Use the == operator to check if the argument is a reference to this object

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

Always override toString

The advantage of specifying a format is that it serves as a standard, unambiguous, human-readable representation of an object. The toString method should return a concise, useful description of the object in an aesthetically pleasing format.

Override clone judiciously

If the clone method simply returns super.clone(), the resulting Stack instance will have the appropriate value. In order for the clone method on Stack to work properly, it must copy the internals of the stack.

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 section of the compareTo contract, which is a strong suggestion rather than a true requirement, simply states that the equality test imposed by .

Minimize the accessibility of classes and members

You can expose constants via public static final fields, provided the constants form an integral part of the abstraction from the class. From Java 9, two more implicit access levels are introduced as part of the module system.

In public classes, use accessor methods, not public fields

In the case of a private nested class, the scope of the change is further limited to the enclosing class. Several classes in the Java platform libraries violate the advice that public classes should not expose fields directly.

Minimize mutability

Instead of making an immutable class final, you can make all its constructors private or package-private and add public static factories instead of the public constructors (point 1). You should only provide a public mutable companion class to your immutable class when you have confirmed that it is necessary for satisfactory performance (paragraph 67).

Favor composition over inheritance

Each instance method in the new class invokes the corresponding method on the containing instance of the existing class and returns the results. Inheritance is only appropriate in circumstances where the subclass is indeed a subtype of the superclass.

Design and document for inheritance or else prohibit it

Then replace each self-invocation of an overridable method with a direct call to the overridable method's private helper method. You must document all of its self-use patterns, and once you have documented them, you must commit to them for the life of the class.

Prefer interfaces to abstract classes

By convention, skeletal implementation classes are called AbstractInterface, where Interface is the name of the interface they implement. Whenever possible, you should provide the skeleton implementation via default methods on the interface so that all implementers of the interface can make use of it.

Design interfaces for posterity

The Apache version also provides the option to use a client-supplied object for the lock instead of a collection. Although default methods are now part of the Java platform, it is still very important to design interfaces carefully.

Use interfaces only to define types

Consider adding underscores to numeric literals, whether fixed or floating-point, if they contain five or more consecutive digits. 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 corresponding implementation of each abstract method in the root class. 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.

Favor static member classes over nonstatic

Common use of public class non-static member class MySet extends AbstractSet. Therefore, it would be wasteful to use a non-static member class to represent inputs: a private static member class is best.

Limit source files to a single top-level class

Thus, the program's behavior is affected by the order in which the source files are passed to the compiler, which is clearly unacceptable. The compiler automatically casts for you and tells you at compile time if you try to cast an object of the wrong type.

Don’t use raw types

Test.java:10: warning: [untagged] untagged call to add(E) as a member of raw type List. If you replace the raw type List with the parameterized type List.

Eliminate unchecked warnings

If you find yourself using the SuppressWarnings annotation on a method or constructor that is more than one line long, you might want to move it to a local variable declaration. It is illegal to put a SuppressWarnings annotation on the return because it is not a statement [JLS, 9.7].

Prefer lists to arrays

List array to an Object array variable, which is legal because arrays are covariant. Types such as E, List, and List are technically known as immutable types [JLS, 4.7].

Favor generic types

As explained in Item 28, you cannot create an array of a non-reverifiable type, such as E. Again, you can easily prove to yourself that the unchecked cast is safe, so it is appropriate to suppress the warning.

Favor generic methods

Using a recursive type bound to express mutual comparability public static > E max(Collection c);. Returns max value in a collection - uses recursive typebound public static > E max(Collection c).

Use bounded wildcards to increase API flexibility

The wildcard type for a parameter that serves as a producer E public void pushAll(Iterable src). The wildcard type for the parameter that serves as a public T selector producer (Collection selections).

Combine generics and varargs judiciously

In Java 7, the SafeVarargs annotation was added to the platform to allow the author of a method with a generic varargs parameter to automatically suppress client warnings. Whenever the compiler warns you about possible heap pollution of a generic varargs parameter in a method you control, make sure the method is safe.

Consider typesafe heterogeneous containers

The next thing to notice is that the value type of favoritesMap is simple. It simply checks that its argument is an instance of the type represented by the class object.

Use enums instead of int constants

An enum type can start life as a simple collection of enum constants and evolve over time into an abstract abstraction. It is not necessary for the set of constants in an enum type to remain fixed forever.

Use instance fields instead of ordinals

Use EnumSet instead of bit fields

Here's what the previous example looks like when it's changed to use enums and enum sets instead of bit fields. The EnumSet class combines the precision and performance of bit fields with all the many advantages of enum types described in Section 34.

Use EnumMap instead of ordinal indexing

So, for example, if a garden contains annuals and perennials, but not biennials, the ByLifeCycle plant size will be three in the EnumMap version and two in both flow-based versions. The map type is Map>, which means "map from (source) phase to map from (destination) phase to transition." This map of maps is initialized using a cascading sequence of two collectors.

Emulate extensible enums with interfaces

You can define another enum type that implements this interface and use instances of this new type instead of the base type. For example, suppose you want to define an extension to the type of operation shown earlier, consisting of the exponentiation and remainder operations.

Referensi

Dokumen terkait