1. Use static factory methods instead of constructors

Advantages of the static factory method: Unlike constructors, it has a name. It does not need to create a new object every time it is called. It can return objects of any subtype of its return type. The class of the returned object can be different depending on the input parameter. When writing the class containing this method, the class of the returned object need not exist.

2. Use Builder mode when there are too many constructor parameters

When using constructors with too many attributes in an object, too many parameters make it difficult to maintain and to read the meaning of each parameter.

How about using constructors to build mandatory arguments and setters to pass optional arguments? This seems to have few arguments, it’s easy to create instances, and the generated code is easy to read. But because the JavaBeans pattern itself is severely flawed, JavaBeans can be in an inconsistent state as constructors are split in multiple calls, and additional work is required to ensure thread-safety.

The best way to deal with parameter overabundance is to use The Builder pattern, which combines the security of the scalable constructor pattern with the readability of the JavaBeans pattern, and then set each optional parameter by calling setter like methods of the Builder object.

3. Inject resources in dependency injection mode

The practice of dependency injection will greatly enhance the flexibility, reusability, and testability of classes.

4. Don’t create unnecessary objects

If the object is immutable, it can always be reused. For example, if the String class is final and immutable, it is best not to use new String(“test”) because it creates a new object every time. In cases where performance is critical, use base types in preference to boxed base types, and also be aware of unintentional auto-boxing, which can affect performance.

5. Eliminate expired object references

This is also known as a memory leak. When a class manages its own memory, it should be wary of memory leaks. Whenever an element is released, any object references contained in the element should be purged.

Another common source of memory leaks is the cache. Once you put an object reference into the cache, it’s easy to forget that it exists, and you can use WeakHashMap to represent the cache.

6. Avoid using Finalizer or Cleaner. Use try-with-resources instead

The uncertainty of the Finalizer and Cleaner mechanism, we don’t know exactly when it will be implemented. For example, relying on Finalizers and Cleaner mechanisms to close files is a serious mistake because open file descriptors are limited resources. If many files are opened due to delays in running Finalizer and Cleaner, the program may fail because it can no longer open the files. You can use either a try-with-resources statement or a try-finally statement, which is not as readable as a try-with-resources statement when opening multiple files, The try-with-resources statement is therefore recommended.

7. Rewrite hashCode as well as equals

When overriding the equals method, the following properties need to be met. Reflexivity: An object must be equal to itself. Symmetry: Any non-empty references to x and y must return true if and only if y.quals (x) returns true. Transitivity: If the first object is equal to the second object and the second object is equal to the third object, then the first object must be equal to the third object. Consistency: If two objects are equal, they must always remain equal unless one (or both) objects have been modified. Non-null: for any non-null reference to x, x.equals(null) must return false.

The hashCode method must be overridden every time the Equals method is overridden, otherwise the program will not work. The hashCode method must follow the general convention specified by the Object class to assign different hash codes to different instance objects.

Always override the toString method

The Object class provides an implementation of the toString method as an unsigned hexadecimal of the package name + class name +@+ hash code. The general convention for toString requires that the returned string be “a concise but rich representation that is easy for people to read.” We need toString for readability.

9. Consider implementing the Comparable interface

In scenarios where comparability is required, it is best to implement the Comparable interface to make it easy to sort, search, and use examples in a comparison-based collection. Avoid using the “<” and “>” operators when comparing field values in implementations of compareTo methods. It is best to use the static compare method in the wrapper class or the build method in the Comparator interface.

10. Minimize accessibility of classes and members

A well-designed component hides all of its implementation details, cleanly separating its API from its implementation. Components then communicate only through their apis and have no idea of each other’s inner workings. Information hiding or encapsulation is a basic principle of software design.

There are four levels of access in Java: private — self access only. Package-private — Default level for access to any class in the package. Protected — Subclasses and themselves are accessible. Public — Any class is accessible.

PS: Clear mountains and clear waters begin with dust, knowledge is more valuable than diligence. I got wine. You got a story? Wechat official account: “Clean the dust chat”. Welcome to chat and talk about code.