First of all, let’s get things straight

The key to attracting customers is to do the job at hand well. Take care of what you have and the rest will come to you. I think it’s not just business, investment… Four to have proper, here I just want to warn myself, for myself now, I may not be able to do many things, but I should do everything as far as possible, I can not so fast, but I should be so good, all night long, liu took out prostitutes to describe programmer, the port back up the heavy burden of more than two hundred years ago the porter, Say we are “technology” of the proletariat, indeed in ma father quote us for the blessing of the 996 as it is, to keep up with the torrent of Internet code a make a living, as programmers have disenchantment, because is not mysterious, so ordinary, may be because of this combined with a variety of external factors or internal reason, Many of us are to code and dozen 🌧 code, the appearance of a state of mind as a direct result of the various programmers commonly used statement, no matter, they can run, various Buddha programmers to come, I saw all vegetation, living beings should see me so, Buddha is a programmer myself included, so hold even today, I once again reviewed the “Alibaba Java Development Manual (V1.5.0 Huashan Edition)” and the well-known “Effective.Java”, which I had forgotten. This series of articles is a record of my notes and some insights from reading Effective.Java. In addition to helping me remember, it is more about sharing and spreading knowledge. Among them, there is a mistake please you great god advice, day arch a pawn no have to do, don’t tang donated to the sea, every day just need to progress a little bit

The Effective. Java”

1. Consider using static factory methods instead of constructors

Traditionally we use constructors to get an instance of a class, but there is a technique that provides a public static factory method inside a class that returns a static method of the class instance

/* Equals equals equals equals equals equals equals equals equals equals equals equals equals equals equals equals For Integer values, if the value is between -128 and 127, you can use == to determine the value. However, all data outside of this range will be generated on the heap, and existing objects will not be reused. Integercache.valueof (0) in the range -128 to 127 is the value */ obtained from the integerCache. cache array using the share mode
Integer.valueOf(0);
String.valueOf("");

Boolean.valueOf(false);
public static Boolean valueOf(boolean b) {
       return (b ? TRUE : FALSE);
  } 
Copy the code

Note ⚠ : This static factory is not a static factory in design mode

Provides the benefits of the static factory approach
  • Unlike constructors, they are named, making them easier to read and use for static factories with names
  • You don’t need to create an object for every call
  • Can return an object of any subtype of its return type
  • The class of the returned object can be different depending on the input parameter
  • When writing a class that contains this method, the class that returns the object need not exist
Provides disadvantages of the static factory approach
  • Classes that have no public or protected constructor cannot be subclassed
  • It’s hard for programmers to find them

Common static factory names

  • The from type conversion method
Date d = Date.from(instant);
Copy the code
  • The of aggregation, which takes multiple parameters and returns an instance of that parameter and merges them together
Set faceCards = EnumSet.of(JACK,QUEEN,KING);
Copy the code
  • More detailed alternatives to valueOf from and to
Boolean.valueOf(false);
Copy the code
  • The instance or getInstance
Object newArray = Array.newInstance(classObject, arrayLen);
Copy the code
  • GetType is similar to getInstance, but if used in a different class in a factory method. Type is the object Type returned by the factory method
FileStore fs = Files.getFileStore(path);
Copy the code
  • NewType is similar to newInstance, but if used in a different class in a factory method. Type is the object Type returned by the factory method
BueredReader br = Files.newBueredReader(path);
Copy the code
  • Type getType and newType are concise alternatives
List litany = Collections.list(legacyLitany);
Copy the code

Both static factory methods and public constructors have their uses, and in general, static factories are preferred, so avoid providing public constructors without considering static factories

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

Builder mode even Builder mode, I am in myPrevious postLombok also provides the @Builder annotation to encapsulate the code. Lombok is not recommended to use Lombok, but I haven’t looked at it closely. No major bugs), for this, the book gives an example of packaged food. Let’s take a look at a small phenomenonHere’s the reasonFinal modifies a non-static field that must be explicitly assigned once and only once before the virtual machine allocates space for it, you can use the constructor to assign a value to it.

