Basic knowledge is prone to mistakes

The difference between object-oriented and procedural

  • Process-oriented: Process-oriented performance is higher than object-oriented performance. Because class invocation requires instantiation, which costs a lot and consumes resources, process-oriented development is generally adopted when performance is the most important factor, such as single-chip microcomputer, embedded development, Linux/Unix, etc. However, process orientation is not as easy to maintain, reuse, and extend as object orientation.
  • Object oriented: Object oriented is easy to maintain, easy to reuse, easy to expand. Because object-oriented has the characteristics of encapsulation, inheritance and polymorphism, it is possible to design a low coupling system, which makes the system more flexible and easier to maintain. However, object-oriented performance is lower than procedural performance.

1. object.equals("str")Easy to report null pointer exceptions, should be used"str".equals(object);

  • You can also use the JDK7 utility class object#equals: objects.equals(null, “STR “); // false

    • Java. Util. Objects# equals the source code:

      Public static Boolean equals(Object a, Object b) {// Avoid null pointer exception. If a==null, then a. quals(b) will not be executed, avoiding null pointer exceptions. return (a == b) || (a ! = null && a.equals(b)); }Copy the code
  • Null pointer exception: Null pointer exception: null pointer exception: null pointer exception: null pointer exception

    • Each primitive type has a default value, such as 0 for int, false for Boolean, and null for any reference type, not strictly for all Object.
    • You can use == or! = operation to compare null values, but no other algorithm or logical operation can be used. In Javanull == nullWill return true.
    • A reference type variable with a value of null cannot be used to call a non-static method, otherwise an exception will be thrown
  • All comparison of object values of Integer wrapper classes (such as Integer) must use equals.

  • == compares values, but primitive datatypes store values, and reference datatypes store object addresses

  • Equals () cannot be used to compare variables of primitive data types. The equals() method exists in the Object class and is implemented by return (this == obj)

  • Special: String equals() is overridden, and the overridden equals method is used in the same way as ==, i.e. String equals compares values instead of addresses

  • The equality of objects compares whether the contents in memory are equal. Reference equality, on the other hand, compares whether the memory addresses they point to are equal.

  • Polymorphism is the same interface, using different instances and perform different operations, such as air conditioning is an interface, different brands of air conditioning implementation landing is different instances to perform different operations like

  • Polymorphism is simply: a reference to a parent class refers to an instance of a child class

2. BigDecimal: Prevents loss of floating-point precision

  • Float a = 1.0f - 0.9f; float a = 1.0f - 0.9f; Float b = 0.9f - 0.8f; float b = 0.9f - 0.9f; System.out.println(a == b); // false: the accuracy is lostCopy the code
  • BigDecimal a = new BigDecimal("1.0"); BigDecimal b = new BigDecimal("0.9"); BigDecimal c = new BigDecimal("0.8"); BigDecimal x = a.subtract(b); // a-b=0.1 BigDecimal y = b.subtract(c); / / b - c = 0.1 System. Out. The println (x.equals (y)); // true System.out.println(a.compareTo(b)); // a>b equals 1Copy the code
  • Reference: Alibaba Java Development Manual

  • BigDecimal is used primarily to operate on (large) floating point numbers, and BigInteger is used primarily to operate on large integers (more than long types)

3. Standards for the use of basic and wrapped data types

  • All POJO class attributes must use wrapper data types.

  • The return values and parameters of RPC methods must use wrapper data types.

  • 【 Recommended 】 All local variables use primitive data types.

4. Set the ArrayList

  • Arrays.aslist () is a generic method where the objects passed in must be Arrays of objects. Its underlying implementation:

    • /** * returns a list of fixed sizes supported by the specified array. This method is used in conjunction with collection.toarray () as a bridge between array-based and collection-based apis. The returned List is serializable and implements the RandomAccess interface. * / 
      public static< T> List< T> asList(T... a) {return newArrayList< > (a); }Copy the code
  • For Arrays. AsList () set using the modified method: add (), remove (), the clear () would throw UnsupportedOperationException

  • List List = new ArrayList<>(array.asList (“a”, “b”, “c”))

  • Collections.reverse(list); S = list.toarray (new String[0]); [0] to save space, only declare the typeCopy the code

    5. Do not remove/add elements in foreach loops

    If you want to remove, you can call the remove method of the iterator instead of the remove method of the collection class. Because if the list from the structure modification at any time after creating an iterator, in any way except through the iterators themselves remove/add method, the iterator will throw a ConcurrentModificationException, this is fail – fast mechanism of single thread state.

    Fail – fast mechanism: multiple threads to fail – fast collection of modified, may throw ConcurrentModificationException, single thread will appear this kind of circumstance, under the above mentioned earlier.

    All collection classes under the java.util package are fail-fast, while all classes under the java.util. Concurrent package are fail-safe.

    Interator<T> iterator=list.iterator(); While (iterator.hasnext ()){... } for(T item:list){list.remove(item)}Copy the code

    6. Generics (introduced in JDK5)

  • Generics provide a compile-time type authorization mechanism that allows programmers to detect illegal types at compile time

  • Type erasure: Java generics are pseudo-generics because all generic information is erased during compilation

  • List<Integer> list = new ArrayList<>(); Class<? extends List> clazz = list.getClass(); Method add = clazz.getDeclaredMethod("add", Object.class); // Return the specified declared method add.invoke(list, "kl") that reflects the class represented by the clazz object; // Add String by reflection. You can add String elementsCopy the code

7. hashCode()

  • HashCode () is used to get a hashCode, also known as a hashCode; It actually returns an int. The purpose of this hash code is to determine the index position of the object in the hash table. HashCode () is defined in the JDK’s Object.java, which means that any class in Java contains a hashCode() function.

    Hash table stores key-value pairs. It can quickly retrieve the corresponding value according to the key. That’s where the hash code comes in! (Can quickly find the desired object)

  • Why have hashCode:

    How does a HashSet check for duplicates? When you add an object to a HashSet, the HashSet evaluates the object’s Hashcode value to determine where the object was added to. It also compares the hashcode value of other objects at that location. If there is no matching Hashcode, A HashSet assumes that the object is not repeated. But if objects with the same Hashcode value are found, the equals() method is called to check whether objects with hashCode equality are really the same. If they are the same, the HashSet will not let the join succeed. If it is different, it will be rehashed to another location. This significantly reduced the number of equals calls, which in turn significantly increased the execution speed.

    HashCode () gets a hashCode, also called a hashCode. It actually returns an int. The purpose of this hash code is to determine the index position of the object in the hash table. HashCode () is useful in hash tables, not in other cases. The purpose of hashCode() in a hash table is to get the hashCode of an object and thereby determine its position in the hash table.

  • HashCode () and equals ()
    1. If two objects are equal, the Hashcode must also be the same
    2. If two objects are equal, calling equals on both objects returns true
    3. Two objects have the same hashCode value, and they are not necessarily equal
    4. Therefore, if equals is overridden, hashCode must be overridden as well
    5. The default behavior of hashCode() is to generate unique values for objects on the heap. If hashCode() is not overridden, the two objects of the class will never be equal anyway (even if they point to the same data)
  • If two objects are equal, hashCode must be the same. Call equals and return true. However, if two objects have the same hashCode, they are not necessarily equal. So if the euqals method is overridden, the hashCode method must be overridden as well.

  • The default behavior of hashCode() is to generate unique values for objects on the heap. If hashCode() is not overridden, the two objects of the class will never be equal anyway (even if they point to the same data)

  • Why do two objects have the same hashcode value and they are not necessarily equal?

    • becausehashCode()The hash algorithm used may just cause multiple objects to return the same hash value. The worse the hash algorithm is, the more likely it is to collide, but this is also due to the nature of the distribution of the data range (collision means that different objects get the samehashCode. So you need equals to determine if two objects are really the same

The modifier

Why is it illegal to call a non-static member in a static method?

Because static methods can be called without an object, other non-static variables cannot be called in a static method, nor can members of a non-static variable be accessed.

How static methods differ from instance methods
  1. You can use the “class name” when calling static methods externally. Method name, or object name. Method name “. Instance methods have only the latter. That is, you can call a static method without creating an object.
  2. When a static method accesses a member of the class, it only allows access to a static member (that is, static member variables and static methods), but not to instance member variables and instance methods. Instance methods do not have this limitation.

Static,final,this,super

encapsulation

Encapsulation refers to hiding an object’s state information (that is, its properties) inside the object, denying external objects direct access to the internal information of the object. However, you can provide methods to manipulate properties that can be accessed by outsiders. It’s like we can’t see the internal parts (attributes) of the air conditioner hanging on the wall, but we can control the air conditioner by remote control. If properties do not want to be accessed by outsiders, we do not need to provide methods to access them. But if a class has no methods to access from the outside world, then that class is meaningless.

inheritance

Inheritance is the technique of using the definition of an existing class as a basis to create a new class. The definition of a new class can add new data or new functions, or use the functions of the parent class, but can not selectively inherit the parent class. Through the use of inheritance, we can quickly create new classes, can improve the reuse of code, program maintainability, save a lot of time to create new classes, improve our development efficiency.

Here are three things to remember about inheritance:

  1. A subclass owns all the attributes and methods of the parent object (including private attributes and methods), but the private attributes and methods of the parent object are not accessible to the subclass.
  2. Subclasses can have their own attributes and methods, that is, they can extend their parent class.
  3. Subclasses can implement the methods of their parent class in their own way.

polymorphism

Polymorphism, as the name suggests, means that an object has more than one state. A reference to a parent class refers to an instance of a child class.

Polymorphic features: (reference x = new object)

  • There is an inheritance (class)/implementation (interface) relationship between object types and reference types;
  • Object types are immutable and reference types are mutable;
  • Methods are polymorphic, but attributes are not.
  • Which class method is invoked by a method that refers to a type variable must be determined during program execution;
  • Polymorphism cannot call methods that exist only in subclasses but not in superclasses;
  • If a subclass overrides a method of its parent class, it actually executes the method overridden by the subclass. If the subclass does not override a method of its parent class, it executes the method of its parent class.

Application: Use Callable to create multiple threads. New Thread(unable to pass Callable. Class); You need to find Runnable, its subinterface, RunnableFuture, its implementation class, FutureTask, which implements the Runnable interface, and its constructor, FutureTask(Callable

Callable). You can use this polymorphic idea to find methods associated with Callable and Runnable.

The equals and = =

== : This is used to determine whether the addresses of two objects are equal. That is, determine whether two objects are the same object (base data type == compares values, reference data type == compares memory addresses).

Equals () : Also checks whether two objects are equal. But it is generally used in two ways:

  • Case 1: The class does not override equals(). Comparing two objects of that class through equals() is equivalent to comparing them through “==”.
  • Case 2: The class overrides equals(). In general, we override the equals() method to compare the contents of two objects; Return true if their contents are equal (that is, the objects are considered equal).

Here’s an example:

public class test1 {
    public static void main(String[] args) {
        String a = new String("ab"); // a is a reference
        String b = new String("ab"); // b is another reference, the object has the same content
        String aa = "ab"; // Put it in the constant pool
        String bb = "ab"; // If there is an object with the same value in the constant pool, look it up from the constant pool
        if (aa == bb) // true
            System.out.println("aa==bb");
        if (a == b) // false, different object
            System.out.println("a==b");
        if (a.equals(b)) // true
            System.out.println("aEQb");
        if (42= =42.0) { // true
            System.out.println("true"); }}}Copy the code

Description:

  • The equals method on String is overridden, because the equals method on object compares the memory addresses of objects, while the equals method on String compares the values of objects.
  • When creating an object of type String, the virtual machine looks in the constant pool for an existing object with the same value as the object to be created, and assigns it to the current reference if it does. If not, create a new String in the constant pool

The Object class is the parent of all classes.

public final nativeClass<? > getClass()// The native method, which returns the Class object of the current runtime object, is modified with the final keyword, so subclasses are not allowed to override.

public native int hashCode(a) // Native method, used to return hash codes for objects, mainly used in hash tables, such as the JDK HashMap.
public boolean equals(Object obj)// This method is used to compare the memory addresses of two objects. The String class overrides this method.

protected native Object clone(a) throws CloneNotSupportedException//naitive method that creates and returns a copy of the current object. In general, for any object x, the expression x.lone ()! = x is true, x.lone ().getClass() == x.gottclass () is true. Object does not implement the Cloneable interface, so don't rewrite the clone method and call CloneNotSupportedException abnormal happens.

public String toString(a)// Return the hexadecimal string of the class name @ instance's hash code. It is recommended that all subclasses of Object override this method.

public final native void notify(a)// Native method, and cannot be overridden. Wakes up a thread waiting on the monitor of this object (the monitor is equivalent to a lock). If there are multiple threads waiting, only one will wake up randomly.

public final native void notifyAll(a)// Native method, and cannot be overridden. As with Notify, the only difference is that all threads waiting on this object's monitor are woken up instead of one thread.

public final native void wait(long timeout) throws InterruptedException// Native method, and cannot be overridden. Suspends the execution of the thread. Note that the sleep method does not release the lock, while the wait method does. Timeout is the wait time.

public final void wait(long timeout, int nanos) throws InterruptedException// Add the nanos parameter, which represents the extra time (in nanoseconds ranging from 0 to 999999). So you have to add nanos milliseconds to the timeout.

public final void wait(a) throws InterruptedException// This is the same as the previous two wait methods, except that this method keeps waiting without the concept of timeout

protected void finalize(a) throws Throwable {}// The action triggered when the instance is collected by the garbage collector
Copy the code

Constant pool

  • Most of the basic types of Java wrapper class implements the constant pool technology, namely, Byte, Short, Integer, Long, Character, and Boolean;

  • Character creates cache data in the range [0,127]. Boolean returns True Or False. New objects are still created if they are out of range

  • The wrapper class Float,Double, for two floating-point types, does not implement constant pooling technology

  • The Integer I = 40; Java directly encapsulates code as Integer I = integer.valueof (40); To use objects in the constant pool. Integer I =new Integer(40) creates an object

What is the difference between interfaces and abstract classes?

  1. Methods on interfaces are public by default, all methods cannot have implementations in interfaces (Java 8 begins with interface methods having default implementations), and abstract classes can have non-abstract methods.
  2. An interface cannot have any variable other than static or final, whereas an abstract class may not.
  3. A class can implement multiple interfaces, but only one abstract class. The interface itself can extend multiple interfaces through the extends keyword.
  4. The default modifier for interface methods is public, and abstract methods can have public, protected, and default modifiers. (Abstract methods cannot use the private keyword because they are intended to be overridden!) .
  5. From the design level, abstraction is the abstraction of class, is a kind of template design, and interface is the abstraction of behavior, is a kind of behavior specification.

Remark:

  1. In JDK8, interfaces can also define static methods that can be called directly with the interface name. Implementation classes and implementations are not callable. If two interfaces define the same default method, they must be overridden, or an error will be reported. (see the issue:github.com/Snailclimb/…
  2. The JDK9 interface is allowed to define private methods.

Java interface concepts in jdk7~ JDk9

  1. In JDK 7 and earlier, interfaces were limited to constant variables and abstract methods. These interface methods must be implemented by the class that chooses to implement the interface.
  2. Interfaces in JDK8 can have default methods and static method functionality.
  3. Jdk 9 introduced private methods and private static methods in the interface.

What is the difference between String StringBuffer and StringBuilder?

AbstractStringBuilder and StringBuffer both inherit from the AbstractStringBuilder class, AbstractStringBuilder also uses character arrays to hold the string char[]value without the final keyword, so both objects are mutable.

Both StringBuilder and StringBuffer constructors are implemented by calling the superclass constructor, AbstractStringBuilder

	AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }
Copy the code

Thread safety

Objects in strings are immutable, which means they are considered constants, thread-safe. AbstractStringBuilder AbstractStringBuilder is a common parent of StringBuilder and StringBuffer. AbstractStringBuilder defines some basic string operations, such as expandCapacity, Append, insert, indexOf and other public methods. A StringBuffer locks synchronized or synchronized methods and is thread-safe. StringBuilder does not lock methods synchronously-so it is not thread-safe.

performance

Each time a String type is changed, a new String is generated and a pointer is pointed to the new String. A StringBuffer operates on the StringBuffer object itself each time, rather than generating new objects and changing object references. Using StringBuilder in the same situation yields only 10% to 15% performance improvement over using StringBuffer, but at the risk of multithreading insecurity.

Summary of the use of the three:

  1. Manipulation of small amounts of data: applicableString
  2. Single thread manipulation of large amounts of data in string buffers: applicableStringBuilder
  3. Multithreaded manipulation of large amounts of data in string buffers: applicableStringBuffer

essays

  • If a Java program does not call a superclass-specific constructor without super() before executing a subclass constructor, it will call the no-argument constructor in the parent class. If the parent class does not have a no-argument constructor, the compiler will fail

  • The ‘String’ class uses the final keyword to modify character arrays to hold strings. Private final char Value [], so strings are immutable. After Java 9, the String class was implemented to store strings in byte arrays instead

  • Shallow copy: passes values to the base data type and passes reference-like copies to the reference data type. This is a shallow copy.

  • Deep copy: Passes values to the base data type, creates a new object for the reference data type, and copies its contents

  • What is the difference between the equality of objects and the equality of references to them?

    The equality of objects compares whether the contents in memory are equal. Reference equality, on the other hand, compares whether the memory addresses they point to are equal.

  • The subclass constructor is called before the subclass constructor is called. Help subclasses do initialization work.
  • What does a class constructor do? If a class does not declare a constructor, does the program execute correctly? Why is that?

    The main function is to complete the initialization of the class object. Yes. Because a class will have a default constructor that takes no arguments even if it does not declare a constructor. If we add class constructors ourselves (with or without arguments), Java doesn’t add default parameterless constructors, and we can’t just new an object without passing arguments, so we’ve been unwittingly using constructors. This is why we create objects with parentheses (because we call the constructor without arguments). If we override a constructor with arguments, remember to include the non-argument constructor as well (whether or not it is used), as this will help us create objects with fewer bugs.

  • What are the properties of constructors?
    1. Name is the same as the class name.
    2. There is no return value, but a constructor cannot be declared with void.
    3. Automatically executed when an object of the class is generated, no call required.
  • If some fields in Java serialization do not want to be serialized: use the TRANSIENT keyword.
    The transient keyword prevents serialization of variables in an instance that are modified with this keyword. When an object is deserialized, variable values modified transient are not persisted and restored. Transient can only modify variables, not classes and methods.
    Serialization provides a great mechanism for storing the state of an object. In plain English, serialization is storing the state of an object on hard disk so that it can be read and used when needed. Some transient fields, such as the bank card number, are not expected to be transferred over the network. The transient function is to store the life cycle of this field in the caller’s memory and not write to disk for persistence.
  • There are two common keyboard input methods:

    Scanner input = new Scanner(System.in);
    String s  = input.nextLine();
    input.close();
    Copy the code
   BufferedReader input = new BufferedReader(new InputStreamReader(System.in));		
   String s = input.readLine();
Copy the code

Common methods of the Collections and Arrays utility classes

Collections

  • Sorting:

     void reverse(List list)/ / reverse
      void shuffle(List list)// sort randomly
      void sort(List list)// Sort by ascending order of nature
      void sort(List list, Comparator c)// Customize the sorting logic by using the Comparator
      void swap(List list, int i , int j)// Swap elements at two index positions
      void rotate(List list, int distance)/ / rotate. When distance is positive, move all the distance elements behind the list to the front. When distance is negative, the first distance elements of the list are moved to the back as a whole.
    Copy the code
  • Find and replace

    • Int binarySearch(List List, Object key)// The List must be ordered int Max (Collection coll)// According to the natural order of elements, return the largest element. Int min(Collection coll) int Max (Collection coll, Comparator c) Analogies int min(Collection coll, Comparator c) void fill(List List, Object obj)// replace all elements in the specified List with specified elements. Int frequency(Collection C, Object O) int indexOfSubList(List List, target) If it can't find it, it returns -1, Int lastIndexOfSubList(List source, List target). Boolean replaceAll(List List, Object oldVal, Object newVal), Replace old elements with new onesCopy the code
  • Synchronization control

    • HashSet, TreeSet, ArrayList, and LinkedList, HashMap, TreeMap is thread safe, thread-safe implementation class vector, stack, hashtable

    • The List and Set implementation classes in the JUC collection package include CopyOnWriteArrayList, CopyOnWriteArraySet, and ConcurrentSkipListSet. Achieve thread safety, support high concurrency

      • 1. CopyOnWriteArrayList is equivalent to a thread-safe ArrayList that implements the List interface. CopyOnWriteArrayList supports high concurrency.

        2. CopyOnWriteArraySet is equivalent to a thread-safe HashSet, which extends from AbstractSet. CopyOnWriteArraySet contains a CopyOnWriteArrayList object (aggregate relation), which is implemented through CopyOnWriteArrayList.

    • The Map implementation classes in the JUC package include ConcurrentHashMap and ConcurrentSkipListMap.

      • ConcurrentHashMap is a thread-safe hash table (equivalent to thread-safe HashMap); It inherits from the AbstractMap class and implements the ConcurrentMap interface. ConcurrentHashMap is implemented through “lock segmentation”, which supports concurrency.

        -ConcurrentSkipListMap is a thread-safe ordered hash table (equivalent to thread-safe TreeMap); It extends from the AbstractMap class and implements the ConcurrentNavigableMap interface. ConcurrentSkipListMap is implemented through a “hop table” that supports concurrency.

        Concurrentskiplistsets are thread-safe ordered collections (equivalent to thread-safe TreeSet); It inherits from AbstractSet and implements the NavigableSet interface. ConcurrentSkipListSet is implemented via ConcurrentSkipListMap, which also supports concurrency.

    • The Queue implementation classes in the JUC collection package include: ArrayBlockingQueue, LinkedBlockingQueue, LinkedBlockingDeque, ConcurrentLinkedQueue and ConcurrentLinkedDeque

      • ArrayBlockingQueue is a thread-safe bounded blocking queue for array implementations.

        (02) LinkedBlockingQueue is a (specified size) blocking queue implemented by a one-way linked list that sorts elements in FIFO (first in, first out).

        LinkedBlockingDeque is a two-way (size specified) concurrent blocking queue implemented by a two-way linked list. This blocking queue supports both FIFO and FILO operations.

        ConcurrentLinkedQueue ConcurrentLinkedQueue ConcurrentLinkedQueue ConcurrentLinkedQueue ConcurrentLinkedQueue ConcurrentLinkedQueue ConcurrentLinkedQueue ConcurrentLinkedQueue ConcurrentLinkedQueue ConcurrentLinkedQueue ConcurrentLinkedQueue ConcurrentLinkedQueue ConcurrentLinkedQueue ConcurrentLinkedQueue

        ConcurrentLinkedDeque is an unbounded queue implemented by bidirectional lists, which supports BOTH FIFO and FILO operations.

  • Arrays:

    • Sorting:sort()And look for:binarySearch()And comparison:equals(), filling:fill(), transfer list:asList(), to string:toString(), copy:copyOf()

abnormal

In Java, all exceptions have a common ancestor to the Throwable class in the java.lang package. Throwable: There are two important subclasses: Exception and Error, both of which are important Java Exception handling subclasses, each containing a large number of subclasses.

Error: An Error that the program cannot handle, indicating a serious problem in running the application. Most errors have nothing to do with what the code writer is doing, and instead represent problems with the JVM (Java Virtual Machine) while the code is running. For example, a Java Virtual Machine run error, an OutOfMemoryError occurs when the JVM no longer has the memory resources it needs to continue with the operation. When these exceptions occur, the Java Virtual Machine (JVM) typically selects thread termination.

These errors indicate that the fault occurs on the VM itself or when the VM tries to execute an application, such as a Java Virtual Machine running error or a NoClassDefFoundError. These errors are not detectable because they are outside the control and processing capabilities of the application, and most of them are not allowed to occur while the program is running. Even if an error does occur, a properly designed application should not, by nature, attempt to handle the exception it raises. In Java, errors are described by subclasses of Error.

Exception: An Exception that can be handled by the program itself. The Exception class has an important subclass, RuntimeException. RuntimeException is thrown by the Java VIRTUAL machine. NullPointerException (thrown when the variable to be accessed does not reference any object), ArithmeticException (dividing an integer by 0, Put the exception) and ArrayIndexOutOfBoundsException (subscript cross-border exception).

Note: The difference between exceptions and errors: exceptions can be handled by the program itself, while errors cannot be handled.

3.2.2. Common methods of Throwable class

  • Public String getMessage(): Returns a brief description of when an exception occurs
  • Public string toString(): Returns details about when an exception occurs
  • public string getLocalizedMessage(): Returns localization information for the exception object. useThrowableSubclasses override this method to generate localized information. If the subclass does not override the method, the information returned by the method isGetMessage ()The same result is returned
  • public void printStackTrace(): Print on the consoleThrowableObject encapsulates exception information

usetry-with-resourcesTo take the place oftry-catch-finally

  • Try block: Used to catch exceptions. This may be followed by zero or more catch blocks, or if there is no catch block, a finally block must follow.
  • Catch block: Used to handle exceptions caught by a try.
  • Finally block: Statements ina finally block are executed whether or not exceptions are caught or handled. When a return statement is encountered ina try or catch block, the finally block is executed before the method returns.

A finally block is not executed in four special cases:

  1. An exception occurred on the first line of the finally block. Because on other lines, the finally block will still be executed
  2. System.exit(int) was used in the previous code to exit the program. Exit is a parameter function; If the statement follows an exception statement, finally is executed
  3. The thread on which the program resides dies.
  4. Close the CPU.

Note: When both try and finally statements have return statements, the contents of the finally statement will be executed before the method returns, and the return value of the finally statement will override the original return value. As follows:

public class Test { public static int f(int value) { try { return value * value; } finally { if (value == 2) { return 0; }}}}Copy the code

If f(2) is called, the return value will be 0, because the return value of the finally statement overrides the return value of the try block.

  1. Scope of application (definition of resources) :Any implementationjava.lang.AutoCloseableOr the java.io.Closeable object
  2. Close the execution order of resources and final:try-with-resourcesStatement in which any catch or finally block is run after the declared resource is closed

The Effecitve Java makes it clear:

With resources that must be closed, try-with-resources should always be used in preference to try-finally. The resulting code is shorter, cleaner, and produces exceptions that are more useful to us. The try-with-resources statement makes it much easier to write code for resources that must be closed than would be possible with a try-finally.

Java resources such as InputStream, OutputStream, Scanner, PrintWriter, etc., all need to be closed manually by calling close(). This is usually done by try-catch-finally statements. As follows:

// Read the contents of a text file Scanner Scanner = null; try { scanner = new Scanner(new File("D://read.txt")); while (scanner.hasNext()) { System.out.println(scanner.nextLine()); } } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (scanner ! = null) { scanner.close(); }}Copy the code

Modify the above code with the try-with-resources statement after Java 7:

try (Scanner scanner = new Scanner(new File("test.txt"))) {
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException fnfe) {
    fnfe.printStackTrace();
}
Copy the code

Of course, using try-with-resources is also very easy when multiple resources need to be closed, but if you still use try-catch-finally, it can cause a lot of problems.

Multiple resources can be declared in a try-with-resources block by using semicolons.

try (BufferedInputStream bin = new BufferedInputStream(new FileInputStream(new File("test.txt"))); BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(new File("out.txt")))) { int b; while ((b = bin.read()) ! = -1) { bout.write(b); } } catch (IOException e) { e.printStackTrace(); }Copy the code

multithreading

A thread is similar to a process, but a thread is a smaller unit of execution than a process. A process can produce multiple threads during its execution. Unlike a process, many threads of the same kind share the same memory space and a group of system resources, so the system is much less burden than a process when producing a thread or switching between threads. It is also because of this, threads are also called lightweight processes.

A program is a file containing instructions and data that is stored on a disk or other data storage device, that is, a program is static code.

Process is a process of program execution, is the basic unit of the system running program, so the process is dynamic. When a system runs a program, it is a process from creation, to execution, to extinction. To put it simply, a process is a program in execution, which executes instruction after instruction in the computer. At the same time, each process also occupies certain system resources such as CPU time, memory space, files, access to input and output devices, and so on. In other words, when a program is executed, it is loaded into memory by the operating system. Threads are smaller running units that processes are divided into. The main difference between threads and processes is that processes are essentially independent, whereas threads are not necessarily, as threads in the same process will most likely interact with each other. On the other hand, a process belongs to the category of operating system, mainly in the same period of time, can execute more than one program, while a thread is in the same program almost simultaneously execute more than one program segment.

  • Threads have six states:

  • After the thread is created, it will be inNEW (NEW)State, callstart()Method starts running, and the thread is inREADY to runState. A runnable thread is in a state when it has acquired a CPU timesliceRUNNINGState.
  • The operating system hides the READY and RUNNING states in the Java Virtual Machine (JVM). It sees only RUNNABLE states, so Java systems generally refer to these two states collectively as RUNNABLE states.
  • When the thread executeswait()Method, the thread enters the **WAITING ** state. Threads that enter the wait state need to be notified by other threads to return to the run state, whileTIME_WAITING(timeout waiting)State is equivalent to adding timeout limits to wait states, such as passSleep (Long Millis)Method orWait (long millis)Method to place a Java thread in a TIMED WAITING state. When the timeout expires, the Java thread will return to the RUNNABLE state. When a thread calls a synchronous method, the thread will enter without acquiring the lockBLOCKED.State. Thread executing Runnablerun()Method will then enter theTERMINATEDState.

File IO

  • The Java I0 stream’s more than 40 classes are derived from the following four abstract base classes:
    • InputStream/Reader: The base class for all input streams, which are byte input streams and character input streams.
    • OutputStream/Writer: Base class for all output streams, byte output streams and character output streams.
  • According to the flow direction, it can be divided into input flow and output flow.
  • According to operation unit, it can be divided into byte stream and character stream.
  • Flows are divided into node flows and processing flows according to their roles.
  • Classification by operation mode

  • Classification by operation object

– Why have a character stream when you have a byte stream?

Whether a file is read or written, or a network is sent or received, the smallest storage unit of information is a byte. Why are I/O stream operations divided into byte stream operations and character stream operations?

  • A: Character streams are generated by the Java virtual machine converting bytes. The problem is that this process can be very time-consuming, and if we don’t know the encoding type, we can easily have garbled characters. Therefore, the I/O stream simply provides a direct interface to manipulate characters, which is convenient for us to stream characters.

  • BIO (Blocking I/O): Synchronous Blocking in I/O mode, data reads and writes must be blocked in a thread waiting for it to complete. In the case that the number of active connections is not particularly high (less than 1000 for a single machine), this model is relatively good, allowing each connection to focus on its OWN I/O and simple programming model, without too much consideration of system overload, current limiting and other problems. The thread pool itself is a natural funnel to buffer connections or requests that the system can’t handle. However, when faced with hundreds of thousands or even millions of connections, the traditional BIO model is powerless. Therefore, we need a more efficient I/O processing model to handle the higher concurrency.
  • NIO (Non-blocking/New I/O):NIO is a synchronous non-blocking I/O model. The NIO framework was introduced in Java 1.4, corresponding to the Java.niO package, which provides abstractions such as channels, selectors, and buffers. N in NIO can be interpreted as non-blocking, not just New.It supports buffer-oriented, channel-based approaches to I/O operations. NIO provides a comparison with the traditional BIO modelSocketServerSocketThe correspondingSocketChannelServerSocketChannel Two different socket channel implementationsBoth channels support blocking and non-blocking modes. Blocking mode, like traditional support, is relatively simple, but has poor performance and reliability. Non-blocking mode is the opposite. For low-load, low-concurrency applications, synchronous blocking I/O can be used for faster development and better maintenance; For high-load, high-concurrency (network) applications, NIO’s non-blocking mode should be used for development
  • AIO (Asynchronous I/O): AIO is NIO 2. NIO 2, an improved version of NIO introduced in Java 7, is an asynchronous, non-blocking IO model. Asynchronous IO is implemented based on events and callbacks. This means that the application operation is returned directly, not blocked, and when the background processing is complete, the operating system notifies the corresponding thread to proceed with the subsequent operation. AIO is short for asynchronous IO. Although NIO provides a non-blocking method for network operations, NIO’s I/O behavior is synchronous. For NIO, our business thread is notified when the IO operation is ready, and then the thread performs the IO operation itself, which is synchronous. Looking around the Internet, I found that AIO is not widely used so far, and Netty tried and abandoned AIO before.

reflection

Introduction to reflection Mechanism

The JAVA reflection mechanism allows you to know all the properties and methods of any class in the running state. For any object, you can call any of its methods and properties; This ability to dynamically retrieve information and invoke methods on objects is called the Reflection mechanism of the Java language.

Two ways to get a Class object

If we get this information dynamically, we need to rely on Class objects. Class objects tell the running program information about a Class’s methods, variables, and so on. Java provides three ways to get Class objects:

1. If you know the specific class, you can use:

Class alunbarClass = TargetObject.class;
Copy the code

However, we usually do not know the specific Class, and we usually get the Class object by iterating through the Class under the package

2. Get from the path passed to class.forname () :

Class alunbarClass1 = Class.forName("cn.javaguide.TargetObject");
Copy the code

3. Obtain from object instance instance.getClass() :

Employee e;
Class alunbarClass2 = e.getClass();
Copy the code

The code examples

Simple code to demonstrate the reflection of some operations!

1. Create a class TargetObject that we want to use reflection:

package cn.javaguide;

public class TargetObject {
    private String value;

    public TargetObject(a) {
        value = "JavaGuide";
    }

    public void publicMethod(String s) {
        System.out.println("I love " + s);
    }

    private void privateMethod(a) {
        System.out.println("value is "+ value); }}Copy the code

2. Use reflection to manipulate the class’s methods and arguments

public class Main {
    public static void main(String[] args) throws Exception {
        /** * get the Class object of TargetObject and create an instance of TargetObject */Class<? > tagetClass = Class.forName("cn.javaguide.TargetObject");
        TargetObject targetObject = (TargetObject) tagetClass.newInstance();
        /** * get all methods defined in all classes */
        Method[] methods = tagetClass.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName()); // Iterate over the print method name
        }
        /** * gets the specified method and calls */
        Method publicMethod = tagetClass.getDeclaredMethod("publicMethod",
                String.class); // Get the specified method

        publicMethod.invoke(targetObject, "JavaGuide"); // Executes the method of the class instance object with the argument JavaGuide
        /** * gets the specified parameters and modifies them */
        Field field = tagetClass.getDeclaredField("value");
        // In order to modify the parameters in the class we cancel the security check
        field.setAccessible(true);
        field.set(targetObject, "JavaGuide"); // Assign a value to the member variable of the class instance object
        /** * call the private method */
        Method privateMethod = tagetClass.getDeclaredMethod("privateMethod"); // Get the method by its name
        // To call the private method we cancel the security check
        privateMethod.setAccessible(true);
        privateMethod.invoke(targetObject); // Call the specified method privateMethod and print value is JavaGuide}}Copy the code