/ * * *@authorTan Jing jie *@date2020/11/25 * * /
public class NutritionFacts {
	private final int servingSize; // Daily intake (mL) required
	private final int servings; // Per container required
	private final int calories; // Calories are optional
	private final int fat; // Total fat (g/serving) optional
	private final int sodium; / / sodium (mg per serving) optional
	private final int carbohydrate;// Carbohydrate (g/serving) optional

	public NutritionFacts(int servingSize, int servings) {
		this(servingSize, servings, 0);
	}

	public NutritionFacts(int servingSize, int servings, int calories) {
		this(servingSize, servings, calories, 0);
	}

	public NutritionFacts(int servingSize, int servings, int calories, int fat) {
		this(servingSize, servings, calories, fat, 0);
	}

	public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium) {
		this(servingSize, servings, calories, fat, sodium, 0);
	}

	public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium, int carbohydrate) {
		super(a);this.servingSize = servingSize;
		this.servings = servings;
		this.calories = calories;
		this.fat = fat;
		this.sodium = sodium;
		this.carbohydrate = carbohydrate; }}Copy the code

Client call mode

public static void main(String[] args) {
	NutritionFacts cocaCola = new NutritionFacts(240.8.100.10.35.27);
}
Copy the code

At first glance, perfect, but if we don’t need a certain value, still have to give it a value, for example sodium is not choice value, but we still have to give it a pass a zero value, and if more and more parameters, and the number of arguments will be more and more, when encountered many optional parameter in the constructor, Another option is the JavaBeans pattern, in which an object is created by calling a no-argument constructor and then calling setter methods to set each required and optional argument, such as:

NutritionFacts cocaCola = new NutritionFacts();
cocaCola.setServingSize(240);
cocaCola.setServings(8);
cocaCola.setCalories(100);
cocaCola.setSodium(35);
cocaCola.setCarbohydrate(27);
Copy the code

While this pattern solves the above problem, it also introduces some new problems, such as inconsistencies in the construction process, or too many parameters that can easily be left out (I always miss fields anyway…). A better solution is a form of The Builder pattern, where the client does not call the required object directly, but instead calls the constructor and takes the necessary parameters to get a Builder object

/ * * *@authorTan Jing jie *@date2020/11/25 * * /
public class NutritionFacts {
	// In actual development, each argument needs to be checked for validity. If the check fails, IllegalArgumentException is thrown

	private final int servingSize; // Daily intake (mL) required
	private final int servings; // Per container required
	private final int calories; // Calories are optional
	private final int fat; // Total fat (g/serving) optional
	private final int sodium; / / sodium (mg per serving) optional
	private final int carbohydrate;// Carbohydrate (g/serving) optional

	public static class Builder {
		// Required parameters
		private final int servingSize;
		private final int servings;
		// Optional parameters - initialized to default values
		private int calories = 0;
		private int fat = 0;
		private int sodium = 0;
		private int carbohydrate = 0;

		public Builder(int servingSize, int servings) {
			this.servingSize = servingSize;
			this.servings = servings;
		}

		public Builder calories(int val) {
			calories = val;
			return this;
		}

		public Builder fat(int val) {
			fat = val;
			return this;
		}

		public Builder sodium(int val) {
			sodium = val;
			return this;
		}

		public Builder carbohydrate(int val) {
			carbohydrate = val;
			return this;
		}

		public NutritionFacts build(a) {
			return new NutritionFacts(this); }}private NutritionFacts(Builder builder) { servingSize = builder.servingSize; servings = builder.servings; calories = builder.calories; fat = builder.fat; sodium = builder.sodium; carbohydrate = builder.carbohydrate; }}Copy the code

The client call is:

public static void main(String[] args) {
		new NutritionFacts.Builder(10.20).calories(12).fat(13).build();
	}