Output content:

publicMethod
privateMethod
I love JavaGuide
value is JavaGuide
Copy the code

Static and dynamic compilation

  • Static compilation: Determine the type and bind the object at compile time
  • Dynamic compilation: Determine the type and bind the object at run time

Pros and cons of reflection

  • Advantages: Runtime type judgment, dynamic loading classes, improve code flexibility.
  • Disadvantages: 1. Performance bottleneck: Reflection is equivalent to a series of interpreted operations telling the JVM what to do, and performance is much slower than direct Java code. 2, security issues, so that we can dynamically change the attributes of the class but also increase the security risks of the class.

Reflection property

Reflection is a series of interpreted operations that go into the meta-space to see if its target class has been loaded. If not, a classloading process is required to tell the JVM what to do, and performance is much slower than direct Java code.

Reflection application scenarios

Reflection is the soul of frame design.

In our daily project development process, reflection mechanism is rarely used directly, but this does not mean that reflection mechanism is useless, in fact, there are a lot of design and development related to reflection mechanism, such as modular development, through reflection to call the corresponding bytecode; Reflection is also used in dynamic proxy design patterns, as well as in frameworks like Spring/Hibernate that we use every day.

For example:

  1. We use class.forname () to load the database driver by reflection when connecting to the database using JDBC;

  2. The Spring framework’s IOC (Dynamically loaded Management Beans) object creation and AOP (dynamic proxies) capabilities are related to reflection;

  3. Dynamically configure instance properties;

  4. decompiling

  5. Dynamically obtaining some state at run time can achieve the function of code reuse

The agent

Static agent

In static proxies, our enhancements to each method of the target object are done manually (the code will be shown later), very inflexible (for example, when the interface adds new methods, both the target object and the proxy object need to be modified) and cumbersome (you need to write a separate proxy class for each target class). There are very, very few practical application scenarios, and the use of static proxies is rarely seen in daily development.

From the implementation and application perspective, static proxies turn interfaces, implementation classes, and proxy classes into actual class files at compile time.

Static proxy implementation steps:

  1. Define an interface and its implementation class;
  2. Creating a proxy class also implements this interface
  3. The target object injection is injected into the proxy class, and the corresponding method in the target class is called in the corresponding method of the proxy class. This way, we can mask access to the target object through the proxy class and do whatever we want before and after the target method executes.

The following code shows!

1. Define the interface for sending SMS messages

public interface SmsService {
    String send(String message);
}
Copy the code

2. Implement the INTERFACE for sending SMS messages

public class SmsServiceImpl implements SmsService { public String send(String message) { System.out.println("send message:" + message); return message; }}Copy the code

3. Create a proxy class and implement the interface for sending SMS messages

public class SmsProxy implements SmsService {

    private final SmsService smsService;

    public SmsProxy(SmsService smsService) {
        this.smsService = smsService;
    }

    @Override
    public String send(String message) {
        Before calling the method, we can add our own operations
        System.out.println("before method send()");
        smsService.send(message);
        // After calling the method, we can also add our own operations
        System.out.println("after method send()");
        return null; }}Copy the code