Copy the code

This seems not only easy to write, but more importantly easy to read, two word professionalIf you are using poJO code generated automatically using various reverse engineering methods, you can create a base abstract implementation class for future generations to implement their build methods

advantages

  • There are multiple mutable parameters, each specified in its own method
  • The flexibility is so great that a Bulider can be reused to build multiple objects

disadvantages

  • In order to create an object, it must first create its Builder, which is more verbose than the flex constructor pattern and therefore only available in

It is worth using it only if you have enough arguments, such as four or more **

3. Implement Singleton using private constructors or enumerated classes

Singleton translation is a Singleton, namely the Singleton pattern in our design pattern (ensure a class has only one instance and provide a global point of access to access it), in general, realize the Singleton pattern, usually have a lot of kinds, such as LanHanShi, hungry Chinese type, double check the lock check type, as create the global properties of classes exist, create classes to be loaded when created, Enumeration, etc., is more recommended to use enumeration to create a singleton pattern. In this article, we first give two examples of singleton pattern, as follows:

A singleton implementation decorates member variables with final, such as

public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis(a) {... }public void leaveTheBuilding(a) {... }}Copy the code

The private constructor is called only once to initialize the public static final Elvis.instance property. A way that there is a loophole: privilege. The client can use AccessibleObject setAccessible method, using reflection to invoke private constructor (solution: modify the constructor, the request to create the second instance when the throw is.) Another is that the public member is a static factory method

// Singleton with static factory
public class Elvis {
private static final Elvis INSTANCE = new Elvis();
private Elvis(a) {... }public static Elvis getInstance(a) { return INSTANCE; }
public void leaveTheBuilding(a) {... }}Copy the code

The main advantage of the public property method is that the API explicitly states that the class is a singleton: the public static property is modified by final, so it always contains the same object reference. The second benefit is that it’s simpler. Finally, method references can use supplier. For example, Elvis::instance equals supplier

Note ⚠ : Using these two methods requires overriding the Serializable readResolve method to prevent it from creating an instance in deserialization, and instance attributes should also be declared transient

Finally, there is a proposed approach, enumeration generation

public enum Elvis {
INSTANCE;
public void leaveTheBuilding(a) {... }}Copy the code

Similar to the public property method, it provides a free serialization mechanism that is resistant to serialization and reflection attacks

4. Perform non-instantiation using private constructors

Suppose you have a class that contains only static methods and static properties. Such classes get a bad rap because some people abuse them to avoid thinking object-oriented, but they do have special uses. The idea here is that this class does not need to be designed to be instantiated, because static methods can be directly class names. Method name (attribute name), so instantiation is meaningless, but when explicitly declaring a constructor, the compiler voluntarily provides a no-argument constructor, which to the user is no different from any other constructor, right

It was stated that trying to enforce non-instantiation by creating abstract classes does not work. Classes can be subclassed, and subclasses can be instantiated. In addition, it misleads users into thinking that the class is designed for inheritance. However, there is a simple way to ensure non-instantiation. A default constructor is generated only if the class does not contain an explicit constructor, so class de-instantiation can be achieved by including a private constructor, for example:

/* * This habit has the side effect of preventing classes from subclassing. All constructors must call the parent constructor either explicitly or implicitly, while subclasses have no accessible parent constructor to call. Public UtilityClass {private UtilityClass() {// Disallow non-instantiated default constructors // AssertionError exceptions are not strictly required, but provide a guarantee that In case a constructor is accidentally called on a class. throw new AssertionError(); }}Copy the code

05. Dependency Injection is superior to Hardwiring Resources

Dependency injection yes, you read that right, the Spring dependency injection, where many classes in a project depend on one or more underlying resources. The example in this article is a spell-checker that relies on dictionaries and can be implemented in several ways

// Static utility class
public class SpellChecker {
private static finalLexicon dictionary = ... ;private SpellChecker(a) {} // Noninstantiable
public static boolean isValid(String word) {... }public static List<String> suggestions(String typo) {... }}// singleton implementation
public class SpellChecker {
private finalLexicon dictionary = ... ;private SpellChecker(...). {}
public static INSTANCE = newSpellChecker(...) ;public boolean isValid(String word) {... }public List<String> suggestions(String typo) {... }}Copy the code

Both approaches are unsatisfactory because they assume that only one dictionary is worth using. In practice, each language has its own dictionary, and special dictionaries are used for special vocabularies. It is also advisable to use a specialized dictionary for testing. It is wishful thinking to assume that a dictionary will suffice, and instead pass resources into the constructor when creating a new instance. This is a form of dependency injection ** : the dictionary is a dependency of the spell checker that is injected into the spell checker when it is created, with improved code like:

// Dependency injection provides flexibility and testability
public class SpellChecker {
private final Lexicon dictionary;
public SpellChecker(Lexicon dictionary) {
RequireNonNull; // objects. requireNonNull
this.dictionary = Objects.requireNonNull(dictionary); 
}
public boolean isValid(String word) {... }public List<String> suggestions(String typo) {... }}Copy the code

advantages

  • The dependency injection pattern is simple, it can use any number of resources and any dependency graph, maintaining invariability so that multiple clients can share dependency objects (also applies to constructor, static factory, and Builder patterns)
  • Provides class flexibility and testability

disadvantages

It can clutter large projects, which often contain thousands of dependencies. Using dependency injection frameworks such as Dagger [Dagger], Guice [Guice], or Spring [Spring] can eliminate these messes.

In general, do not implement a class using singletons or static utility classes that depend on one or more underlying resources whose behavior affects the behavior of the class, and do not let the class create those resources directly. Instead, pass the resource or factory to the constructor (or static factory or Builder pattern). This practice, called dependency injection, will greatly increase the flexibility, reusability, and testability of classes.

6. Avoid creating unnecessary objects

This chapter, it is a cliche, tell us a little bit code in DE programmers know that meaningless things, don’t throw has fired home for a while now, ha ha ha 😀, so every time the best way is to need to reuse an object instead of creating a new same function object, a few extreme cases (note is a counter example, didn’t make a mask)

// Each execution of this statement creates a String. The argument to the String constructor (" Bikini ") is itself an instance of Bikini, which has the same function as all objects created by the constructor

String s = new String("Tan Jingjie");
// The best way to declare it is to assign it directly
String s = "Tan Jingjie"

// Or by using the static factory method
Boolean.valueOf(false)
Copy the code

Another way to do this is to cache objects that are expensive, and I think Integer is a nice example, and the last one is to prioritize primitives over boxed primitives, and also to be aware of automatic boxing.

Note ⚠ : This entry should not be misunderstood to imply that object creation is expensive and should be avoided. In contrast, it is very cheap to create and recycle small objects using constructors, which do very little display work, especially on modern JVM implementations. It’s often a good thing to create additional objects to enhance your program’s clarity, simplicity, or functionality. Conversely, unless the objects in the pool are very heavyweight, it is a bad idea to avoid object creation by maintaining your own object pool. A typical example of an object pool is a database connection. The cost of establishing connections is very high, so it makes sense to reuse these objects. In general, however, maintaining your own object pool can clutter your code, increase memory footprint, and hurt performance. Modern JVM implementations have highly optimized garbage collectors that easily outperform such object pools on lightweight objects.

The corresponding point in this item is defensive copying in item 50. The current entry says: “Do not create a new object when you should reuse an existing object”, while entry 50 says: “Do not reuse an existing object when you should create a new object.” Note that the cost of reusing the objects required for defensive replication is far greater than the cost of creating duplicate objects unnecessarily. Failure to copy defensively when needed leads to potential errors and security vulnerabilities; Creating objects unnecessarily only affects the style and performance of the program.

7. Eliminate expired object references

Although Java is not like C, programmers need to manually recycle resources, but in some conditions as a Java programmer we still need to consider object recycling, see the example code in the article

// Can you spot the "memory leak"?
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack(a) {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop(a) {
if (size == 0)
throw new EmptyStackException();
return elements[--size];
}
/**
* Ensure space for at least one more element, roughly
* doubling the capacity each time the array needs to grow.
*/
private void ensureCapacity(a) {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1); }}Copy the code