4. Actual use

public class Main {
    public static void main(String[] args) {
        SmsService smsService = new SmsServiceImpl();
        SmsProxy smsProxy = new SmsProxy(smsService); // Create a proxy object
        smsProxy.send("java"); }}Copy the code

After running the above code, the console prints:

before method send()
send message:java
after method send()
Copy the code

As you can see from the output, we have added the send() method to SmsServiceImpl.

Dynamic proxy

Dynamic proxies are more flexible than static proxies. Instead of creating a separate proxy class for each target class, and instead of having to implement the interface, we can directly proxy the implementation class (CGLIB dynamic proxy mechanism).

From the JVM’s perspective, dynamic proxies dynamically generate bytecode classes at run time and load them into the JVM.

When it comes to dynamic proxies, Spring AOP and THE RPC framework are two of the most obvious, both of whose implementations rely on dynamic proxies.

Dynamic proxies are a relatively small part of our daily development, but are almost mandatory in frameworks. Learning dynamic proxies is also very helpful in understanding and learning the principles of various frameworks.

For Java, there are many ways to implement dynamic proxy, such as JDK dynamic proxy, CGLIB dynamic proxy and so on.

Guide-rpc-framework uses JDK dynamic proxy. Let’s take a look at the use of JDK dynamic proxy.

In addition, although guide-Rpc-Framework does not use CGLIB dynamic proxies, here is a brief overview of its use and its comparison with JDK dynamic proxies.

3.1. JDK dynamic proxy mechanism

Introduce 3.1.1.

In the Java dynamic proxy mechanismInvocationHandlerThe interface andProxyClasses are the core.

The most frequently used method in the Proxy class is newProxyInstance(), which is used to generate a Proxy object.

public static Object newProxyInstance(ClassLoader loader, Class<? >[] interfaces, InvocationHandler h) throws IllegalArgumentException {...... }Copy the code

This method takes three parameters:

  1. Loader: class loader used to load proxy objects.
  2. Interfaces: interfaces implemented by proxy classes;
  3. h: to achieve theInvocationHandlerInterface object;

To implement dynamic proxies, you must also implement InvocationHandler to customize the processing logic. When our dynamic proxy object calls a method, the call to that method is forwarded to the Invoke method that implements the InvocationHandler interface class.

public interface InvocationHandler {
    /** * this method is actually called when you call a method using a proxy object */
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}
Copy the code

The invoke() method takes the following three arguments:

  1. Proxy: dynamically generated proxy class
  2. Method: Corresponds to the method called by the proxy class object
  3. Args: parameter of the current method

That is: the Proxy object you create with the newProxyInstance() of the Proxy class actually calls the invoke() method of the class that implements the InvocationHandler interface when calling a method. You can customize the processing logic in the invoke() method, such as what to do before and after the method is executed.