This program appears to have no problems, but in fact it has a vulnerability called a memory leak, which silently degrades performance and even generates OutofMemoryErrors due to increased garbage collector activity, or increased memory usage

So where is the memory leak?

If a stack grows and shrinks, objects that pop off the stack are not garbage collected, even if the program that uses the stack no longer references them. This is because the stack maintains out-of-date references to these objects (references). An expired reference is simply a reference that is never removed. In this case, any reference other than “active portion” of the element array is expired. The active part consists of elements whose index subscript is less than size

The solution

The solution to this problem is simple: Once object references expire, set them to NULL. In the case of our Stack class, references to elements are set to expire as soon as they are popped from the Stack. A modified version of the POP method looks like this:

public Object pop(a) {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; // Eliminate obsolete reference
return result;
}
Copy the code

That way, if they are subsequently referenced incorrectly, the program immediately throws a NullPointerException

When to empty references

Storage pool is actually a large array of so-called pointer in c is the array index, in addition to the active element in the array is also our assignment of elements are assigned, the others are all free, that said that view is the fact that but do you know do not represent garbage collector know, so whether useful useless, all objects in the array are effective, The same is true in JavaScript advanced programming, but it means that the closure holds an HTML element in its scope chain, which means that the element cannot be destroyed. See 7.2.3 Memory Leaks. Once the elements in the array become an inactive part, you can manually clear references to those elements. Even when a class manages memory itself, we 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 caching, and there are several solutions to this problem. First, as long as there is a key reference to an entry outside the cache, then the entry is clearly associated, and WeakHashMap can be used to represent the cache. WeakReference (key= current thread, value= thread-local variable cache value). However, it still has memory leakage problem. There are many blogs on the web to find out why. Here’s a snippet of ThreadLocal code:

public T get(a) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if(map ! =null) {
            // The map is its class member, ThreadLocalMap
            ThreadLocalMap.Entry e = map.getEntry(this);
            if(e ! =null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                returnresult; }}return setInitialValue();
    }
    
    // This Entry is in the ThreadLocalMap class
    static class Entry extends WeakReference<ThreadLocal<? >>{
            /** The value associated with this ThreadLocal. */Object value; Entry(ThreadLocal<? > k, Object v) {super(k); value = v; }}Copy the code

Another is that the useful life cycle of cached items is less clear, and some items become less valuable over time. In this case, the cache should occasionally clean up obsolete items. This can be achieved by a background thread (and perhaps ScheduledThreadPoolExecutor) or add new items to the cache in to clean up, such as the LinkedHashMap class USES its removeEldestEntry method to achieve the latter

The last common source of memory leaks is listeners and other callbacks. If you implement an API whose clients register callbacks but do not explicitly unregister callbacks, they will accumulate unless some action is taken. One way to ensure that callbacks are garbage collection is to store only weak references, for example, only in the key of a WeakHashMap.

8. Avoid using Finalizers and Cleaner

Java provides a finalize method to finalize resource release, which is similar to the destructor in C++. Finalizers are generally unpredictable. The Cleaner mechanism replaces the Finalizer mechanism in Java 9. Cleaner is less dangerous but still unpredictable. In Java, when an object becomes unreachable, the garbage collector reclaims the storage space associated with the object without additional work by the developer. But being unreachable does not necessarily mean being recycled. To be or not to be is a question that I added to 🤭, Shakespeare’s classic quote: to be or not to be, To be or not To be–this is the question