3.1.2. JDK dynamic proxy class usage steps

  1. Define an interface and its implementation class;
  2. The customInvocationHandlerPay equal attention to writinginvokeMethods,invokeMethod we call native methods (methods of the propped class) and customize some processing logic;
  3. throughProxy.newProxyInstance(ClassLoader loader,Class<? >[] interfaces,InvocationHandler h)Method to create a proxy object;

3.1.3. Code examples

This may sound a little hollow and hard to understand, but I gave you an example.

1. Define the interface for sending SMS messages

public interface SmsService {
    String send(String message);
}
Copy the code

2. Implement the INTERFACE for sending SMS messages

public class SmsServiceImpl implements SmsService { public String send(String message) { System.out.println("send message:" + message); return message; }}Copy the code

3. Define a JDK dynamic proxy class and methods to enhance proxied objects

/ * * *@author shuang.kou
 * @createTime 2020年05月11日 11:23:00
 */
public class DebugInvocationHandler implements InvocationHandler {
    /** * The real object in the proxy class */
    private final Object target;

    public DebugInvocationHandler(Object target) {
        this.target = target;
    }

   
    public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException 	  {
        Before calling the method, we can add our own operations
        System.out.println("before method " + method.getName());
        Object result = method.invoke(target, args);// Finally the invoke method calls the proxied object's native method
        // After calling the method, we can also add our own operations
        System.out.println("after method " + method.getName());
        returnresult; }}Copy the code