To be or not To be–this is the question.

In the reachability analysis algorithm, unreachable objects are not necessarily dead. At this time, they are temporarily in the “probation” stage. In order to truly declare an object dead, at least two marking processes must be experienced:

  • If an object is found to have no reference chain connected to GC Roots after reachabality analysis, it will be marked for the first time and filtered if it is necessary to execute the Finalize () method. When an object does not overwrite a Finalize () method, or a Finalize () method has already been called by a virtual machine, the virtual machine considers both cases “not necessary to execute”.)

  • If the object is judged to be necessary to execute finalize (), then the object will be placed ina Queue called f-Queue (to be executed later by a low-priority Finalizer thread automatically set up by the virtual machine. “execute” means the virtual machine will trigger the method. But doesn’t promise to wait it out)

If an object executes slowly in Finalize (), or an infinite loop (more extreme case) occurs, it is likely to cause other objects in the F-queue to wait forever, or even cause the entire memory reclamation system to crash.

The Finalize () method is the last chance for objects to escape death. Later, GC will make a second small tag on objects in the F-queue. If objects want to save themselves successfully in Finalize () — just re-associate with any object on the reference chain, For example, if you assign yourself (this keyword) to a class variable or member variable of an object, it will be removed from the collection on the second tag; If the object hasn’t escaped at this point, it’s basically been reclaimed.


It is important not to trust system. gc and system. runFinalization methods. They may increase the chances that finalizers and Cleaner mechanisms will be implemented, but there is no guarantee that they will.

A method to free an object

Instead of writing finalizers and Cleaner machines for objects that need to be wrapped around resources (such as files or threads), have your class implement the AutoCloseable interface. Or use try-with-resources (JDk1.7 syntax), usually used to ensure termination, even in the face of an exception thrown

9. Replace try-finally statements with try-with-resources statements

Try-with-resources is a method introduced in jdk1.7. Previously, we used try-finally to release resources, such as

static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally{ br.close(); }}Copy the code

The problem with this approach is that when you add a second resource, your code looks like this

// try-finally is ugly when used with more than one resource!
static void copy(String src, String dst) throws IOException {
InputStream in = new FileInputStream(src);
try {
OutputStream out = new FileOutputStream(dst);
try {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
} finally{ out.close(); }}finally{ in.close(); }}Copy the code

But try-with-resources are different. Resources that use this construct implement the AutoCloseable interface, which consists of a close that returns void. Rewrite the above method as follows:

// try-with-resources - the the best way to close resources!
static String firstLineOfFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(
new FileReader(path))) {
returnbr.readLine(); }}Copy the code
// try-with-resources on multiple resources - short and sweet
static void copy(String src, String dst) throws IOException {
try (InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst)) {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n); }}Copy the code

The conclusion is clear: use a try-with-resources statement instead of a try-finally statement when dealing with resources that must be closed. The generated code is cleaner, cleaner, and the generated exceptions are more useful. Try-with-resources statements are easier and error-free to write code that must close a resource, whereas using try-finally statements is virtually impossible.

10. Follow the general convention when overriding equals

Override Equals timing

If a class contains a concept of logical equality, distinct from object identity, and the parent class has not overridden equals. Another value class that doesn’t need to be overridden by equals is one that uses the singleton pattern. (Enumeration types fall into this category.)

Specifically agreed

  • Reflexivity: for any non-empty reference to x, x.equals(x) must return true.

  • Symmetry: For any non-empty references x and y, x. quals(y) must return true if and only if y.quals (x) returns true.

  • Transitivity: For any non-empty reference x, y, z, x. quals(z) must return true if x.quals (y) returns true and y.quals (z) returns true.

  • Consistency: For any non-empty reference x and y, multiple calls to x.equals(y) must always return true or always return false if the information used in the EQUALS comparison has not been modified.

  • For any non-null reference to x, x.equals(null) must return false.

Next article: Effective.Java