Invoke () method: When our dynamic proxy object calls a native method, we actually end up calling the invoke() method, which then calls the proxied object’s native method instead of us.

4. Obtain the factory class of the proxy object

public class JdkProxyFactory {
    public static Object getProxy(Object target) {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(), // Class loading of the target class
                target.getClass().getInterfaces(),  // Specify more than one interface that the proxy needs to implement
                new DebugInvocationHandler(target)   // A custom enhancement method corresponding to the proxy object); }}Copy the code

GetProxy () : Gets the Proxy object of a class, mainly through proxy.newProxyInstance ()

5. Actual use

SmsService smsService = (SmsService) JdkProxyFactory.getProxy(new SmsServiceImpl()); // Enhanced dynamic proxy object smsservice.send (" Java "); // Invoke implements the invoke method of the InvocationHandler classCopy the code

After running the above code, the console prints:

before method send
send message:java
after method send
Copy the code

3.2. CGLIB dynamic proxy mechanism

Introduce 3.2.1.

One of the most deadly problems with JDK dynamic proxies is that they can only proxy classes that implement the interface.

To solve this problem, we can use CGLIB dynamic proxy mechanism to avoid.

CGLIB(Code Generation Library) is an ASM-based bytecode Generation Library that allows you to modify and generate bytecode dynamically at run time. CGLIB implements the proxy through inheritance. Many well-known open source frameworks use CGLIB, such as AOP modules in Spring: JDK dynamic proxies are used by default if the target object implements an interface, CGLIB dynamic proxies are used otherwise.

In CGLIB dynamic proxy mechanismMethodInterceptorThe interface andEnhancerClasses are the core.

You’ll need to customize the MethodInterceptor and override the Intercept method, which intercepts methods that enhance the propped class.

public interface MethodInterceptor
extends Callback{
    // Intercepts methods in proxied classes
    public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable;
}
Copy the code
  1. Obj: Proxied objects (objects that need enhancement)
  2. Method: methods that are being intercepted (methods that need enhancement)
  3. Args: method entry parameter
  4. MethodProxy: Used to call the original method

You can use the Enhancer class to dynamically fetch the promenade class. When the proxy class calls a method, it actually calls the Intercept method in MethodInterceptor.

3.2.2. Steps for using the CGLIB dynamic proxy class

  1. Define a class;
  2. The customMethodInterceptorPay equal attention to writinginterceptMethod,interceptMethods used to intercept enhanced propped classes, and in JDK dynamic proxiesinvokeMethods are similar;
  3. throughEnhancerOf the classcreate()Create a proxy class;

3.2.3. Code examples

Unlike the JDK, dynamic proxies do not require additional dependencies. CGLIB(Code Generation Library) is actually an open source project and you need to manually add dependencies if you want to use it.

1. Implement a class that uses Ali Cloud to send SMS messages

package github.javaguide.dynamicProxy.cglibDynamicProxy;

public class AliSmsService {
    public String send(String message) {
        System.out.println("send message:" + message);
        returnmessage; }}Copy the code

2. CustomMethodInterceptor(method interceptor), equivalent to the DebugInvocationHandler class of the JDK dynamic proxy above

/** * Custom MethodInterceptor */
public class DebugMethodInterceptor implements MethodInterceptor {
    /** * is equivalent to the INVOKE method of the JDK dynamic proxy@paramO Proxied objects (objects to be enhanced) *@paramMethod Method that is intercepted (method that needs enhancement) *@paramArgs method entry parameter *@paramMethodProxy is used to call the original method */
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Before calling the method, we can add our own operations
        System.out.println("before method " + method.getName());
        Object object = methodProxy.invokeSuper(o, args);
        // After calling the method, we can also add our own operations
        System.out.println("after method " + method.getName());
        returnobject; }}Copy the code

3. Obtain the proxy class, which is equivalent to the newProxyInstance step of JDK dynamic proxy

import net.sf.cglib.proxy.Enhancer;

public class CglibProxyFactory {

    public static Object getProxy(Class
        clazz) {
        // Create dynamic proxy enhancement classes
        Enhancer enhancer = new Enhancer();
        // Set the class loader
        enhancer.setClassLoader(clazz.getClassLoader());
        // Set the proxied class
        enhancer.setSuperclass(clazz);
        // Set method interceptor
        enhancer.setCallback(new DebugMethodInterceptor());
        // Create the proxy class
        returnenhancer.create(); }}Copy the code

4. Actual use

AliSmsService aliSmsService = (AliSmsService) CglibProxyFactory.getProxy(AliSmsService.class);
aliSmsService.send("java");
Copy the code

After running the above code, the console prints:

before method send
send message:java
after method send
Copy the code

3.3. JDK dynamic proxy and CGLIB dynamic proxy comparison

  1. JDK dynamic proxies can only proxy classes that implement interfaces, whereas CGLIB can proxy classes that don’t implement any interfaces. In addition, CGLIB dynamic proxies intercept method calls of proxied classes by generating a subclass of the proxied class, so classes and methods declared as final cannot be proxied.
  2. In most cases, the JDK dynamic proxy is superior in terms of both efficiency, and this advantage becomes more apparent as JDK versions are upgraded.

4. Comparison between static proxy and dynamic proxy

  1. Flexibility: Dynamic proxies are more flexible in that they don’t have to implement interfaces, they can implement classes directly, and they don’t need to create a proxy class for each target class. In addition, in static proxies, once the interface adds new methods, both the target object and the proxy object have to be modified, which is very troublesome!
  2. JVM level: Static agents convert interfaces, implementation classes, and proxy classes into actual class files at compile time. Dynamic proxies, on the other hand, generate bytecodes dynamically at run time and load them into the JVM.

Class objects are stored in the meta-space (method area), and instance objects are stored in the heap

Java four kinds of references

StrongReference

Strong references are the most commonly used references. If an object has a strong reference, the garbage collector will never collect it.

Object o=new Object(); / / strong referenceCopy the code

When running out of memory, the Java virtual machine would rather throw outofMemoryErrors to abort the program than randomly recycle objects with strong references to resolve the memory problem. When not used, references are weakened by explicitly setting O to null, or by going beyond the life of the object, then gc considers that the object does not have a reference and can reclaim the object. Exactly when to collect depends on the GC algorithm.

Inside a method there is a strong reference, which is stored in the stack, and the actual reference content (Object) is stored in the heap. When the method is finished, it exits the stack, the reference to the content does not exist, and the Object is reclaimed.

However, if the variable is global, it needs to be null when the object is not used, because strong references are not garbage collected.

  • Application of strong references in ArrayList

    A private array of variables elementData is defined in the ArrayList class, and when the method is called to empty the array, you can see the assignment of null to the contents of each array. Unlike elementData=null, strong references still exist, avoiding reallocation of memory in subsequent calls to methods such as add() to add elements. Using methods such as clear() to free memory is particularly useful for reference types held in arrays, so that memory can be freed in time.

SoftReference

If an object has only soft references, there is enough memory for the garbage collector not to reclaim it; If you run out of memory, the objects are reclaimed. As long as the garbage collector does not collect it, the object can be used by the program. Soft references can be used to implement memory sensitive caching.

String str=new String("abc");                                     / / strong reference
SoftReference<String> softRef=new SoftReference<String>(str);     / / soft references
Copy the code

Soft references have important practical applications, such as the browser back button. When you press Back, is the content of the page displayed on the back page rerequested or retrieved from the cache? It depends on the implementation strategy.

(1) If a web page is recycled at the end of browsing, then click back to view the previous browsing page, need to rebuild

(2) If the browsing web pages are stored in memory, it will cause a large amount of memory waste, and even cause memory overflow. This is where soft references can be used

A soft reference can be used in conjunction with a ReferenceQueue (ReferenceQueue), and if the object referenced by the soft reference is collected by the garbage collector, the Java virtual machine adds the soft reference to the ReferenceQueue associated with it.

WeakReference

The difference between weak and soft references is that objects with only weak references have a shorter lifetime. When the garbage collector thread scans the memory area under its control, once it finds an object with only weak references, it reclaims its memory regardless of whether the current memory space is sufficient. However, because the garbage collector is a low-priority thread, objects that have only weak references are not necessarily found quickly.

WeakReference<String> weakRef = new WeakReference<String>(str);
Copy the code

If the object is used sporadically and you want it to be available whenever you use it, but you don’t want to affect the garbage collection of the object, then you should use Weak Reference to remember the object.

  • A weak reference becomes a strong reference:

    String  abc = abcWeakRef.get();
    Copy the code
  • Weak references can be used in conjunction with a ReferenceQueue (ReferenceQueue), and if the object referenced by a weak reference is garbage collected, the Java virtual machine adds the weak reference to the ReferenceQueue associated with it.

  • When you want to reference an object, but the object has its own life cycle, and you don’t want to interfere with the life cycle of the object, you are using weak references.

  • Weak references do not have any additional impact on an object’s garbage collection judgment

Virtual Reference

Unlike the other references, virtual references do not determine the life cycle of an object. If an object holds only virtual references, it can be collected by the garbage collector at any time, just as if there were no references at all.

Virtual references are mainly used to track the activity of objects being collected by the garbage collector. One difference between a virtual reference and a soft or weak reference is that a virtual reference must be used in conjunction with a ReferenceQueue. When the garbage collector is about to reclaim an object and finds that it has a virtual reference, it adds the virtual reference to the reference queue associated with it before reclaiming the object’s memory.