Java basic syntax

title: Java basic syntax
date: 2021-02-04 14:24:12
categories: Java
tags:

  • Basics

After learning C language, thinking is still process oriented programming thought. Now start learning Java and change your mind. I hereby write a blog to record the knowledge points of Java. Some common repetitive contents in the programming language (such as escape characters, process control statements, etc.) will not be repeated here. The basis of this article is that they buried their own pits when learning C language at that time, which are their own blood and tears!!!

In addition, this blog is only about the most basic part of JavaSE. There are many important issues related to the underlying source code and some technologies that are not discussed here.

Update 2021-04-17: it took more than 2 months to learn the introduction to Java after the end of spreading flowers, and a quarter of it at home for more than 1 month (learning efficiency is too low!!!). After returning to school, because I usually have classes, the time is relatively tight. As soon as I have time, I basically watch the teaching video and knock the code. At present, I have a general understanding of the knowledge system of Java and some basic syntax. But I know that this is not even a layman. I will go over it again and learn the language Java deeply. When the code is almost typed, they will start to learn java application technology. The last sentence concludes:

Talk is cheap, show me your code!

To be practiced item 3: P389~P405

It is divided into two parts due to the length of (jia) and (jia)

1. Preface

1.1 language features

  • Two basic concepts of object-oriented: class and object; Three characteristics: encapsulation, inheritance and polymorphism;
  • Robustness removes the application and release of pointer memory that affect robustness in C/C + +, and provides a relatively safe memory management and access mechanism and garbage collection mechanism (but there will still be problems of memory overflow and memory leakage)
  • Cross platform: Write once, run anywhere. The principle is: on the operating system that needs to run Java applications, install Java virtual machine first. The virtual machine is responsible for the running of Java programs in the system.

1.2 two core mechanisms of Java

  • Virtual machine mechanism (Java Virtual Machine)
  • Garbage Collection

1.3 JDK,JRE,JVM

  • JDK = JRE + development tool set (e.g. javac compiler)
  • JRE = JVM + JavaSE standard class library

2. Basic grammar

2.1 keywords, reserved words and identifiers

  • Key words: Thank you. Just remember the code
  • Reserved words: the existing JAVA version has not used the name, but later versions may be used as keywords. Therefore, these reserved words need to be avoided when naming identifiers: const and goto
  • Identifier: variable name, method name, class name, interface name, package name, etc. all that you can name are called identifiers. JAVA is strictly case sensitive when naming

2.2 naming conventions

  • Package name: all words in lowercase "xxyyzz"
  • Class name and interface name: capitalize the first letter of each word (named by the big hump) "XxYyZz"
  • Variable name and method name: the first word is lowercase, and the following words are capitalized (named by the small hump) "xxYyZz"
  • Constant name: all letters are capitalized, and multiple words are underlined to connect "XX_YY_ZZ"

2.3 classification of variables

According to the basic data type:

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-eujwo9gc-1620462806222)( https://pic-blogs.oss-cn-beijing.aliyuncs.com/img/ Classification of variables - by data type svg)]

According to the position of the Declaration:

The basic data types are classified according to the following variables:

2.3.1 basic data type

  • Integer (byte, short, int, long): integer constant is of type int by default

  • Floating point type (float, double): floating point constant is double by default. When defining long and float types, you need to add "L" or "L" and "F" or "F" after the value during initialization and assignment. Commonly used int and double types. If the long type is not suffixed, it defaults to int type, while the float type must be suffixed, otherwise the compilation fails;

  • Character type (char): different from C, java character type char can represent any character (each character occupies 2 bytes), not just western characters, such as char a = 'I';, And char a = '48'; Is wrong, because '48' is 2 characters, not even '4 spaces'. Spaces are also one character, but char a = 48; That's right, because when it is not enclosed in single quotation marks, it is equivalent to giving the ASCII code value to A. during compilation, the machine will look up the table and replace it with the corresponding character. 128 ASCII characters are represented by 8 bits, the highest bit is specified as 0, and the remaining 7 bits represent 0 ~ 127 ASCII characters;

  • boolean

2.3.2 reference type

class, interface, array

2.3.3 data type conversion (excluding boolean)

  • Automatic type promotion when a variable of a data type with a small capacity is calculated with a variable of a data type with a large capacity, the result is automatically promoted to a data type with a large capacity. That is, byte, char and short → int → long → float → double. In particular, when the variables of byte, char and short are operated, the result is int
  • Cast (inverse operation of automatic type promotion)

2.4 operators

1. Self increasing and self decreasing and + = and - = will not change the data type, such as:

short a = 1;
/******************************************************************/
//a = a + 1;
//The result of a+1 in Java is automatically converted to int, but the received a is short.
//C is only a warning, but the compilation can pass, and the result can be automatically converted into short, while java cannot pass the compilation
/******************************************************************/
a += 1;
//a++;
//++a;
//Self increment and self decrement will not modify their own data types, so they can be compiled in C and java without warning
/******************************************************************/
System.out.println(a);//2

2. The difference between self increasing and self decreasing in Java and C

short a = 1;
a += (a++) + (++a);//Although this kind of "Tan + +" expression is meaningless and even a little anti-human, it is often tested in exams
//In C, first calculate the content on the right: 1 + (2 + 1) = 4. At this time, due to the self increase of (+ + a), a=3; Then calculate a=a+4, so the final result is a = 7
//Java also calculates the content on the right first: 1 + (2 + 1) = 4, but the value of a will not change due to self increment,
//Still a = 1, then calculate a = a + 4 directly, and the result is a = 5
System.out.println(a);//5

3. Logical operator (the operation object must be boolean)

//There are only &, |, |, and in C! (i.e. and, or and not) three logical operators (the operation object can be any basic data type, and only judge the value: 0 is false, and non-0 is true)
//In Java, there are &, |, & &, |^ (i.e. logical and, logical or, short-circuit and, short-circuit or, logical non, logical XOR) six kinds of logical operators. The first four kinds can also be called single and, double and, single or, double or
//In Java logical operators &, | regardless of the previous expression, the latter expression will be executed (relatively stupid), while there is no such logical operator in C
//The logical operator has a short circuit, that is, when the previous expression can get the final result, the latter expression will not be executed (it is smarter and saves running time), and vice versa; On this point, & &, |𞓜 in C is the same as java;
//Therefore, the general development uses & &, |, |, and & mostly appear in the exam
//Take & and & & as ex amp les, and | and | are similar
boolean judgement1 = false;
int number1 = 1;
if(judgement1 & (number1++ > 0))
System.out.println(number1);//2

boolean judgement2 = false;
int number2 = 1;
if(judgement2 && (number2++ > 0))
System.out.println(number2);//1

4. Bitwise operators (rarely practical, but there will be relevant questions in the exam): move left < <, fill 0 in the low order (discard the high order); Shift right operation > >, the high bit is supplemented with the symbol bit (the value of the symbol bit is supplemented with the value)

//Note: all bit operations operate on the complement, and the sign bit does not participate in the shift
//Move left operation
//①
int a = 44;
int b = a << 2;
System.out.println(b);
//0 000 0000 0010 1100		44
//0 000 0000 1011 0000 		 Results 176
//②
int c = -8319;
int d = c << 2;
//1 010 0000 0111 1111 		 Original code - 8319
//1 101 1111 1000 0001 		 Complement-8319
//1 111 1110 0000 0100 		 Shift left result (complement)
//1 000 0001 1111 1100 		 Shift left result (original code) - 33276
System.out.println(d);//-33276

//Shift right operation
int e = -36;
int f = e >> 2;
//1 000 0000 0010 0100 		 Original code - 36
//1 111 1111 1101 1100 		 Complement-36
//1 111 1111 1111 0111 		 Shift right result (complement)
//1 000 0000 0000 1001 		 Shift right result (original code) - 9
System.out.println(f);//-9

5. The comparison operator instanceof determines whether the object is a class

2.5 switch case statement

The newly added variables can only be one of the following types: variable (char. 0) and variable (int) in JDC and C.

Note: don't forget to break when writing case statements!!! This is a mistake many beginners will make.

2.6 break and continue keywords

break ends the current loop by default and can be used for loop statements and switch case statements;
By default, continue only ends the current loop of the current loop, and continue can only be used for loop statements.

The similarities between the two are: at the same level, there can be no execution statement behind it, otherwise the compilation will report an error.

//Use of tags (in java, not in C)
label:for(......){
    for(......){
        break label;//Ends the current loop at the label
        //continue label;// End this cycle of the outer cycle at the label
    }
}

3. Array

The array belongs to the reference data type, and the elements of the array can be any data type

3.1 one dimensional array

import java.util.Scanner;

public class OneDimensionalArray {
    public static void main(String[] args) {
        //1. Array static initialization
        int[] array1_1 = new int[]{1,2,3,4};//Reference type initialization requires the help of new
        String[] array1_2 = new String[]{"Chuan Jianguo","Zhen Hua Bai","FakeNews","China"};

        //2. Array dynamic initialization
        int[] array2_1 = new int[4];
        String[] array2_2 = new String[4];

        System.out.println(array2_1.length);//The length property returns the length of the array
        //Once the array is initialized, the length is determined


        //Requirements: input the number of students and scores, and rate them according to the difference between the scores and the highest scores:
        //[0,10) is A, [10,20) is B, [20,30) is C, [30,maxScore] is D
        System.out.println("Enter the number of people:");
        Scanner scan = new Scanner(System.in);
        int number = scan.nextInt();
        int[] score = new int[number];
        int maxScore = score[0];
        System.out.println("Enter score:");
        for (int index = 0; index < score.length; index++) {
            score[index] = scan.nextInt();
            if (maxScore < score[index]) {
                maxScore = score[index];
            }
        }
        System.out.println("Highest score maxScore = " + maxScore);
        for (int index = 0; index < score.length; index++) {
            if (maxScore - score[index] < 10) {
                System.out.println("student" + index + "The score level of is:" + "A");
            } else if (maxScore - score[index] < 20) {
                System.out.println("student" + index + "The score level of is:" + "B");
            } else if (maxScore - score[index] < 30) {
                System.out.println("student" + index + "The score level of is:" + "C");
            } else if (maxScore - score[index] <= maxScore) {
                System.out.println("student" + index + "The score level of is:" + "D");
            }
        }
    }
}

When traversing an array, you can use the enhanced for loop (new in JDK1.5)

int[] arr = new int[]{1,2,3,4,5};

//Implemented using a normal for loop
for(int i =  0 ; i < arr.length ; i++){
    System.out.println("Element:"+ arr[i]);
}

//Using enhanced for loop implementation 
for(int ints : arr){
    System.out.println("Element:"+ ints);
}

Different types of array elements have different default initialization values

Element typeinitialize value
Integer (byte, short, char, int, long)0
Floating point type (float, double)0.0
Character type (char)0
booleanfalse
Reference data type (class, interface, array)null

3.2 two dimensional array

public class TwoDimensionalArray {

    public static void main(String[] args) {
        //1. Static initialization
        int[][] array1 = new int[][]{{1, 2, 3}, {4, 5, 6}};

        //2. Dynamic initialization
        int[][] array2_1 = new int[2][3];
        int[][] array2_2 = new int[2][];

        int[][] arr = new int[4][3];
        System.out.println(arr);
        //[[ I@1b6d3586 "[[" represents a two-dimensional array, "I" represents int type, and the number after @ represents the address value
        
        System.out.println(arr[0]);//[I@4554617c
        System.out.println(arr[0][0]);//0
    }
}

3.3 common algorithms involved in arrays

Here is only a brief introduction to some algorithms. For details, please refer to the course of data structure and algorithm.

3.3.1 assignment of array elements (Yang Hui triangle, return number, etc.)

import java.util.Scanner;
//Take Yanghui triangle as an example
public class YangHuiTriangle {
    public static void main(String[] args) {
        //Print Yang Hui triangle using two-dimensional array
        System.out.print("Number of input lines:");
        Scanner scan = new Scanner(System.in);
        int column = scan.nextInt();
        int[][] yangHui = new int[column][];

        for(int i = 0;i < yangHui.length;i++){
            yangHui[i] = new int[i + 1];//Row i has column (i+1)
            yangHui[i][0] = yangHui[i][i] = 1;//The first and last values of each line are assigned 0

            //Assign values to elements that are not at the beginning and end of each line
            for(int j = 1;j < yangHui[i].length - 1;j++){
                yangHui[i][j] = yangHui[i-1][j-1] + yangHui[i-1][j];
            }
        }

        //Traversing a two-dimensional array
        for(int i = 0;i < yangHui.length;i++){
            for(int j = 0;j < yangHui[i].length;j++){
                System.out.print(yangHui[i][j] + "\t");
            }
            System.out.println();
        }
    }
}

3.3.2 find the maximum value, minimum value, sum and average value of array elements

The difficulty is low and can be mastered with a little practice, so the code is not pasted here.

3.3.3 search of array elements

1. Linear search (search in order)
2. Dichotomy search (half search): use data whose premise is order (ascending and descending order is OK)

import java.util.Scanner;

public class BinarySearch {
    public static void main(String[] args) {

        int[] array = new int[]{-18, -9, 12, 21, 34, 45, 78, 90, 99, 123};
        int head = 0;
        int end = array.length - 1;

        System.out.print("Please enter the value you want to find:");
        Scanner scanner = new Scanner(System.in);
        int number = scanner.nextInt();
        boolean flag = true;
        while (head < end) {
            int middle = (head + end) / 2;
            if (number == array[middle]) {
                System.out.print("The specified element was found at index position:" + middle);
                flag = false;
                break;
            } else if (number > array[middle]) {
                head = middle + 1;
            } else {
                end = middle - 1;
            }
        }
        if (flag) {
            System.out.println("Unfortunately, the element value was not found");
        }
    }
}

3.3.4 sorting algorithm of array elements

Let's take the bubbling method as an example, and other sorting algorithms will not be mentioned for the time being

public class BubbleSort {
    public static void main(String[] args) {
        int[] array = new int[]{0, 12, -9, 123, 121, 90, 65, 1, 32, 19};
        int temp = 0;
        for (int i = 0; i < array.length - 1; i++) {
            for (int j = 0; j < array.length - 1 - i; j++) {
                if (array[j] > array[j + 1]) {
                    temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
        }
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + "\t");
        }
    }
}

3.4 array tool class Arrays class

import java.util.Arrays;

public class ArraysTest {
    public static void main(String[] args) {
        //Common methods in Arrays class
        //1.boolean equals(int[] a,int[] b) compare whether the two arrays are equal (whether the element values are equal)
        int[] array1 = new int[]{4,5,2,3};
        int[] array2 = new int[]{2,3,4,5};
        boolean isEqual = Arrays.equals(array1,array2);
        System.out.println(isEqual);

        //2.String toString(int[] a) output array information
        System.out.println(Arrays.toString(array1));

        //3.void fill(int[] a,int val) fills the specified value into the array
        Arrays.fill(array2,10);
        System.out.println(Arrays.toString(array2));

        //4.void sort(int[] a) sort the array
        int[] array3 = new int[]{0, 12, -9, 123, 121, 90, 65, 1, 32, 19};
        Arrays.sort(array3);
        System.out.println(Arrays.toString(array3));

        //5.int binarySearch(int[] a,int key) finds the index of elements in the array
        int[] array4 = new int[]{0, 12, -9, 123, 121, 90, 65, 1, 32, 19};
        int index1 = Arrays.binarySearch(array3,121);
        int index2 = Arrays.binarySearch(array3,122);
        System.out.println(index1);
        System.out.println(index2);//If it is not found, it returns a negative number. For the specific negative number, you need to check the source code of the method

    }
}

4. Object oriented programming (Part I)

Three main lines of object orientation:

1.Java classes and class members: properties, methods and constructors; Code block, inner class

2. Three characteristics of object-oriented: encapsulation, inheritance, polymorphism, (abstraction)

3. Keywords: this, super, static, final, abstract, interface, package, import

4.1 classes and objects

Class: the description of a class of things, which is an abstract and conceptual definition;

Object: each individual of this kind of thing that actually exists, so it can be said to be an instance of the class;

Anonymous object: you do not need to create an object to receive the reference type from new, or you do not explicitly assign a variable name when creating an object, which is an anonymous object. However, anonymous objects can only be used once and will be recycled after calling.

new Student().height = 176;
System.out.println(new Student().height);
//The result is 0, because the anonymous object of new Student() in the previous sentence is recycled after it is used up

It can only be used when the object needs to be used only once, such as passing in formal parameters. The focus of object-oriented programming is the design of classes, and design classes are members of design classes. An example code is as follows:

public class ClassTest {
    public static void main(String[] args) {
        Person p1 = new Person();
        p1.name = "Tom";
        p1.isMale = true;
        Person p2 = new Person();
        System.out.println(p2.name);
        Person p3 = p1;
        p3.age = 10;
        System.out.println(p1.age);
    }
}
class Person{
    String name;
    int age = 1;
    boolean isMale;
}

The memory analysis of the above object code is as follows:

The memory analysis of an object array code is as follows:

Array elements are of student type (i.e. reference type), so array members are null by default when they are not initialized (New creates an object). If the attribute value is printed out at this time, system out. println(stus[1].number);, Then an error will be reported, which is a null pointer exception. Because null does not point to any address, the value cannot be read out. Only initialize array members, i.e. stus[1] = new Student(); After that, the properties of the modified member can be read out.

4.2 difference between attribute (or "member variable") and local variable

Attribute: directly defined in a pair of {} of the class

Local variables: variables declared within methods, method parameters, code blocks, constructor parameters, and constructors

The differences are as follows:
1. Permission modifier can be used to indicate its permission when declaring attributes. Default: public and private. However, local variables cannot be modified with permission modifiers, otherwise the compilation will not pass;

2. Local variables have no default initialization value, so when calling local variables, they must be explicitly assigned; Arguments must also be initialized before they can be passed to formal parameters. The default initialization value of the attribute is as follows (the same as the default initialization value of the array element):

However, after the property is initialized, it cannot be assigned inside the external class of the creator.

3. The location attribute loaded in memory is loaded into the heap space (non static). When there is no point to the variable in the stack, the variable in the heap will be recycled by the garbage collector. Local variables are loaded into the stack space. After the method is completed, the local variables are out of the stack.

4.3 method

4.3.1 method overload

In the same class, more than one method with the same name is allowed. As long as the number of parameters or parameter types are different, the method overload is between two or more methods with duplicate names. The return value type is not considered, that is, if the return types of methods with the same name and parameters are inconsistent, they will not constitute overloading and will cause ambiguity.

Are the following methods consistent with void show(int a,char b,double c){}Composition method overload

a)void show(int x,char y,double z){}//no, because although the names of formal parameters are different, the types of formal parameters are the same

b)int show(int a,double c,char b){}//yes, because the order of the formal parameter list is different

c)void show(int a,double c,char b){}//yes, ditto

(b)and(c)They do not constitute method overloading. They are exactly the same, but the return value types are different, which will lead to ambiguity

d)boolean show(int c,char b){}//yes, the parameter list is different

e)void show(double c){}//yes, ditto

f)double show(int x,char y,double z){}//no, the formal parameter types are consistent

g)void shows(){double c;}//no, the method names are different

4.3.2 variable number formal parameters

JDK5.0 provides a variable number of arguments (varargs) mechanism, which allows you to directly define formal parameters that can match multiple arguments. Thus, you can pass a variable number of arguments in a simpler way.
JDK5. Before 0: use array parameters to define methods, and pass in multiple variables of the same type, public static void test (int a, string [] books);
JDK5.0: use variable number formal parameters to define methods, and pass in multiple public static void test (int a, string... Books) variables of the same type;

public static void test(int a,String[] books);
public static void test(int a,int[] books);
public static void test(int a,String... books);
public static void test(int a,int... books);

The parameters passed in can be: 0, 1, 2, 3... However, the variable number parameter must be declared at the end of the method parameter, and at most one deformable parameter can be declared. The above two methods do not constitute method overloading. They are exactly the same.

4.3.4 value transfer mechanism of method parameters

There is only one way to pass parameters of methods in Java: value passing. That is, a copy (Replica) of the actual parameter is passed into the method, and the parameter itself is not affected. 1. When the formal parameter is a basic data type, the data value of the basic data type is passed;
2. When the formal parameter is a reference data type, the address value of the reference data type variable is passed.

4.3.5 recursion method

//Recursive summation
public int getSum(int n){
    if(n == 1){
        return 1;
    }else{
        return n + getSum(n - 1);
    }
}
//Recursive calculation of Fibonacci number
public class FibonacciSequence {
    public static void main(String[] args) {
        int[] arr = new int[100];
        System.out.print("n = ");
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();

        FibonacciSequence test = new FibonacciSequence();
        //The first n Fibonacci sequences are stored in array arr
        for(int i = 1;i <= n;i++){
            arr[i] = test.function(arr,i);
        }
        System.out.println("front" + n + "Xiang Fibonacci's sequence is as follows:");
        for(int i = 1;i <= n;i++){
            System.out.print(arr[i] + "\t");
        }
        System.out.println();
    }
    /*The value of a certain term of Fibonacci sequence is obtained by recursive creation method*/
    public int function (int[] arr,int n){
        if(n == 1){
            return 1;
        }else if(n == 2){
            return 1;
        }else{
            return arr[n-1] + arr[n-2];
        }
    }

}

A word of advice: be careful with recursion before you become an old programmer. Although recursion is much simpler than loop, the logic is not so clear.

4.4 object oriented features

4.4.1 permission modifier

Four kinds of permissions specified by Java (from small to large): private, default (that is, not writing), protected and public are placed in front of the definition of class members (properties, methods, constructors and internal classes), which are used to restrict the access rights of objects to members of this class.

Among them, classes can only be modified by public and default. Public classes can be accessed anywhere, and default classes can only be accessed between classes in the same package. The access rights of modifiers are shown in the following table:

Modifier Class interiorDifferent classes of the same packageSubclasses of different packagesSame project (including multiple packages)
privateyesnonono
Default (i.e. no writing)yesyesnono
protectedyesyesyesno
publicyesyesyesyes

For permission modifiers, see 5.3 four permission modifiers Further supplementary explanations are also made in.

4.4.2 Encapsulation (one of the object-oriented features)

When you create an object of a class, you can use the object Property or object Method. However, in practical problems, it is often necessary to add constraints to attributes (for example, the number of animal legs is generally even even even number). However, this restriction cannot be set at the time of property declaration. It can only be added by creating a method in this class without calling the property of the object.

At the same time, in order to avoid the confusion of using methods to set constraints and object calls to set constraints, use the private keyword to declare properties or methods private.

Embodiment of encapsulation 1: privatize the attribute xxx of the class using private, and provide public methods (public decoration) to obtain (getXxx) and set (setXxx) the value of this attribute;
Embodiment of encapsulation 2: not exposing private methods;
Embodiment of encapsulation 3: Singleton mode (privatizing the constructor);
Embodiment 4 of encapsulation: if you do not want the class to be called outside the package, you can set the class as the default.

4.5 constructor (or construction method, constructor)

4.5.1 characteristics of constructor

It has the same name as the class, does not declare the return value type (different from declaring void), cannot be modified by static, final, synchronized, abstract and native, and cannot return a value with a return statement.

4.5.2 function of constructor

1. Create objects (the core role), such as Order o = new Order();
2. Initialize the attribute when creating the object, for example: Person p = Person("Peter",15);

4.5.3 description

1. If the constructor of a class is not explicitly defined, the system provides an empty parameter constructor by default, so a class has at least one constructor;
2. Define the format of constructor: permission modifier class name (formal parameter list) {};
3. Multiple constructors can be defined in a class to form overloads with each other;
4. Once the class constructor is explicitly defined, the system will no longer provide the default null parameter constructor (this is often forgotten by many people!!!);
5. The constructor can be called only in the constructor, and it is forbidden to call the constructor elsewhere.

//Write two classes, TriAngle and Constructor
//The TriAngle class declares the private base length and high H eight, and also declares the public method to access the private variable.
//In addition, provide the necessary constructors for the class
//These common methods are used in the Constructor class to calculate the area of a triangle
public class Constructor {
    public static void main(String[] args) {
        TriAngle angle1 = new TriAngle();
        angle1.setBase(3.0);
        angle1.setHeight(4.9);
        System.out.println("base = " + angle1.getBase() + "\theight = " + angle1.getHeight() + "\tarea = " + angle1.area());

        TriAngle angle2 = new TriAngle(2.0,3.1);
        System.out.println("base = " + angle2.getBase() + "\theight = " + angle2.getHeight() + "\tarea = " + angle2.area());

    }
}

class TriAngle {
    private double base;
    private double height;

    //Access private variables by declaring public methods
    public void setBase(double b) {
        base = b;
    }

    public double getBase() {
        return base;
    }

    public void setHeight(double h) {
        height = h;
    }

    public double getHeight() {
        return height;
    }
    
    //Constructor declaration:
    //Once a public TriAngle(double b, double h) {} maker is explicitly defined,
    //The system will no longer provide the default null parameter constructor, that is, Triangle t1 = new Triangle(); It won't work
    //You must define another empty constructor public Triangle() {}
    //You can only use Triangle t1 = new Triangle(); Create object t1
    public TriAngle() {

    }
	
    public TriAngle(double b, double h) {
        base = b;
        height = h;
    }
    //Declare the public method of calculating the area
    public double area() {
        double area = base * height / 2.0;
        return area;
    }

}

4.6 JavaBean

The so-called JavaBean is actually a Java class that meets the following standards:

1. Class is public;
2. There is a public constructor without parameters;
3. There are attributes and corresponding get and set methods.

4.7 keyword this

this can be used to call properties, methods and constructors, which can be understood as a reference to the current object.

4.7.1 this calls properties and methods

In the class method, this represents the current object. We can use this Field or this Method() to call the property or method of the current object. But usually, we choose to omit this. In particular, if the formal parameter of the method has the same name as the attribute of the class, we must explicitly use this Field, indicating that this variable is an attribute rather than a formal parameter.

public class Person{
    int age;
    String name;
    public void method(int age){
    	//If this is not used here, the default is that the formal parameter assigns its own value
        this.age = age;
	}
}

4.7.2 this call constructor

1. In the constructor of a class, you can explicitly use this (formal parameter list) method to call other overloaded constructors in the class according to the formal parameter list;
2. The constructor cannot call itself through this (formal parameter list);
3. Specify: this (formal parameter list) must be declared in the first line of the current constructor;
4. Since this (formal parameter list) can only be in the first line, if you write more, it will not be in the first line, so you can only declare one this (formal parameter list) at most to call other constructors (pay attention to distinguish it from this calling properties and methods);

public constuctor(){
    this.eat();
    this.sleep();
}
public constructor(double x){
    this();
    //The constructor constructor() {} of the above empty reference is invoked, and the steps of calling the eat method and then calling the sleep method are executed.
    
    this.walk();
}
public constructor(double x,int y){
    this(x);
    //Call the overloaded constructor constructor(double x) {}, and execute the calling empty reference constructor and invoke the walk method.
    
    //this(x,y); Is wrong, the constructor cannot call itself
   
    //this();
    //this(x);
    //This is also wrong, because only one this (formal parameter list) can be declared
}

4.8 package and import keywords

4.8.1 package keyword

In order to solve the problem of many complex classes and interfaces in the project, packages are used for management, similar to folder management files.

Use package to declare the package to which the class or interface belongs on the first line. Generally use lowercase letters to name xxyyzz, each Once represents a layer of file directory. For example, xx yy. The parent directory of yzzy is the parent directory of yzzy. And there cannot be classes or interfaces with the same name under the same package (excluding sub packages). Common packages are as follows:

Package nameexplain
java.langIt contains some core classes of java language, such as String, Math, Integer, System, Thread, etc., and provides common functions
java.netContains classes and interfaces that perform network related operations
java.ioContains classes that provide multiple input / output functions
java.utilIt includes some practical tool classes, such as defining system features, collection framework classes of interfaces, and using methods related to date and calendar
java.textContains some java formatting related classes
java.sqlContains java JDBC database programming related classes / interfaces
java.awtContains several classes that make up the abstract window toolkits, which are used to build and manage the graphical user interface (GUI) of the application. Because the interface is extremely ugly, it is generally not used as a GUI

4.8.2 import keyword

Use the import structure to import the class and interface declaration under the specified package between the package declaration and class declaration.

import java.util.Scanner;//Import the Scanner class under util package
import java.util.Arrays;//Import the Arrays class under util package
import java.util.*;//Import all classes and interfaces under the util package, excluding the classes and interfaces of its sub packages. The sub packages need to be imported additionally

//Note that the source files import all classes and interfaces in the lang package by default, and there is no need to import the package
import java.lang.reflect.Field;
//The file class under the reflect package in the lang package is not the class under the lang package, but the class under its reflect package,
//Therefore, you must explicitly guide the package and cannot omit it

//If the class or interface used in the source file is defined under this package, you can call it directly without importing the package
//Although classes or interfaces under different packages can have the same name, if you want to use these classes or interfaces with the same name at the same time,
//The complete package name must be added before use (such class name is the full class name), such as:
pers.zhangsan.exercises.Person p1 = new Person();
pers.lisi.exercises.Person p2 = new Person();

//Extension: import static can import static structures (properties or methods) in classes or interfaces. You can understand them
import static java.lang.System.*;
import static java.lang.Math.*;//Never write like this: import static Java lang.Math;
out.println("Study hard and the roof is up");
long num = round(123.456);

5. Object oriented programming (medium)

5.1 inheritance (the second feature of face object)

5.1.1 format of inheritance

class A extends B {}, where A is called A subclass or A derived subclass, and B is called A parent class or A base class or A derived superclass.
Once subclass A inherits parent class B, all properties and methods declared in parent class B are inherited in subclass A. In particular, if private attributes and methods are declared in the parent class, they can still be inherited, but because of the influence of encapsulation, the attributes and methods in the parent class cannot be called directly (in short, yes, but not adjustable). After the subclass inherits the parent class, it can also declare its own unique properties and methods to expand its functions. As follows:

public class Inheritance {
    public static void main(String[] args) {
        SubClass subClassTest = new SubClass();

        System.out.println(subClassTest.a + "\t" +
                           subClassTest.b + "\t" + subClassTest.c);

        subClassTest.eat();
        subClassTest.sleep();
        subClassTest.study();
    }
}

class SuperClass{
    int a = 1;
    int b = 2;

    public void eat(){
        System.out.println("having dinner");
    }

    public void sleep(){
        System.out.println("sleep");
    }
}

class SubClass extends SuperClass{
    int c = 3;
    public void study(){
        System.out.println("study");
    }
}

The result is:

5.1.2 provisions on inheritance in Java

1. A class can be inherited by multiple subclasses, but a class can only have one parent class (single inheritance of Java);
2. Child and parent are relative concepts;
3. The parent class directly inherited by the child class is called the direct parent class, and the parent class indirectly inherited is called the indirect parent class;
4. After the subclass inherits the parent class, it obtains the attributes and methods declared in the direct parent class and all indirect parent classes;

5. The Object class is the root of the class hierarchy. Each class has Object as its parent class, and all objects (including arrays) implement such methods.

5.2 method Override

Modifying the method inherited from the parent class in the subclass is also called method reset and overwrite. When the program executes, the methods of the subclass will override the methods of the parent class.

The rewriting rules are as follows:

1. The subclass overriding method must have the same method name and parameter list as the method overridden by the parent class;

2. The return value type of the subclass overriding method cannot be greater than the return value type of the method overridden by the parent class;

① If the return value of the overridden method in the parent class is void, the overridden method in the child class can only be void; ② If the return value of the overridden method in the parent class is type A, the return value of the overridden method in the subclass can be type A or a subclass of a; ③ If the return value of the overridden method in the parent class is the basic data type, the return value of the overridden method in the child class must be the same. For example, if double is in the parent class, double must also be in the child class; If the parent class is int, the child class must be int.

3. The permission modifier used by the subclass rewriting method cannot be less than the access permission of the parent class rewritten method;

For example, if the parent class is a protected modified method, the overridden method in the child class must be protected or public; If the parent class is a public modifier, the child class can only be public. In particular, methods that use private decoration in the parent class cannot be overridden in a subclass.

4. The exception thrown by the subclass rewriting method cannot be greater than the exception of the parent class rewritten method (explain again at the exception handling section)

5. Methods with the same name and parameters in the subclass and parent class must be declared as non static (i.e. overridden) or static (not overridden) at the same time

Generally speaking, in the process of actually writing code, when rewriting methods, the main consideration should be to design the method body. I'm too lazy to take into account the above four rules. Generally, I copy the permission modifier, return value type, static modifier, etc. of the parent class. This is just for introduction.

Constructors and methods can be overloaded, but only methods can be overridden, and constructors cannot.

5.3 four access rights modifiers

Modifier Class interiorDifferent classes of the same packageSubclasses of different packagesSame project (including multiple packages)
privateyesnonono
Default (i.e. no writing)yesyesnono
protectedyesyesyesno
publicyesyesyesyes

1. Other classes in the same package, such as class A2 in package a, cannot call the properties and methods modified by private in class A1, but only those modified by default, protected and public;
2. Subclasses of different packages. For example, Class B1 in package B inherits from class A1 in package a, Class B1 cannot call the properties and methods of private and default modification in class A1, but can only call protected and public modification. Protected is designed to be visible and called only to subclasses in different packages;
3. For ordinary classes (non subclasses) of different packages, for example, all classes in package B cannot call the properties and methods modified by private, default and protected in all classes in package A, but only those modified by public.

5.4 keyword super

The keyword that can be used to understand the constructor's parent class, constructor's parent class, or constructor's child class.
Note: both direct and indirect parents are parents.

5.4.1 super calls the attribute with the same name in the parent class

A subclass can have an attribute with the same name as the parent class (the data type can be the same or different), and the attribute will not be rewritten like the rewriting method.

If the property of the same name is called in the subclass, if the front is not written, the compiler will add the this keyword in front of the attribute by default, so it is all called by default the same name property of the subclass (whether it is the same as the data type, which is the default tone class).

If you want to call the same name property of the parent class in the subclass method or constructor, use the super keyword through the super.. A property with the same name calls a property in the parent class.

class SuperClass{
    String id = "SuperClass";
}

class SubClass extends SuperClass{
    String id = "SubClass";
    //int id = 1;
    public void show(){
        System.out.println(id);//The default is to call the property with the same name of the subclass
        System.out.println(super.id);//Call a property with the same name in the parent class

    }
}

public class Inheritance{
    public static void main(String[] args) {

        SuperClass superClassTest = new SuperClass();
        SubClass subClassTest = new SubClass();

        System.out.println(superClassTest.id);
        System.out.println(subClassTest.id);

        subClassTest.show();

    }
}

Although the attributes with the same name in the child and parent classes can be distinguished, this writing is time-consuming and meaningless. Therefore, the case of the child and parent classes with the same name in this section is only for introduction. In practice, attributes with the same name are generally not defined in child and parent classes, which makes trouble for yourself.

5.4.2 super calls the overridden method in the parent class

Calling a method with the same name in the parent class is roughly the same as calling a property with the same name.

Writing a method with the same name in a subclass is actually rewriting (or overwriting) the method of the parent class in the subclass. The compiler will add this keyword by default, so it calls the method in the subclass by default.

If you want to call a rewrite method in the parent class in a subclass method or constructor, use super.. method

class SuperClass{
    public void show(){
        System.out.println("From parent class show method");
    }
}

class SubClass extends SuperClass{
    @Override
    //Override the show method in SubClass subclass
    public void show() {
        System.out.println("From subclass overrides show method");
        super.show();
    }
    
    //Other non overridden methods call methods in the parent class
    public void show1(){
        System.out.println("A non overridden method from a subclass");
        super.show();
    }
}

public class Inheritance{
    public static void main(String[] args) {
        SubClass subClassTest = new SubClass();
        subClassTest.show();
        subClassTest.show1();
        
    }
}

5.4.3 calling the constructor in the parent class

1. You can explicitly use super (formal parameter list) (super() if the formal parameter list is empty) in the subclass constructor to call the specified constructor declared in the parent class. Like this (formal parameter list) calling the constructor, super (formal parameter list) must be declared in the first line of the subclass constructor;

2. If super (formal parameter list) is not explicitly declared in the first line of the constructor, the default super() calls the constructor of the null parameter of the parent class;

3. In the class constructor, because this (formal parameter list) and super (formal parameter list) can only be located in the first line, only one can be written. For this (formal parameter list) or super (formal parameter list), you can only choose one from the other and cannot appear at the same time;

4. Among multiple constructors of a class, the constructor of at least one class uses super (formal parameter list) to call the constructor in the parent class (if not written, the default is super() to call the null parameter constructor). Therefore, if the first line inside the constructor is this (formal parameter list), you cannot write Super (formal parameter list) on the next line, but the constructor will call super() by default. If the first line is super (formal parameter), this (formal parameter list) cannot be written on the next line, and the constructor will not call this() by default.

class Person1{
    int age;
    public Person1(){
        age = 20;
    }

    public Person1(int age){
        this.age = age;
    }

}

class Person2 extends Person1{
    public Person2(){
        //If it is not written here, the null parameter constructor in the parent class will be called by default. If it is written, the written constructor will be called
    }
    
    /*public Person2(){
        super();//It's OK to write it. If you don't write it, super() is added by default;
      	//Write one more line of super(age) or this(age) and an error will be reported
      	//Because this (formal parameter list) and super (formal parameter list) can only be in the first line, only one can be written
        //Note: the previous constructor and this constructor are essentially the same constructor, so they cannot be written at the same time, otherwise an error will be reported
    }*/
    
    /*public Person2(){
        super(age);
        //This is also wrong, because the initialization of the constructor is earlier than that of the local variable,
        //In other words, when the constructor is initialized, the local variable age has not been created (the constructor is null and has no formal parameters, so it has not been created),
        //So it can't be called
    }*/
    
    /*public Person2(int age){
        super(age,id);
        //Similarly, when trying to call the public Person(double x, double y) constructor in the parent class,
        //Since the id local variable has not been created when initializing the constructor, the constructor in the parent class cannot be called
    }*/
    
    public Person2(int age){
         super(age);//Call the constructor with parameters
        //Similarly, if it is not written here, the constructor of the null parameter will be called first by default, and then the next line of statement will be executed
        this.age = age;
    }
    //If the null parameter constructor in the above parent class is deleted, only the one with parameters will be retained,
    //Then the subclass constructor without writing super (formal parameter list) and this (formal parameter list) cannot find the null parameter constructor of the parent class by default,
    //Because once only the constructor with parameters is written, the constructor that provides empty parameters by default is no longer available. You must manually write a constructor with empty parameters.
}

In fact, this and super call constructors have many similarities, but the former is the constructor that calls the current object, while the other is the constructor that calls the parent class. Since the constructor can only be called inside the constructor, both call the constructor inside the constructor, which is prohibited elsewhere.

5.5 subclass object instantiation process

1. From the result: after the subclass inherits the parent class, it obtains the properties or methods declared in the parent class. If you create an object of a subclass, the attributes declared in all the parent classes will be loaded in heap space.
2. From the process point of view: when we create a subclass object through the subclass constructor, we will call the constructor of the parent class directly or indirectly, and then call the constructor of the parent class until we call Java Until the constructor of lang.Object null parameter, because all the structures of the parent class have been loaded, we can see that there are structures (properties and methods) in the parent class in memory, and the child class object can consider calling its structure.

It should be clear that although the constructor of the parent class is called when creating a subclass object, only one object (that is, the subclass object of new) has been created from beginning to end

Thinking: 1 Why can't super(...) or this(...) call statements appear in one constructor at the same time?
Answer: because both super and this call constructors must be declared on the first line, if multiple super(...) or multiple this(...) or both super(...) and this(...) appear at the same time, it will not be on the first line.
2. Why can the super(...) or this(...) call statement only appear as the first sentence in the constructor (or written on the first line)?
A: no matter which constructor you use to create a subclass object, you need to initialize the parent class first. The purpose is to inherit all the properties and methods in the parent class after the child class inherits the parent class. Therefore, the child class must know how the parent class initializes the object.

5.6 Polymorphism (object-oriented feature 3)

Polymorphism can be understood as multiple forms of a thing.

5.6.1 what is polymorphism

Polymorphism is also generally called object polymorphism. To sum up, it is that the reference of the parent class points to the object of the child class (or the reference of the object of the child class assigned to the parent class).

//Assuming that at this time, both Man class and Woman class inherit from Person class, then:
Person p1 = new Person();//create object
Person p2 = new Man();//polymorphic
Person p3 = new Woman();//polymorphic
//Similarly, the attributes modified by private are inherited by subclasses. p2 objects in the above polymorphism have those unique attributes and methods in subclass Man,
//It's just that you can't call it. Due to the limitation of Person type, you can only call the properties and overridden methods with the same name in the subclass and Person class.
//The same is true for p3 objects

5.6.2 introduction to the application of polymorphism

It is mainly used for virtual method calls, that is, we can only call the methods declared in the parent class at compile time, but at run time, we actually execute the methods that override the parent class in the subclass. To sum up, look at the left for compilation and the right for operation.

Premise of use:
① Class inheritance relationship;
② Method rewriting;

public class AnimalTest {

    public static void main(String[] args) {
        AnimalTest test = new AnimalTest();
        test.func(new Dog());

        test.func(new Cat());
    }

    /*If there is no polymorphism, if you want to use Dog and Cat's eat method and shot method respectively,
    You have to rewrite the method. If there are multiple animals, you have to rewrite it many times.
    In this way, it is too cumbersome and too much redundant useless code is written
    */
    public void func(Animal animal){
        animal.eat();
        animal.shout();
    }

    public void func(Dog dog){
        dog.eat();
        dog.shout();
    }

    public void func(Cat cat){
        cat.eat();
        cat.shout();
    }

}

class Animal {
    public void eat() {
        System.out.println("Animals, eating");
    }

    public void shout() {
        System.out.println("Animals, called");
    }
}

class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("Dogs eat bones");
    }
    @Override
    public void shout() {
        System.out.println("Woof! Woof! Woof!");
    }
}
class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("Cats eat fish");
    }
    @Override
    public void shout() {
        System.out.println("Meow! Meow! Meow!");
    }
}

The operation results are as follows:

5.6.3 application of polymorphism

//Suppose that at this time, both the Man class and the Woman class inherit from the Person class
Person p2 = new Man();
Person p3 = new Woman();
//Attributes similar to private decoration are inherited by subclasses,
//The p2 object in the above polymorphism has those unique attributes and methods in the subclass Man, but it can't be called,
//Due to the limitation of Person type, only properties with the same name in subclass and Person class and overridden methods can be called. The same is true for p3 objects

In the above code, if you want to use the special properties and methods in the subclass Man, you can use forced type conversion:

Man m = (Man)p2;//Forced type conversion (the type must have a child parent relationship)
//After the conversion, you can call the properties and methods
m.method();

With the automatic type promotion in the basic data type, int number1 = 1;double number2 = number1; Similarly, the object created by the subclass is assigned to the variable created by the parent type, that is, Person p1 = new Man(), which will automatically be cast into the parent type Person, and also has those unique properties and methods in the subclass Man, but it can't be called. This transformation is essentially polymorphic.

Downward transformation is rarely used, and basically upward transformation (polymorphism) is used. If you want to be like double number1 = 1.0;int number2 = (int)number2;, To cast a parent type to a child type, you can use cast like the code above.
However, the premise of this transformation is: the object of the subclass is assigned to the reference (variable) of the parent class through polymorphism. At this time, the reference of the parent class can be forcibly transformed into the subclass type (in essence, the object must be an instance of the target class during transformation to be transformed into the target type), as shown below:

/*Correct downward transformation*/
Person p = new Man();
Man m = (Man)p;//Object p is an instance of Man class, so it can be forcibly converted

/*Wrong downward transformation*/
Person p = new Person();
Man m = (Man)p;//Object p is not an instance of Man class, so it cannot be forced

Therefore, downward transformation is prone to errors. Generally, the instanceof keyword will be added to judge whether the object is an instance of a class,

public class InstanceofTest {
    public static void main(String[] args) {
        //1. Compilation failed
//        Man m1 = new Woman();

        //2. Compile and run
//        Person p1 = new Woman();
//        Man m1 = (Man) p1;

        //3. The compilation passed and the runtime passed
        Object obj = new Woman();
        Person p = (Person) obj;

        /*  a instanceof A  Judge whether object a is an instance of class A. if so, return true. If not, return false
        Usage context: in order to avoid the exception of ClassCastException in the downward transformation, before the downward transformation,
        Using the judgment of instanceof, once it returns true, it will be transformed downward, otherwise it will not be transformed downward
        If: a instanceof A returns true and a instanceof B returns true, then class B is the parent class of class A
        */

        Person person = new Person();
        Man man = new Man();
        Woman woman = new Woman();
        if (person instanceof Person) {
            System.out.println("Person Class object is Person Class");//The same is true for other classes
        }
        if (man instanceof Person) {
            System.out.println("Subclass Man The object of is also a parent class Person An instance of type");
        }
        if (woman instanceof Person) {
            System.out.println("Subclass Woman The object of is also a parent class Person An instance of type");
        }
        if (!(person instanceof Man || person instanceof Woman)) {
            //It will be executed only when it is also false
            System.out.println("Parent class Person The object of is not a subclass Man and Woman An example of");
        }
        System.out.println();
        Person manInPerson = new Man();
        Person womanInPerson = new Woman();
        if (manInPerson instanceof Person && manInPerson instanceof Man) {
            Man man1 = (Man) manInPerson;
            System.out.println("In polymorphism, subclasses Man Object of manInPerson Is a parent class Person An example of Man An example of");
        }

        if (womanInPerson instanceof Person && womanInPerson instanceof Woman) {
            Woman woman1 = (Woman) womanInPerson;
            System.out.println("In polymorphism, subclasses Woman Object of womanInPerson Is a parent class Person An example of Woman An example of");
        }

        if (!(manInPerson instanceof Woman || womanInPerson instanceof Man)) {
            System.out.println("In polymorphism, subclass objects are not instances of each other's types. Because there is no inheritance relationship, there is no connection between subclasses");
        }

    }
}

class Person {

}

class Man extends Person {

}

class Woman extends Person {

}

The results are as follows:

5.7 Object class

There are no attributes defined in the Object class, only methods are defined. Among them, arrays are similar to classes, but also inherit from the Object class.

5.7.1 equals() method

1. Review the use of = = operator. If the variables of basic data type are compared (cannot be compared with boolean type), the comparison is whether the data values are the same (the data types do not have to be the same, and the type will be promoted automatically); If you are comparing variables that reference data types, you are comparing whether the address values of the two objects are the same (that is, whether the two references (i.e. variables) point to the same object instance), rather than whether the properties and methods of the object itself are the same. It can only be used to compare * * objects of the same type (including objects of child and parent classes) * *, otherwise it will not even pass the compilation.

2. Use of equals() method public boolean equals(Object obj) is a method, not an operator, and can only be used to reference data types. Examples are as follows:

public class Equals {
    public static void main(String[] args) {
        Person person1=new Person("Tom",21);
        Person person2=new Person("Tom",21);
        String str1 = "Tom";
        String str2 = "Tom";
        System.out.println(person1 == person2);//false
        System.out.println(person1.equals(person2));//false
        System.out.println(str1.equals(str2));//true

    }

}

class Person {
    int age;
    String name;

    public Person(String name, int age) {
        this.age = age;
        this.name = name;
    }

    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return this.name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return this.age;
    }

}

View the definition of the equals() method in the Object class:

public boolean equals(Object obj) {
    return (this == obj);//this represents the current object
}

You can see that the equals method in the Object class is the same as the = = operator, which is the address value of the comparison Object. The String class rewrites the equals() method:

public boolean equals(Object anObject) {
    if (this == anObject) {//this object represents the current
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

String, Date, File, wrapper class, etc. all override the equals() method in the Object class. After rewriting, the comparison is not whether the address values of the two references are the same, but whether the "entity content" of the two objects is the same.

3. Override the equals() method in a custom class. Generally, if a custom class uses the equals() method, it generally wants to compare the entity contents of two objects, so it needs to override the equals() method in the Object class

@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj instanceof Person) {
        Person person = (Person) obj;
        //Compare whether each attribute of two objects is the same or not, and whether to compare all attributes is up to you
        return this.age == person.age && this.name.equals(person.name);
    }
    return false;
}

Generally, the quick rewrite equals method of IDE is used, which is more rigorous and saves time. Whether it can only be used for objects of the same type depends on the source code of the equals() method.

5.7.2 toString() method

1. * * when outputting a reference to an object, it is actually calling the toString of the current object, * * examples are as follows:

public class toString {
    public static void main(String[] args) {
        Person person = new Person();
        String str1 = new String("HandsomeBoy");//The toString method is overridden in the String class
        System.out.println(str1.toString());
        System.out.println(str1);//Because toString() will be automatically adjusted by default during output, it doesn't matter if it's not written here
        System.out.println(person.toString());
        System.out.println(person);

    }

}

2. Definition of the same String() in object class:

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

3. String, Date, File, wrapper class, etc. have rewritten the toString () method in the Object class, so that the "entity content" information is returned when calling the toString () of the Object; 4. The custom class can also override toString(). When this method is called, the "entity content" of the Object will be returned.

@Override
public String toString() {
    return "Person[ age=" + age + ", name=" + name + " ]";
}

Similarly, the IDE is generally used to generate rewritten toString methods.

5.8 JUnit unit test (just understand)

In the process of writing code, with the prompt function of IDE, syntax errors can be found and eliminated in the process of writing code. However, sometimes, when designing a method, we often don't know whether it can achieve the expected effect. If we create variables or objects specifically for testing the method, After retesting, you have to comment or delete these test codes (because if you don't remove them, on the one hand, it will bring a certain burden to check the code in the future; on the other hand, mixing test codes between the codes is easy to cause structural confusion). When the amount of code is large, it's a headache to just note these useless test codes. Therefore, in order to improve efficiency, another test class is specially created to separate the test code from the main code. When testing, just run in the test class, which will not affect the debugging and operation of the main code. At present, JUnit unit test is mainly used to test the method. The following are the steps of JUnit unit test in intelligent idea:

1. Create a new folder named "Test" in the project directory (in the same directory as src folder), and set Mark as to Tests in file - > project structure;

2. Create Java classes in the Test folder and conduct unit tests in this class. The required format of this Java class is as follows:
① It must be public modified and provide a public parameterless constructor;
② In the test, the method does not have permission, and the returned value is not required in the public method;
③ The annotation @ test needs to be declared on this unit test method and imported into import org. Before the unit test class junit. Test;

3. After declaring the unit test method, you can test the relevant code in the method body;

4. After writing the code, right-click the unit test method name and run it. Note: if there is no abnormality in the execution result, the green bar; If there is an exception in the execution, a red bar is displayed.

If you want to directly test the methods in existing classes, you can right-click the class to be tested - > go to - > test, select "create new test..." and open the generation interface. In the generation interface, select Testing Library as JUnit 4, check the function to be tested, and then click OK to generate.

5.9 Wrapper

In order to make up for the disadvantage that the basic data type does not have class characteristics, the corresponding reference type packaging class (packaging class) is defined for eight basic data types, so that the variables of the basic data type have class characteristics.

Among them, the parent class of the first six numeric wrapper classes is Number (inherited from the Number class).

Basic data typePackaging
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
booleanBoolean
charCharacter

Master the conversion among basic data type, packing class and String. The following is the conversion between basic data type and packing class.

public class Wrapper {
    public static void main(String[] args) {
        Difference test = new Difference();
        System.out.println(test.isBoy);//false, the default value of basic data type is 0
        System.out.println(test.isGirl);//Null. The default value of class type is null

        //Basic data type - > wrapper class: call the constructor of wrapper class
        int num1 = 10;
        Integer int1 = new Integer(num1);
        System.out.println(int1.toString());//10

        Integer int2 = new Integer("123");
        System.out.println(int2.toString());//123

          //An exception is reported. The value of the formal parameter of Integer must be a number whether it is String or int
//        Integer in3 = new Integer("123abc");
//        System.out.println(in3.toString());

        Float f1 = new Float(13.0f);
        Float f2 = new Float("13.0f");
        System.out.println(f1);
        System.out.println(f2);

        //In particular, String type parameters of Boolean wrapper class can ignore case, while boolean type parameters cannot
        Boolean b1 = new Boolean(true);
        Boolean b2 = new Boolean("TrUe");
        Boolean b3 = new Boolean("true123");
        System.out.println(b3);//false



        //Wrapper class - > basic data type: call xxxValue() of wrapper class Xxx
        Integer int3 = new Integer(12);
        int i1 = int3.intValue();
        System.out.println(i1);

        Float f3 = new Float(12.3);
        float f4 = f3.floatValue();
        System.out.println(f4);


    }

}

class Difference{
    boolean isBoy;
    Boolean isGirl;
}

JDK5.0 added a new feature: automatic packing and unpacking, which can be used directly in the future.

//Auto packing: basic data type -- > Packing class
int num1 = 10;
Integer int1 = num;//Directly assign the basic data type to the variable of the wrapper class
boolean b1 = true;
Boolean b2 = b1;

//Automatic unpacking: packaging class -- > basic data type
System.out.println(int1.toString());
int num2 = int1;//Directly assign variables of package type to variables of basic data type

The following is the conversion between basic data type, wrapper class and String type

//Basic data type, packing class - > string type
//Mode 1: connection operation
int num2 = 12;
String str1 = num2 + "";
//Method 2: call the valueof (xxxxxx) method of String overload (more commonly used)
float f5 = 12.3f;
String str2 = String.valueOf(f5);//Basic data type to String
Double d1 = new Double(12.4);
String str3 = String.valueOf(d1);//Package class to String
System.out.println(str1 + "\t" + str2 + "\t" + str3);

//String type - > basic data type, wrapper class: call parseXxx(String s) method of wrapper class
//Note: since there is no parseCharacter() method, string - > char and its wrapper class cannot be used,
//You can call charAt() of the String class to get the characters under the specified index of the String
String str4 = "123";
int num3 = Integer.parseInt(str4);
System.out.println(num3 + 1);
//        String str4 = "123abc";
//        int num3 = Integer.parseInt(str4);
//        System.out.println(num3 + 1);
//NumberFormatException exception. The value must be a number and cannot have letters

String str5 = "trUe";
boolean b4 = Boolean.parseBoolean(str5);
System.out.println(b4);
String str6 = "true123";
boolean b5 = Boolean.parseBoolean(str6);
System.out.println(b5);

practice:

//IntegerCache class is defined inside Integer, and one Integer type array cache [] is defined in IntegerCache
//An Integer in the range of - 128 ~ 127 is saved. If the automatic packing method is used, when the value assigned to Integer is in the range of - 128 ~ 127,
//You can directly use the elements in the array without calling the method assignment of the new object.
//Purpose: in order to improve efficiency, you don't have to go to new every time as long as you are within the scope
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j);

Integer m = 1;
Integer n = 1;
System.out.println(m == n);//true

Integer x = 128;
Integer y = 128;
System.out.println(x == y);//false

6. Object oriented programming (Part 2)

6.1 keyword static

static can be used to modify attributes, methods, code blocks and internal classes, but not constructors.

6.1.1 static modifier attribute

The attributes modified by static are called static attributes, or static variables and class variables; Non static modified attributes are non static attributes, or instance variables.

**Instance variable: * * multiple objects are created, and each object independently has a set of non static attributes in the class. When modifying the non static attribute in one object, it will not cause the modification of the attribute value in other objects;

**Static variable: * * multiple objects are created, and all objects share the same static attribute. When a static variable is modified for the next through a certain, it will cause other objects to call this static variable. It is modified.

Local variables are not initialized by default and need to be explicitly initialized (arguments must be initialized before they can be passed to formal parameters).

Description of static modifier attribute:

1. Static variables are loaded with class loading, so they can be loaded directly through class Static variables are called in the form of static variables, so static variables are also called class variables;
2. Calling permission of classes and objects:

Static propertiesNon static method
classyesno
objectyesyes

3. The loading of static variables is earlier than the creation of objects;
4. Since the class is loaded only once, there will only be one copy of the static variable in memory, which exists in the static field of the method area.

public class ChineseTest{
    public static void main(String[] args){
        Chinese c1 = new Chinese();
        c1.name = "Zhang San";
        c1.age = 20;
        c1.nation = "CHN";
        Chinese c2 = new Chinese();
        c2.name = "Li Si";
        c2.age = 30;
        System.out.println(c1.nation + "\t" + c2.nation);

        c2.nation = "China";
        System.out.println(c1.nation + "\t" + c2.nation);

        Chinese.nation = "CHN China";
        System.out.println(c1.nation + "\t" + c2.nation + "\t" + Chinese.nation);
    }
}
class Chinese{
    static String nation;
    String name;
    int age;
}

The operation results are as follows:

The memory parsing code is as follows:

6.1.2 static modification method

1. Similar to static attributes, static methods are also loaded with the loading of classes, so you can also use classes Static method call;
2. Calling permission of classes and objects:

Static methodNon static method
classyesno
objectyesyes

3. In static methods, only static methods or attributes can be called. In non static methods, both non static methods or attributes and static methods or attributes can be called;
4. this and super keywords cannot be used in static methods, because they are object-based, and static methods are loaded with classes, so they are earlier than the creation of objects.

public class Chinese {
    String name;
    int age;
    static String nation;

    public void eat() {
        System.out.println("Chinese people eat Chinese food");
        //Call non static structure
        this.info();
        //Call static structure
        walk();
        System.out.println("nation:" + nation);//Class Classes can be omitted from static properties
    }
    
    public static void show() {
        System.out.println("I am a Chinese!");
        //Non static properties and methods cannot be called
//        eat();
//        name = "Tom";
        //Static structures can be called
        System.out.println(Chinese.nation);
        walk();//Class Classes can be omitted from static methods

    }

    public void info() {
        System.out.println("name:" + name + ", age:" + age);
    }

    public static void walk() {

    }

}

The invocation of static attributes and static methods can be understood from the perspective of life cycle.

Scenario of modifying attributes with static: when attribute values are shared by multiple objects, they will not vary with different objects, and constants in classes are often declared as static;
The scene of modifying a method with static: when a method operates on static attributes, it is usually modified with static;
In addition, the methods in tool classes are usually modified with static to call directly without creating objects, such as Math, Arrays, Collections, etc.

6.1.3 inheritance of static attributes and methods

Static methods and properties can be inherited (because static methods are loaded with the class and are part of the class).
However, non static methods are instances of classes and can be overridden by subclasses to achieve the effect of polymorphism; Static methods belong to classes and cannot be overridden, so they cannot be polymorphic.

If a static method and static attribute with the same name as the parent class are defined in the subclass, the static method or static attribute of the parent class is not overridden but "hidden". The function of rewriting is that after "Rewriting", the priority of the subclass is higher than that of the parent class, but there is no such priority for "hiding". If you want to call the static methods and properties of the parent class, you can use the class directly Property or method.

public class StaticTest {
    public static void main(String[] args) {
        System.out.println(Students.age);//Subclasses call static properties in the parent class
        System.out.println(Students.name);//Subclasses call their own static properties
        Students.eat();//Subclasses call static methods in subclasses
        Students.talk();//The subclass calls the static method in the parent class and inherits

    }
}

class Person{
    static String name = "Person";
    static int age = 1;
    public static void eat(){
        System.out.println("Parent class Person having dinner");
    }
    public static void talk(){
        System.out.println("Parent class Person speak");
    }
}
class Students extends Person{

    //Same attribute name
    static String name = "Students";
    public static void eat(){
        System.out.println("Subclass Students having dinner");
    }
}

The results are as follows:

6.1.4 single case design mode of class

The so-called class singleton design pattern is to take certain methods to ensure that there can only be one object instance of a class in the whole software system, and the class can only provide a method to obtain its object instance.
If you want a class to generate only one object in a virtual machine, you must first set the access permission of the class constructor to private. In this way, you can't create new objects outside the class, but you can still generate objects of this class inside the class.
In addition, since the object of the class cannot be obtained outside the class, it cannot be returned by calling non static methods, so only a static method of the class can be called to return the object created inside the class, and the static method can only access the static member variables in the class (the non static attributes are loaded with the creation of the object), Variables that point to objects of this class generated within the class must also be defined as static.

Here are two ways to experience the single instance design mode of class:
1. Hungry Chinese implementation: the advantage is thread safety (refer to the following multithreading), and the disadvantage is that the object loading time is too long

//Hungry Chinese implementation of singleton mode
public class SingleTonTest1 {
    public static void main(String[] args) {
        Bank bank1 = Bank.getInstance();
        Bank bank2 = Bank.getInstance();
        System.out.println(bank1 == bank2);
    }
}

class Bank{
    //1. Constructor of privatization class
    private Bank(){

    }

    //2. For the object of creating class internally, the object must also be declared as static to be called by static method
    private static Bank instance = new Bank();//Make a good object first, hungry

    //3. Provide public methods to return class objects
    public static Bank getInstance(){
        return instance;
    }
    
}

2. Lazy implementation: the advantage is to delay the creation of objects, while the disadvantage is that the following writing method is unsafe. Thread safety issues

//Lazy implementation of singleton mode
public class SingleTonTest2 {
    public static void main(String[] args) {
        Order order1 = Order.getInstance();
        Order order2 = Order.getInstance();
        System.out.println(order1 == order2);
    }
}

class Order{

    //1. Constructor of privatization class
    private Order(){

    }

    //2. The current object is declared but not initialized
    private static Order instance = null;

    //3. Declare public and static methods to return the current class object
    public static Order getInstance(){
        if(instance == null){
            instance = new Order();//Recreate the object when you use it, lazy
        }
        return instance;
    }
}

6.2 understand the syntax of main method

As the entry of the program, the main method is actually just an ordinary static method. You can create a main method in each class, but you need to choose which class's main method to enter at run time.

6.3 class member 4: code block (rarely used)

{...} Used to initialize classes and objects. If you want to modify them, you can only modify them with static. It is divided into static code block and non static code block according to whether it is modified or not. Multiple static code blocks can be defined inside the class and executed in the order of declaration. But generally, you don't write multiple code blocks, all of which are written in one code block. Function: initializes class or object information. Because the static is loaded with the class and is earlier than the creation of the object, no matter what the declaration order is, the static and non-static must be executed first and then the non-static.

Static code block: there can be output statements inside, which will be executed as the class is loaded. Since the class is loaded only once, it will be executed only once. Only static properties and methods can be called, and non static structures cannot be called.

Non static code block: there can be output statements inside, which are executed with the creation of objects, and are executed once every time an object is created.

static{
    System.out.println("hello, static block-1");
}
static{
    System.out.println("hello, static block-2"); 
}

{
    System.out.println("hello");
}

By parent and child, static first

6.4 keyword final

final can be used to modify classes, methods and variables.

6.4.1 final modification class

The final modifier class indicates that it cannot be inherited by other classes. For example: String class, System class and StringBuffer class.

6.4.2 final modification method

The final modifier indicates that this method cannot be overridden. For example: getClass() of Object class

6.4.3 final modifier variable

After final modifies a variable, the variable at this time is called a constant and cannot be modified.

1.final modifier attribute. The assignment positions that can be considered are: explicit initialization, initialization in code block and initialization in constructor;
2.final modifies a local variable, especially when using final to modify a formal parameter, which indicates that the formal parameter is a constant. When calling this method, assign an argument to the constant formal parameter. Once assigned, this formal parameter can only be used in the method body (because local variables can only be used in the method body), that is, it can only be used and cannot be modified.

public class Something{
    public static void main(String[] args){
        Other o = new Other();
        new Something().addOne(o);
       
    }
    public void addOne(final Other o){
        o.i++;//The compilation passed because only o cannot be modified, but its members are modifiable without final modification        
        //o = new Other();// Compilation failed, O cannot be modified
	}
}
class Other{
    public int i;
}

static final can only be used to modify attributes and methods. When modifying attributes, this attribute is a global constant, indicating that it can only be initialized and cannot be modified, and all objects share this attribute.

6.5 abstract classes and methods (use the keyword Abstract)

6.5.1 abstract classes

You can see that people are the parent class and have multiple subclasses. However, as people continue to be inherited by subclasses, people become more and more abstract, and their subclasses become more and more concrete. Then the parent class will no longer be used when creating objects. The parent class only acts as a base class and sets some basic properties and methods to inherit from the child class. At this point, modify the class with the keyword abstract so that it cannot be instantiated (create an object), and use subclasses to create new objects.

Although the abstract class cannot create a new object, there must be a constructor inside, because the subclass will call the constructor of the parent class in the process of creating the object (instantiation). Therefore, abstract classes are inherited by subclasses, otherwise abstract classes are meaningless.

6.5.2 abstract methods

Similarly, abstract can also modify methods, such as: public abstract void eat();, This method has no method body.

1. "Class" contains sufficient and unnecessary conditions for abstract method "to be" class is abstract class (i.e. must be declared as abstract) ";

2. The subclass can be instantiated only after overriding all abstract methods in the parent class (always remember: the parent class contains direct and indirect parents). If the subclass does not override the abstract method in the parent class, it indicates that the class is an abstract class and needs to be modified with abstract;

3.abstract cannot be used to modify private methods (private methods cannot be accessed by subclasses, and abstract methods must be overridden by subclasses), static methods (because static methods cannot be overridden, or it is not called rewriting, but "hidden"), final methods (final methods cannot be overridden), and final classes (final classes cannot be inherited).

6.5.3 Abstract usage scenarios

for instance:
The parent class will eat, but the sub class people who eat are different, such as sub class workers and students. The reasons for eating more are also different. For example, workers have to eat more when they do hard work, and students have to eat more when they grow up. So when we want to define the reasons for eating more according to different groups, we can write different methods in subclasses.
However, the methods that may need to be written in the future may not only be the reason for eating, but also sleeping and washing your face. If there are many methods, some may be omitted if they are written in the subclass. At this time, if an abstract method is defined in the parent class, if you forget to override an abstract method inherited from the parent class in the subclass, you will be prompted with an error, so that you won't miss it.

public class AbstractTest {
    public static void main(String[] args) {
        Workers worker = new Workers();
        Students students = new Students();
        worker.eat();
        students.eat();
    }
}

abstract class Person{
    abstract public void eat();
}

class Workers extends Person{
    
    @Override
    public void eat(){
        System.out.println("Workers do a lot of heavy work and have to eat more");
    }
}

class Students extends Person{

    @Override
    public void eat() {
        System.out.println("Students should eat more when they are growing up");
    }
}

6.5.4 creating anonymous subclass objects of abstract classes

Similar to anonymous objects, you can also create anonymous subclasses and throw them away once you use them.

public class AbstractTest {
    public static void main(String[] args) {
        Person p = new Person(){
//Instead of creating a class, an anonymous subclass is directly created using polymorphism (because the abstract class Person cannot be instantiated),
//Rewriting methods in unnamed subclasses eliminates the need to write subclasses
            @Override
            public void eat(){
                System.out.println("This is an anonymous subclass that only eats");
            }
        };
        p.eat();
    }
}

abstract class Person{
    abstract public void eat();
}

The results are as follows:

6.6 interface

An interface is a specification. It defines a set of rules, which reflects the idea that if you are / want to..., you must be able to. Inheritance is a yes or no relationship, while interface implementation is a yes or no relationship. In essence, interfaces are contracts, standards and specifications, just like laws. After they are formulated, everyone should abide by them.

1. The interface is defined by interface, which is a parallel structure with the class;
2. * * constructor cannot be defined in the interface! Therefore, the interface can not be instantiated, so it can be used in the way of implements * * through classes** If the implementation class covers all the abstract methods in the interface, the implementation class can be instantiated** If not, the implementation class is still an abstract class and needs to be modified with abstract;
3.Java classes can implement multiple interfaces, making up for the limitation of Java single inheritance. Format: Class AA extensions BB implementations CC, DD, EE;
4. Interfaces can inherit from one interface to another, so polymorphism is also met, and multiple inheritance is also allowed.

The following is the writing method of JDK7 and before:

//JDK7 and before, only global constants and abstract methods can be defined
//Global constant: the attribute of public static final, but it can be omitted when writing
//Abstract method: the method of public abstract, which can also be omitted when writing
public class InterfaceTest{
    public static void main(String[] args){
        System.out.println(Flyable.MAX_SPEED);//Constant of calling interface
        System.out.println(Flyable.MIN_SPEED);
        //Flyable.MIN_SPEED = 2;// An error is reported, and the constant cannot be assigned
        Plane plane = new Plane();
        plane.fly();
    }
}
interface Flyable{
    
    public static final int MAX_SPEED = 7000;//Not omitted
    int MIN_SPEED = 1;//public static final is omitted
    public abstract void fly();
    void stop();//public abstract is omitted
    //Therefore, no matter whether the variable declaration in the interface is modified or not, it must be modified by public static final,
    //Are "static constants that cannot be modified"
    //The same is true for abstract methods. They must be modified with public abstract. They are abstract methods
}

interface Attackable{
    void attack();
}

class Plane implements Flyable{
    public void fly(){
        System.out.println("Take off by engine");
    }
    public void stop(){
        System.out.println("Driver deceleration stop");
    }
}
abstract class Kite implements Flyable{
    //If the methods in the interface are not completely covered, the class must be declared abstract
    public void fly(){
    }
}

class Bullet implements Flyable,Attackable{//Inherit multiple interfaces
    
}

The results are as follows:

JDK8: in addition to defining global constants and abstract methods, you can also define static methods and default methods; (JDK7 and previous writing methods are used more)
1. Static methods defined in the interface can only be called by the interface;
2. The default method defined in the interface can only be called by the object of the implementation class of the interface, and can be rewritten by the implementation class * * (generally, it is not rewritten, but can be used directly, which is just for introduction) * *;

Note: when writing code, you usually don't define methods with the same name and parameters to make trouble for yourself. The following duplicate names are just for introduction.
3. If the method with the same name and parameter is declared in the inherited parent class and the implemented interface of the subclass (or implementation class), the subclass will call the method with the same name and parameter in the parent class by default without overriding this method. - > Class priority principle (for methods);
4. If the implementation class implements multiple interfaces and default methods with the same name and parameters are defined in these interfaces, an error will be reported if the implementation class does not override this method - > that is, interface conflict. If you want to implement this method, you must override this method in the implementation class;

5. If the implementation class overrides the default method in the interface (static methods cannot be overridden), just as the subclass calls the overridden method in the parent class, if you want to call the overridden method in the interface, use the interface name super. Method call.

The following are the new features of JDK8 (making the interface more and more like a class):

//JDK8
public class Interface2{
    public static void main(String[] args) {
        SubClass s = new SubClass();
        //s.method1();// report errors
        //SubClass.method1();// report errors
        //1. The interface calls its own static method
        Interface.method1();//interface: Beijing
        //Interface.method3();// report errors
        System.out.println("**************************************************");

        //2. Object calls default method
        s.method2();//SuperClass: Shanghai
        System.out.println("**************************************************");

        //3. Class priority principle
        s.method2();//SuperClass: Shanghai
        System.out.println("**************************************************");

        //4. The default method of multiple interfaces has the same name
        s.method3();//SubClass: Nanjing
        System.out.println("**************************************************");

        //5. Call the rewritten method in the interface
        s.myMethod();

    }
}
interface Interface {
    public static void method1(){//Static methods can be defined. There are method bodies. They are public by default and can be omitted
        System.out.println("interface: Beijing");

    }

    public default void method2(){//Define the default method. The keyword default is public by default, which can be saved
        System.out.println("interface: Shanghai");
    }

    default void method3(){
        System.out.println("interface: Nanjing");
    }
}

interface Interface11{
    default void method3(){
        System.out.println("interface11: Nanjing");
    }
}

class SuperClass{
    public void method2(){
        System.out.println("SuperClass: Shanghai");
    }
    public void method3(){
        System.out.println("SuperClass: Nanjing");
    }
}

class SubClass extends SuperClass implements Interface,Interface11{
    public void method3(){
        System.out.println("SubClass: Nanjing");
    }

    public void myMethod(){
        method3();//Call overridden method
        super.method3();//Call the method declared in the parent class

        //Call the default method in the interface
        Interface.super.method3();
        Interface11.super.method3();

    }
}

Similarly, interfaces can also achieve polymorphism

/**
 * Interface polymorphism (similar to class)
 */
public class Application {
    public static void main(String[] args) {
        Computer com = new Computer();
        Udisk udisk = new Udisk();
        com.transferData(udisk);
        System.out.println();
        Printer printer = new Printer();
        com.transferData(printer);
    }
}

class Computer{
    public void transferData(USB usb){
        usb.start();
        System.out.println("Details of specific transmission data");
        usb.stop();
    }
}

interface USB{
    //Constant: define size, ship speed, etc
    //Method: define working mode, etc
    void start();
    void stop();
}
class Udisk implements USB{

    @Override
    public void start() {
        System.out.println("U Disc opening operation");
    }

    @Override
    public void stop() {
        System.out.println("U Disk end work");
    }
}
class Printer implements USB{

    @Override
    public void start() {
        System.out.println("Printer on");
    }

    @Override
    public void stop() {
        System.out.println("Printer finished working");
    }
}

Summarize the similarities and differences between abstract classes and interfaces:
Similarities: all cannot be instantiated and can be inherited;
Difference: abstract classes have constructors, but constructors cannot be declared inside interfaces; Abstract classes can only be inherited by single, and interfaces can be inherited by multiple

6.7 category 5: internal category (hardly used)

Java allows a Class A to be declared in class B, then class A is the inner class, and class B is called the outer class.

1. Internal class classification: member internal class and local internal class (within method, code block and constructor)

2. Member internal class:
① On the one hand, as a member of an external class: call the structure of the external class; Can be modified by static; Can be modified by four permission modifiers;
② On the other hand, as a class: attributes, methods, constructors, etc. can be defined in the class; Can be modified by final, indicating that this class cannot be inherited; Can be modified by abstract.

public class InnerClassTest {
    public static void main(String[] args){

        //Create a Dog instance (internal class of static member)
        Animal.Dog dog = new Animal.Dog();//The internal class is called by the external class as a structure, and then the object is created
        dog.show();//Object calling method of inner class

        //Create Bird instance (non static member inner class)
        //Static member inner classes can be called directly by outer classes to create objects
        //The non static member inner class must first create an object and call the object by calling the inner class through the object
        Animal a = new Animal();
        Animal.Bird bird = a.new Bird();//a.new Bird() calls the constructor of the inner class through the object
        bird.sing();
        bird.display("Small animals");
    }
}

class Animal{
    String name = "Small animals";
    int age;

    public void eat(){
        System.out.println("having dinner");
    }

    //Static member inner class
    static class Dog{
        String name = "puppy";
        int age;
        public void show(){
            System.out.println("Dog having dinner");
            //eat();// Wrong, static cannot be adjusted, non static
        }
    }

    //Non static member inner class
    class Bird{
        String name = "Bird";
        int age;
        public Bird(){

        }
        public void sing(){
            System.out.println("I am a little bird");
            eat();//Call the non static attribute of the external class, and omit animal by default this.
        }

        //
        public void display(String name){
            System.out.println(name);//Call parameter
            System.out.println(this.name);//Call the properties of the inner class of the formal parameter Bird
            System.out.println(Animal.this.name);//Call the properties of the Animal external class
        }
    }

}

3. Local internal classes are generally written inside methods. The common writing methods are as follows:

//Returns an object of a class that implements the Comparable interface
public Comparable getComparable(){
    
    //Create a class that implements the Comparable interface: a local inner class
    class MyComparable implements Comparable{
        //Override compareTo(Object o) in the Comparable interface
        @Override
        public int compareTo(Object o){
            return 0;
        }
    }
    return new MyComparable();
}

Bytecode files will be generated for both member internal classes and local internal classes after compilation. The file lattice name is as follows:
Member inner class: outer class \ $inner class name class
Local internal class: external class $numeric internal class name class

7. Exception handling

7.1 exception overview and exception architecture

In the process of using computer language model project development, even if the programmer's code is perfect, there will still be some problems in the operation of the system, because many problems can not be avoided by code, such as the format of user input data, whether the read file exists, whether the network remains unobstructed, and so on.

In the Java language, abnormal conditions occurring in program execution are called exceptions (syntax errors and logic errors are not exceptions). Exceptions during execution can be divided into Error and Exception.

Error: a serious problem that cannot be solved by the Java virtual machine. Such as: JVM system internal error, resource exhaustion and other serious situations. For example: StackOverFlow and OOM. Generally, targeted code is not written for processing.

Exception: other general problems caused by programming errors or accidental external factors can be handled with targeted code. For example: null pointer access, trying to read a file that does not exist, network connection interruption, array subscript out of bounds, etc.

Common runtime exceptions are as follows:

Exception typeAbnormal cause
NullPointerException (null pointer exception)Call an object with null value
IndexOutOfBoundException (index out of bounds exception)Out of index range
ClassCastException (type conversion exception)Type cast is not inherently convertible
NumberFormatException (number format exception)An exception occurred while converting a value type related
Inputmismatch exception (input type mismatch exception)The input type does not match the type of the given variable
ArithmeticException()Violation of mathematical operation, such as division by 0, square of negative number, etc

7.2 exception handling

The so-called exception handling is to hide the possible exception errors in a way and replace them with more friendly exception tips. For example, garbled code, flash back and other situations are replaced by text prompts, but the exception is not solved in essence. To resolve the exception, you can only modify the code.

7.2.1 exception handling: grab and throw model

Process 1 (throwing): once an exception occurs during the normal execution of the program, an object corresponding to the exception class will be born in the code and thrown. Once the object is thrown, the subsequent code is no longer executed.
Process 2 (CATCH): it can be understood as the exception handling method: ① try catch finally ② throws

7.2.2 exception handling mechanism 1: try catch finally

try{
    //Possible exception codes
    //Code after possible exception
}catch(Exception type 1 variable name 1){
    //How to handle exceptions 1
    //Code after possible exception
}catch(Exception type 2 variable name 2){
    //How to handle exceptions 2
    //Code after possible exception
}catch(Exception type 3 variable name 3){
    //How to handle exceptions 3
    //Code after possible exception
}
...

finally{
    //Code that must appear
}

1. Use try to package the possible exception code. Once an exception occurs during execution, an object corresponding to the exception class will be generated. According to the type of this object, match it in catch;
2. When a catch is matched, it will enter the catch for exception handling. Once the processing is completed, jump out of the current try catch structure (without writing finally) and continue to execute the subsequent code;
3. If the exception type in catch has no child parent relationship, the declaration order has no relationship; If yes, the subclass must be declared on the parent class, otherwise an error will be reported;
4. Two common methods for handling exceptions: ① String getMessage() ② void printStackTrace()
5. Variables declared in the try structure cannot be called after the try structure is out;
6. Try catch finally structures can be nested with each other (but generally they will not be nested when writing code);

7.finally is optional (can be written or not);
8.finally, after exception handling, it will be executed. If there is a return statement during exception handling, it will still execute finally first, and then execute the return statement; If there is a return statement inside finally, the return statement after finally is executed will end, and the return statement after catch will no longer be executed;
9. Resources such as database connection, input / output stream and network programming Socket cannot be recycled automatically by the JVM, and resources need to be released manually. At this time, the resource release needs to be declared in finally.

About compile time and run-time exceptions in Code:
1. Using try catch finally to handle compile time exceptions is equivalent to delaying the exceptions that may occur during compilation until they occur at run time.
2. Since runtime exceptions are common, try catch finally is usually not written for runtime exceptions. For compile time exceptions, you must consider exception handling.

import org.junit.Test;

public class ExceptionHandle {

    @Test
    public void test1(){
        String str = "abc";
        try{
            int num = Integer.parseInt(str);
            System.out.println("hello----1");//After an exception occurs, the following statements will not be executed again
        }catch(NullPointerException e){
            System.out.println("There is a null pointer exception. Don't worry");
        }catch (NumberFormatException e){
            System.out.println(e.getMessage());
//            System.out.println("in case of abnormal value conversion, don't worry");
        }
        System.out.println("hello----2");
    }

    @Test
    public static int test2(){

        try {
            int a = 10;
            int b = 0;
            System.out.println(a / b);
        }catch (ArithmeticException e){
            e.printStackTrace();
            return 1;
        }catch (Exception e){
            e.printStackTrace();
            return 2;
        }finally {
            System.out.println("Invincible most lonely");
        }
        return 0;
    }
    public static int test3(){

        try {
            int a = 10;
            int b = 0;
            System.out.println(a / b);
        }catch (ArithmeticException e){
            e.printStackTrace();
            return 1;
        }catch (Exception e){
            e.printStackTrace();
            return 2;
        }finally {
            System.out.println("Invincible most lonely");
            return 3;
            //If you add a return statement inside finally,
            //Then the return statement after catch will not be executed, and the method ends here
        }
    }
    public static void main(String[] args) {
        int num2 = test2();
        int num3 = test3();
        System.out.println(num2);
        System.out.println(num3);
    }
}

The results are as follows:

7.2.3 exception handling mechanism 2: throws

1. "Throws + exception type" is declared at the declaration of the method, indicating the type of exception that may be thrown when the method is executed. For example: public void method() throws IOException {} Once an exception occurs during the execution of the method body, an object of exception class will still be generated at the generation of exception code. When this object meets the exception type after throws, it will be thrown. The code behind the exception code will no longer be executed!

2. Try catch finally really handles the exception. Throws just throws the exception to the caller of the method, and does not really handle the exception.

3. The exception thrown by the subclass overriding method cannot be greater than the exception of the overridden method of the parent class. For example, if the method overridden by the parent class does not throw an exception, the overridden method in the child class cannot throw an exception.

7.2.4 selection of exception handling

If there is no override of the throw - catch method in the parent class, the override of the throw - catch method in the child class must also be used. If there is no override of the throw - catch method in the parent class, it means that the exception can not be handled by the throw - catch method

2. Among the executed methods, several other methods are called successively. If these methods are executed in a progressive relationship, these methods can be processed in the way of throws, and the executed methods can be processed in the way of try catch finally.

7.3 exception thrown manually: throw

In the "grasping and throwing model", there are two ways to automatically generate objects in case of exceptions:
1. The system automatically generates exception objects
2. Manually generate an exception object and throw it

public class ThrowTest {
    public static void main(String[] args) {
        try {
            Student s = new Student();
            s.register(-1001);
            System.out.println(s);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

class Student {
    private int id;

    public void register(int id) throws Exception {
        //Declare the possible exception types and handle them for the caller
        if (id > 0) {
            this.id = id;
        } else {
			//throw new RuntimeException("the data you entered is illegal!");
            //Run times an exception and throw an object of RuntimeException class
            throw new Exception("The data you entered is illegal!");//Object that throws an Exception class
        }
    }
}

The results are as follows:

7.5 user defined exception class

How to customize exception classes?
Answer: 1 Inherited from the existing Exception structure: RuntimeException, Exception
2. Provide global constant: serialVersionUID
3. Provide overloaded constructor

public class CustomException extends RuntimeException{
    static final long serialVersionUID = -7034897190745766939L;
    public CustomException(){

    }
    public CustomException(String msg){

    }
}

8. Multithreading

8.1 basic concepts: program, process and thread

program: a set of instructions written in a certain language to complete a specific task, that is, a piece of static code and static object.

Process: an execution process of a program, or a running program. It is a dynamic process, with its own emergence, existence and extinction process. For example: QQ, wechat and video player in operation. The program is static (not running), while the process is dynamic (running). In addition, as the unit of resource allocation, the system will allocate different memory areas for each process at run time.

Thread: a thread is an executable process.
① If a process executes multiple threads in parallel at the same time, the process supports multithreading.
② As a unit of scheduling and execution, each thread has an independent running stack and program counter (PC), and the overhead of thread switching is small.
③ Multiple threads in a process share the same memory unit (heap and method area) – > they allocate objects from the same heap and can access the same variables and objects. This makes the communication between threads easier and more efficient. However, the shared system resources operated by multiple threads may bring security risks.

Parallel: multiple CPU s execute multiple tasks at the same time. For example: many people do different things at the same time
Concurrency: one CPU "performs multiple tasks at the same time" (actually fast switching), such as second kill and multiple people doing the same thing

Taking the single core CPU as an example, although the CPU can execute multiple threads concurrently, the essence of concurrent execution is to constantly switch execution between multiple threads, and the switching time is relatively long, so it is faster to use a single thread to complete multiple tasks successively (call multiple methods) than to use multiple threads. If so, why do you still need multithreading?
Answer: 1 Improve the user experience. For example, multithreading can enable users to type while listening to music;
2. The utilization of CPU is improved. Because the CPU is constantly switching execution threads, there is no waste of idle time;
3. Improve the program structure, which can divide the long and complex process into multiple threads and run independently, which is conducive to understanding and modification.

When do I need multithreading?
Answer: 1 The program needs to perform two or more tasks at the same time;
2. When the program needs to realize some tasks that need to wait, such as user input, file reading and writing operation, network operation, search, etc;
3. When you need some programs running in the background.

8.2 creation and use of threads

8.2.1 create Thread through Thread class

The creation of multithreading, method 1: inherit from the Thread class
1. Create a subclass inherited from Thread class
2. Override run() of Thread class
3. Create subclass objects of Thread class
4. Call start() through this object: ① start the currently created thread ② call run() of the currently created thread

public class ThreadTest {
    public static void main(String[] args) {
        //3. Create subclass objects of Thread class
        MyThread t1 = new MyThread();
        //4. Call start() through this object: ① start the current thread 	 ② Call the run() of the current thread
        t1.start();
        //Problem 1: calling run() directly cannot start the thread
        //t1.run();

        //Problem 2: start another thread and traverse the even number within 100
//        t1.start();
        //The exception IllegalThreadStateException is reported, so the thread that has started () cannot be executed
        
        //We need to recreate a thread object
        MyThread t2 = new MyThread();
        t2.start();

        //The following operations are still performed in the main thread
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.println("**********main**********");
            }
        }
    }
}

//1. Create a subclass inherited from Thread class
class MyThread extends Thread {
    //2. Override run() of Thread class
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.println(Thread.currentThread().getName() + 
                                   ": " + i + "**********main**********");
            }
        }

    }
}

8.2.2 common methods in thread class

1.start(): start the currently created thread and call the run() of the current thread
2.run(): you usually need to override this method in the Thread class and declare the operation to be performed by the created Thread in this method
3.currentThread(): a static method that returns the thread executing the current code
4.getName(): get the name of the current thread
5.setName(): sets the name of the current thread
6.yield(): release the execution right of the current thread and give the execution opportunity to the thread with the same or higher priority, but it is possible to assign the execution right to the current thread at the next moment. If there are no threads with the same or higher priority, this method is ignored
7.join(): join () in thread a calling thread b. At this point, thread a enters a blocking state until thread b is fully executed, and thread a ends the blocking state. Unlike yield(), the priority of thread a and thread b will not affect join()
8. Sleep (long duration): make the current thread "sleep" for milliseconds. Within the specified milliseconds, the current thread is blocked. Since this method will automatically throw an exception, it is generally used to wrap the method with try catch to handle the exception.
9.isAlive(): judge whether the current thread is still alive

class HelloThread extends Thread {


    public HelloThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                try {
                    sleep(10);
                    //After a delay of 1ms, if the CPU allocates resources after 1s, the following code will be executed. If no resources are allocated, it will not be executed
                  //sleep() will throw an interrupt exception when calling, but you can't throw an exception here. You can only try catch to handle exceptions
                    //Because the run() of the parent Thread class does not throw an exception, the overriding method of the child class cannot throw an exception
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }
        }
    }
}

public class ThreadMethod {
    public static void main(String[] args) {

        //Name the Thread through one of the constructors of the Thread class
        HelloThread helloThread = new HelloThread("Thread1");
        //Name the thread through setName()
//        helloThread.setName("thread 2");
        helloThread.start();
        //Note that to start another Thread, you must create an object (an object of the Thread class or subclass of the Thread),
        //Otherwise, an exception will be thrown because an object can only start one thread (that is, call a start())

        System.out.println(helloThread.isAlive());

        //Name the main thread
        Thread.currentThread().setName("Main thread");
        for (int i = 0; i < 100; i++) {
            if (i % 2 != 0) {
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }
            if(i == 19){
                try {
                    helloThread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println(helloThread.isAlive());
        //false, the Thread thread dies after the call
        System.out.println(Thread.currentThread().isAlive());
        //true, the main thread is still alive before the end of main()
    }
}

8.2.3 thread scheduling

The thread scheduling method in Java is: threads with the same priority form a first in first out queue, and use the time slice strategy. For high priority, use the preemptive strategy of priority scheduling. The high priority thread will preempt the execution right of the low priority thread CPU. However, only in terms of probability, the high priority thread is executed with high probability, which does not mean that the low priority thread will execute only after the high priority thread is executed.

The following three constants are the priority level (priority value) of the Thread defined in the Thread class:
1.MAX_PRIORITY: 10
2.MIN_PRIORITY: 1
3.NORM_PRIORITY: 5

You can return the Thread priority value through getPriority() of Thread class, and setPriority(int priority) can change the Thread priority.

8.3 create thread through runnable interface

Multithreading is created in two ways: the Runnable interface is implemented
1. Create a class that implements the Runnable interface
2. Implement the class to implement the abstract method in Runnable: run()
3. Create an object that implements the class
4. Pass this object as a parameter to the constructor of Thread class (the formal parameter of the constructor is of runnable interface type, and the polymorphism of the interface is used here) and create the object of Thread class
5. Call start() through the object of Thread class

//1. Create a class that implements the Runnable interface
class MThread implements Runnable {
    private int variable = 0;

    //2. Implement the class to implement the abstract method in the Runnable interface: run()
    @Override
    public void run() {
        System.out.println(variable);
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }
        }
    }
}

public class ThreadTest2 {
    public static void main(String[] args) {
        //3. Create an object that implements the class
        MThread mThread = new MThread();
//
//        //4. Pass this object as a parameter to the constructor of Thread class to create the object of Thread class
//        //Create the Thread object through a constructor of Thread, public Thread(Runnable target) {}
//        //The formal parameters of the constructor use the runnable interface type, which also reflects the polymorphism of the interface (that is, the objects of any implementation class of the interface can be passed to the formal parameters)
//        Thread t1 = new Thread(mThread);

        //You can also merge steps 3 and 4 directly to create anonymous objects that implement classes
        //Thread t1 = new Thread(new MThread());

        Thread t1 = new Thread(mThread);
        //5. Call start() through the object of Thread class
        t1.setName("Thread1");
        t1.start();

        //Create another thread
        Thread t2 = new Thread(mThread);
        t2.setName("Thread2");
        t2.start();

        //t1 and t2 threads share the private int variable in the implementation class,
        //Because the incoming formal parameters are mthread objects of mthread type, the printed values are consistent

    }
}

Generally, priority is given to "how to implement runnable interface" to create threads. Because the implementation method does not have the limitation of single inheritance of classes, and the implementation method is more suitable to deal with the situation that multiple threads share data.

The connection between the two methods of creating threads: both methods need to override run(), and declare the logic to be executed by the thread in run()

8.4 thread life cycle

Java uses the objects of Thread class or its subclasses to represent threads. In a complete declaration cycle, Java usually experiences the following five states:
1. New: when the object of a Thread class or its subclass is declared and created, the new Thread object is in the new state;
2. Ready: after the thread in the new state is started (), it will enter the thread queue and wait for the CPU time slice. At this time, it has met the running conditions, but it has not been allocated to CPU resources;
3. Run: when the ready thread is scheduled and obtains CPU resources, it enters the running state. run() defines the operation and function of the thread;
4. Blocking: in a special case, when it is considered to hang or perform input and output operations, give up the CPU and temporarily suspend its own execution to enter the blocking state;
5. Death: the thread has completed all its work, or the thread is forcibly suspended or terminated due to an exception.

8.5 thread synchronization

Example: create three windows to sell tickets, and the total number of tickets is 100
1. Problem: in the process of buying tickets, there are problems of duplicate tickets and wrong tickets, which is the problem of thread safety.
2. The reason is that when a thread operates the ticket and the operation has not been completed, other threads participate and operate the ticket.

/**
 * 3 Window ticket selling (involving thread safety)
 * @author yangzhen
 * @create 2021-03-17 10:51
 */
public class SellTicket {
    public static void main(String[] args) {
        Window window = new Window();

        Thread thread1 = new Thread(window);
        Thread thread2 = new Thread(window);
        Thread thread3 = new Thread(window);
        thread1.setName("Window 1");
        thread2.setName("Window 2");
        thread3.setName("Window 3");

        thread1.start();
        thread2.start();
        thread3.start();
    }
}

class Window implements Runnable{
    private int ticket = 100;//The total number of votes left in the three windows, and the ticket is shared by three Thread type objects

    @Override
    public void run() {
        while(true){
            if(ticket > 0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + 
                                   "Ticket No.:" + ticket);

                ticket--;
            }else{
                break;
            }
        }
    }
}

The results are as follows:

3. How to solve: in Java, thread safety is solved through synchronization mechanism. That is, when thread a is operating a ticket, other threads cannot participate. No other thread can operate the ticket until thread a has finished operating the ticket. In this way, even if thread a is blocked, it cannot be changed.

8.5.1 thread synchronization mode 1: synchronize code blocks

//synchronized(* / * synchronized monitor * /){
//	//Code to be synchronized
//}
//explain:
//1. The code that operates the shared data is the code that needs to be synchronized
//2. Shared data: variables operated by multiple threads. For example, ticket will share data.
//3. Synchronous monitor: commonly known as "lock". The object of any class can act as a lock. Requirement: multiple threads must share the same lock (object). If the lock is not the same lock, the problem of wrong ticket and duplicate ticket will still occur.
//The two methods of creating threads must use the same lock to solve the thread safety problem.
//How to create the lock: 1 The way of inheritance is to set the lock of the subclass to a static object;
//2. The implementation method is as long as the implementation class is declared as an object (lock) (the following is synchronization in the implementation interface)

//Modify the previous Window class
class Window implements Runnable {
    private int ticket = 100;//The total number of votes left in the three windows, and the ticket is shared by three Thread type objects
    Object obj = new Object();
    @Override
    public void run() {
        while (true) {
            synchronized (obj) {//synchronized(this) {is also OK, as long as it is the same object
                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + 
                                       "Ticket number:" + ticket);

                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}

The way of synchronization solves the problem of thread safety. However, when operating synchronous code, only one thread can participate and other threads wait, which is equivalent to a single threaded process with long execution time. Nevertheless, it is better to sacrifice time than solve thread safety problems.

Method 2.8.5: process synchronization

If the code that operates on shared data is completely declared in a method, this method can be declared synchronous.
In fact, the synchronization method still involves the synchronization monitor, but there is no need to explicitly declare:
1. Non static synchronization method. The synchronization monitor is the current object of this class;
2. Static synchronization method. The synchronization monitor is the current class itself.

Solve the thread safety problem of lazy writing in singleton mode

class Order{
    private Order(){}
    
    private static Order instance = null;
    
    //Synchronization method to solve thread safety
    private static synchronized Order getInstance(){
        if(instance == null){
            instance = new Order;
        }
        return instance;
    }
    
    //Synchronous code block to solve thread safety
    /*private static Order getInstance(){
        if(instance == null){
            synchronized(Order.class){
            	if(instatnce == null){
                	instance = new Order();
            	}
        	}
        }
        return instance;
    }*/
}

8.5.3 thread deadlock

Different threads occupy the synchronization resources needed by the other party and do not give up. They are waiting for the other party to give up the synchronization resources they need, forming a deadlock. After a deadlock occurs, there will be no exception or prompt, but all threads are blocked and cannot continue. Therefore, when using thread synchronization, deadlock should be avoided.

/**
 * Demonstrate thread deadlock
 *
 * @author yangzhen
 * @create 2021-03-17 15:51
 */
public class DeadLock {
    public static void main(String[] args) {
        StringBuffer s1 = new StringBuffer();
        StringBuffer s2 = new StringBuffer();
        new Thread() {
            @Override
            public void run() {
                synchronized (s1){
                    s1.append("a");
                    s2.append("1");

                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    synchronized (s2){
                        s1.append("b");
                        s2.append("2");
                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }.start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (s2){
                    s1.append("c");
                    s2.append("3");
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    synchronized (s1){
                        s1.append("d");
                        s2.append("4");
                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }).start();
    }
}

The results are as follows:

In order to avoid deadlock, try to reduce the definition of synchronous resources (don't define synchronized, it's not a panacea), and try to avoid nesting (if there is too much nesting, the clearer ideas will be confused). In addition, there are special algorithms and principles, which are left to other places for understanding and will not be introduced here for the time being.

8.5.3 thread synchronization mode 3: Lock lock (new in JDK5.0)

Still take ticket sales as an example:

/**
 * By means of Lock lock
 */
class Window implements Runnable {
    private int ticket = 100;//The total number of votes left in the three windows, and the ticket is shared by three Thread type objects

    //Using the Reetrantlock class
    private ReentrantLock lock = new ReentrantLock(true);//The default is false without parameters

    @Override
    public void run() {
        while (true) {
            try {
                //Call the lock method lock()
                lock.lock();
                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + 
                                       "Ticket number:" + ticket);
                    ticket--;
                } else {
                    break;
                }
            } finally {
                //Call the unlock method unlock()
                lock.unlock();
            }
        }
    }
}

What are the similarities and differences between synchronized and lock?
Answer: 1 Same: both can solve thread safety problems
2. Difference: the synchronized mechanism automatically releases the synchronization monitor (lock) after executing the completely corresponding synchronization code; Lock needs to manually call lock() to start synchronization and unlock() to finish synchronization

Priority of thread synchronization in 3 ways:
lock - > synchronization code block (it has entered the method body and allocated corresponding resources) - > synchronization method (outside the method body)

8.6 thread communication

Thread communication involves three methods:
wait(): once this method is executed, the current thread will enter the blocking state and release the synchronization monitor;
notify(): once this method is executed, a thread wait ing will be awakened. If multiple threads are wiat, wake up the thread with high priority;
notify(): once this method is executed, all threads will wake up.

/**
 * Communication between threads: use two threads to print 1 ~ 100 Thread 1 and thread 2 print alternately
 *
 * @author yangzhen
 * @create 2021-03-19 10:14
 */
public class Communication {
    public static void main(String[] args) {
        Number number = new Number();
        Thread t1 = new Thread(number);
        Thread t2 = new Thread(number);

        t1.setName("Thread 1");
        t2.setName("Thread 2");

        t1.start();
        t2.start();
    }
}

class Number implements Runnable {
    private int number = 1;

    @Override
    public void run() {
        while (true) {
            synchronized (this) {
                //If the caller is an object created, such as Object obj,
                //Then obj must be added when calling below, otherwise the current object of this will be called by default

                //The caller defaults to this
                notify();//Wake up other threads with high priority, and notifyAll() wakes up all threads
                if (number <= 100) {

                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + ": " + number);
                    number++;
                    try {
                        //The thread that this calls wait() enters the blocking state
                        wait();//wait() throws an exception
              //Once wait() is executed, the thread enters the block and releases the lock; After sleep() is executed, the lock will not be released when the thread enters the block
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    break;
                }
            }
        }
    }
}

explain:
1.wait(), notify() and notifyall() methods must be used in the synchronization code block or synchronization method;

2.wait(), notify(), and notifyall() methods must be synchronization code blocks or synchronization monitors in synchronization methods. Otherwise, an IllegalMonitorStateException will appear:

3.wait(), notify(), and notifyall() are defined in Java Lang. object class

What are the similarities and differences between sleep() and wait()?
Answer: 1 The same point: once the method is executed, the current thread can enter the blocking state
2. Differences: ① the positions of the two method declarations are different: sleep() is declared in Thread class and wait() is declared in Object class
② The requirements for calling are different: sleep() can be used in any required scenario, while wait() must be used in synchronous code blocks or synchronous methods
③ About whether to release the synchronization monitor: if both methods are used in the synchronization code block or synchronization method, sleep() will not release the lock, and wait() will release the lock

The classic producer consumer questions are as follows:

/**
 * Classic application of thread communication: Producer / consumer problem
 * The producer gives the product to the clerk,
 * The customer takes the product from the clerk, who can only hold a fixed number of products (such as 20) at a time,
 * If the producer tries to produce more products, the clerk will ask the producer to stop and inform the producer to continue production when there is an empty space in the store,
 * If there is no product in the store, the clerk will tell the consumer to wait, and then inform the consumer to take the product when there is a product in the store.
 * <p>
 * analysis:
 * 1.Is it a multithreading problem? Yes, producer thread, consumer thread
 * 2.Is there shared data? Yes, clerk (or product)
 * 3.How to solve thread safety problems? Synchronization mechanism, there are three methods
 * 4.Is thread communication involved? yes
 *
 * @author yangzhen
 * @create 2021-03-19 11:13
 */
class Clerk {
    private int productCount = 0;

    public synchronized void produceProduct() {
        if (productCount < 20) {//Start production when the total number of products is no more than 20
            productCount++;
            System.out.println( Thread.currentThread().getName() + 
                               ": Production in progress" + productCount + "Piece product");
            notify();//Wake up consumer thread consumption
            // Because the consumer thread only enters the blocking state and releases the lock when the product is 0, the wake-up here is effective only when the product is 0
            // Other times, because the consumer thread is not blocked, there is no wake-up. It is invalid to call notify()
        } else {//When the total number of products is higher than 20, let the producer stop production and call wait() to enter the blocking state until the consumer wakes up when consuming the product
            try {
                wait();//Block and release the lock and wait for wake-up
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

    public synchronized void consumeProduct() {

        if (productCount > 0) {//When there are products, consumers begin to consume products
            System.out.println( Thread.currentThread().getName() + ": Consuming item" + productCount + "Piece product");
            productCount--;
            notify();//Wake up producer thread
            // Since the producer thread only enters the blocking state and releases the lock when the product is higher than 20, the wake-up here is effective only when the product is 20
            // Other times, because the producer thread is not blocked, there is no wake-up. It is invalid to call notify()
        } else {//Wait until the producer enters the production state, and the consumer wakes up when the product is not used
            try {
                wait();//Block and release the lock and wait for wake-up
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

}

class Producer extends Thread {//producer
    private Clerk clerk;

    public Producer(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        System.out.println(getName() + "Start production...");
        while(true){//Continue to produce until it is finished manually
            clerk.produceProduct();
            try {
                Thread.sleep(10);//Time is set here to make production faster than consumption
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Consumer extends Thread {
    private Clerk clerk;

    public Consumer(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        System.out.println(getName() + "Start consuming products...");
        while(true){//Continue to consume until it ends manually
            clerk.consumeProduct();
            try {
                Thread.sleep(20);//Time is set here to make consumption slower than production
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class ProducerAndConsumer {

    public static void main(String[] args) {
        Clerk clerk = new Clerk();
        Producer p1 = new Producer(clerk);
        p1.setName("Producer 1");
        Consumer c1 = new Consumer(clerk);
        c1.setName("Consumer 1");

        p1.start();
        c1.start();

    }
}

8.7 JDK5.0 added 2 thread creation methods

8.7.1 create thread through Callable interface

The steps are as follows:
1. Create an implementation class that implements the Callable interface
2. Implement call() and declare the operation to be executed by this thread in call()
3. Create an object of the Callable interface implementation class
4. Pass the Callable interface implementation class object to the FutureTask constructor to create the FutureTask object
5. Pass the FutureTask object as a parameter to the constructor of the Thread class, create the Thread() object, and call start()

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * Multi thread creation, method 3: implement Callable interface -- > JDK 5.0 NEW
 *
 * @author yangzhen
 * @create 2021-03-19 13:57
 */

//1. Create an implementation class that implements the Callable interface
class NumTest implements Callable {
    //2. Implement call() and declare the operation to be executed by this thread in call()
    @Override
    public Object call() throws Exception {
        int sum = 0;
        for (int i = 1; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.println(i);
                sum += i;
            }
        }
        return sum;//Automatic boxing. Integer class is a subclass of Object class, which is polymorphic
    }
}

public class ThreadTest3 {
    public static void main(String[] args) {
        //3. Create an object of the Callable interface implementation class
        NumTest numTest = new NumTest();

        //4. Pass the Callable interface implementation class object to the FutureTask constructor to create the FutureTask object
        FutureTask futureTask = new FutureTask(numTest);

        //5. Pass the FutureTask object as a parameter to the constructor of the Thread class, create the Thread() object, and call start()
        new Thread(futureTask).start();

        try {
            //The return value of get() is the return value of the call() method overridden by the Callable implementation class of the FutureTask constructor formal parameter
            Object sum = futureTask.get();
            System.out.println("The sum is:" + sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }

}

Callable is more powerful than Runnable:
1. Compared with the run() method, it can have a return value
2. The method can throw an exception
3. Support the return value of generics (refer to generics later)
4. You need to use FutureTask class to get the returned results, for example

8.7.2 creating threads through thread pool (most commonly used)

The frequent creation and destruction of threads and the use of particularly large resources, such as threads in concurrency, have a great impact on performance.
If you create multiple threads in advance and put them into the thread pool, you can get them directly when you use them, and put them back into the pool after use, you can avoid frequent creation and destruction of threads and realize reuse. Similar to public transport in life.

Steps:
1. Provide a thread pool with a specified number of threads
2. To execute the operation of the specified thread, you need to provide an object that implements the Runnable interface or Callable interface implementation class
3. Close the connection pool

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Multi thread creation method 4: use thread pool (most commonly used) - > JDK 5.0 NEW
 *
 * @author yangzhen
 * @create 2021-03-19 14:31
 */

class number1 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {
            if (i % 2 != 0) {//Print odd
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        }
    }
}
class number2 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {
            if (i % 2 == 0) {//Print even numbers
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        }
    }
}

public class ThreadTest4 {

    public static void main(String[] args) {
        //1. Provide a thread pool with a specified number of threads
        ExecutorService service = Executors.newFixedThreadPool(10);

        //Set properties of thread pool
        //Since ExecutorService is an interface and there are only constants in the interface, it is strongly converted to ThreadPoolExecutor class
//        ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
//        service1.setCorePoolSize(10);
//        service1.setMaximumPoolSize(120);



        //2. To execute the operation of the specified thread, you need to provide an object that implements the Runnable interface or Callable interface implementation class
        service.execute(new number1());//execute() is suitable for Runnable
        service.execute(new number2());//execute() is suitable for Runnable
//        service.submit();//submit() is suitable for Callable

        //3. Close the connection pool
        service.shutdown();

    }
}

Benefits of using thread pools:
1. Increase the corresponding speed (reduce the time to create new threads)
2. Reduce resource consumption (reuse threads in the thread pool and do not need to be created every time)
3. It is convenient for thread management: corePoolSize (the size of the core pool), maximumPoolSize (the maximum number of threads), keepAliveTime (how long does the thread last when there is no task)

9. Common Java classes

9.1 string related classes

9.1.1 characteristics of string

1.String is declared as final, indicating that it cannot be inherited;
2.String implements the Serializable interface, indicating that the string supports serialization; Stirng implements the Comparable interface, which means that the string can be compared in size;
3. final char[] value is defined inside string to store string data;

4.String stands for immutable character sequence, abbreviated as "immutability":
① When the heap string is re assigned, the assignment of the specified memory area needs to be rewritten, and the original value assignment cannot be used;
② When connecting an existing string, you also need to assign a value to the memory area again, and the value will not be assigned to the original value value;
③ When calling the replace() method of String to modify a character or String, you must also reassign the area assignment;

5. Assign a value to a string by literal means (different from new). At this time, the string value is declared in the string constant pool. Characters with the same content will not be stored in the string constant pool.

@Test
public void test1(){
    String s1 = "abc";//Definition of literal quantity
    String s2 = "abc";
    System.out.println(s1 == s2);//Compare the address values of s1 and s2
    s1 = "hello";
    System.out.println(s1);
    System.out.println(s2);

    System.out.println("*************************");

    String s3 = "abc";
    s3 +="def";
    System.out.println(s3);//abcdef
    System.out.println(s2);//abc, which means that instead of adding def after "abc", the value "abcdef" is re assigned in the constant pool

    System.out.println("*************************");
    String s4 = "abc";
    String s5 = s4.replace('a','m');
    System.out.println(s4);//abc
    System.out.println(s5);//mbc, indicating that replace() does not directly replace characters, but assigns "mbc" in the reopened space
}

The results are as follows:

9.1.2 differences between the two methods of creating String variables

The difference between String str1 = "abc" and String str2 = new String() is as follows:

/*
 * String Instantiation method
 * Method 1: through literal quantity
 * Mode 2: through new + constructor
 * */
@Test
public void test2(){
    //By literal: by literal definition: at this time, the values "java" of s1 and s2 are declared in the string constant pool in the method area
    String s1 = "java";
    String s2 = "java";

    //Through the new + constructor: at this time, s3 and s4 save the address value, which is the corresponding address value after the data opens up space in the heap space
    String s3 = new String("java");//new structures all open up space in heap space
    String s4 = new String("java");

    System.out.println(s1 == s2);//true
    System.out.println(s1 == s3);//false
    System.out.println(s1 == s4);//false
    System.out.println(s3 == s4);//false

    System.out.println("*************************");
    Person p1 = new Person("Tom",19);
    Person p2 = new Person("Tom",19);
    System.out.println(p1 == p2);//false
    System.out.println(p1.equals(p2));//false, toString() is not rewritten in p1. The address values of the two objects are still compared, that is, p1 == p2
    System.out.println(p1.name == p2.name);//true
    System.out.println(p1.name.equals(p2.name));//true

}

The results are as follows:

The following is a memory analysis with a code attached to enhance understanding:

String s = new String("abc"); Create objects. How many objects are created in memory?
Answer: there are two. One is the structure of new in the heap space, and the other is the data "abc" in the constant pool corresponding to char []

9.1.3 string splicing

@Test
public void test3(){
    /*The splicing result between constants is in the constant pool, and constants with the same content will not exist in the constant pool
     * However, the splicing results between constants and variables are in the heap
     * If the result of splicing calls intern(), the return value is in the constant pool
     * */
    String s1 = "hello";
    String s2 = "world";
    String s3 = "hello" + "world";
    //The last of the above three variables is the address of the string in the constant pool

    String s4 = s1 + "world";
    String s5 = s1 + s2;
    String s6 = (s1 + s2).intern();
    // The results of the first two variables S4 and S5 have variables involved in the operation, so although the strings are finally stored in the constant pool, S4 and S5 store the address of the array value opened in the heap,
    // The value stored in value is the address of the string in the constant pool,
    // That is, the address value in the heap is stored in the variable, and the content stored in the address is the address of the string in the constant pool
    //s6 finally calls intern(), which returns the address of the string in the constant pool.

    System.out.println(s3 == s4);//false
    System.out.println(s3 == s5);//false
    System.out.println(s3 == s6);//true

    System.out.println(s4 == s5);//false

}

The results are as follows:

9.1.4 common methods of string class

import org.junit.Test;

/**
 * Introduce the common methods in String class
 *
 * @author yangzhen
 * @create 2021-03-20 11:54
 */
public class StringMethod {
    @Test
    public void test1() {
        String s1 = "Hello,World";
        System.out.println(s1.length());//11. Return the number of characters in the string: return value length
        System.out.println(s1.charAt(0));//H. Returns the character at the specified index position of the string: return value[index]
        System.out.println(s1.charAt(1));//e
        System.out.println(s1.charAt(10));//d
//        System.out.println(s1.charAt(11));// An exception is reported. The maximum S1 index is 10
        System.out.println(s1.isEmpty());//false to determine whether it is an empty string: return value length == 0

        String s2 = s1.toUpperCase();
        System.out.println(s1);//Unchanged, the immutability of String
        System.out.println(s2);//HELLO,WORLD, convert lowercase letters to uppercase letters
        System.out.println(s1.toLowerCase());//hello,world, convert uppercase letters to lowercase letters

        String s3 = "   he  llo      world   ";
        String s4 = s3.trim();//Remove whitespace at the beginning and end of the string
        System.out.println("--------" + s3 + "-------------");
        System.out.println("--------" + s4 + "-------------");

        String s5 = "HelloWorld";
        String s6 = "helloworld";
        System.out.println(s5.equals(s6));//false
        System.out.println(s5.equalsIgnoreCase(s6));//true, ignore case and compare whether the two strings are equal

        String s7 = "abc";
        s7 = s7.concat(s5);
        System.out.println(s7);//"+, equivalent to" + "after two strings

        String s8 = "abc";
        String s9 = "adc";
        System.out.println(s8.compareTo(s9));//Compare the size of two strings. Negative number, the current object s8 is small; 0, equal; Positive, s9 large

        String s10 = "welcome to beijing";
        String s11 = s10.substring(2);//Returns a new string, which is the substring of this string intercepted from beginIndex to the last
        String s12 = s10.substring(0, 2);//Returns a new string of characters from beginIndex to endIndex (excluding endIndex)
        System.out.println(s10);
        System.out.println(s11);
        System.out.println(s12);
    }

    @Test
    public void test2() {
        String str1 = "HelloWorld";
        System.out.println(str1.endsWith("rld"));//endWith() tests whether the string ends with the specified suffix
        System.out.println(str1.startsWith("Hel"));//startsWith() tests whether the string starts with the specified prefix
        System.out.println(str1.startsWith("ll",2));//Tests whether the substring starting from the specified index starts with a custom prefix
        System.out.println();

        String str2 = "wor";
        System.out.println(str1.contains(str2));//contains() tests whether str1 contains str2 substrings

        System.out.println(str1.indexOf("Wor"));//indexOf() returns the index of the specified substring at the first occurrence in the string,
        System.out.println(str1.indexOf("lo",5));//Returns the index of the specified substring starting from the specified index at the first occurrence in this string,
        System.out.println(str1.lastIndexOf("lo"));//Returns the index of the specified string at the rightmost occurrence (the last occurrence) of this string
        System.out.println(str1.lastIndexOf("lo",6));//Start from the specified index and start from right to left to find the index of the last occurrence of the string
        //Note: indexOf and lastIndexOf methods return - 1 if they are not found
        //When does indexOf(str) and lastIndexOf(str) return the same value?
        //Answer: there is only one substring STR in the string, or there is no str (the return value is - 1 at this time)
    }

    @Test
    public void test3(){
        String str1 = "welcome to beijing";
        System.out.println(str1);//welcome to beijing
        System.out.println(str1.replace('north','south'));//Welcome to Nanjing
        System.out.println(str1.replace("Beijing","Shanghai"));//Welcome to Shanghai

    }
}

The results are as follows:

9.1.5 data type conversion of string

For the conversion between String and basic data type, see 5.9 packaging . The following is the conversion between String and char [] and byte []

import org.junit.Test;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

/**
 * Introduce some other String type conversions
 * @author yangzhen
 * @create 2021-03-20 16:11
 */
public class DataConvert {

    /*
    * String--->char[]: Call toCharArray() of String
    * char[]--->String: Call the constructor of String
    * */
    @Test
    public void test1(){

        String s1 = "abc123";
        char[] charArray = s1.toCharArray();
        for (int i = 0; i < charArray.length; i++) {
            System.out.println(charArray[i]);
        }
        System.out.println();
        char[] arr = new char[]{'h','e','l','l','o'};
        String s2 = new String(arr);
        System.out.println(s2);
    }

    /*
    * String--->byte[]Conversion between
    * */
    @Test
    public void test2() throws UnsupportedEncodingException {
        String str1 = "abc123 China";
        byte[] bytes1 = str1.getBytes();//Use the default character set for encoding
        System.out.println(Arrays.toString(bytes1));
        System.out.println(new String(bytes1));//Decode using the default character set
        System.out.println("**************************");
        byte[] bytes2 = str1.getBytes("GBK");//Use GBK character set encoding
        System.out.println(Arrays.toString(bytes2));
        System.out.println(new String(bytes2,"GBK"));//Decoding using GKB character set
    }
}

The results are as follows:

9.1.6 StringBuffer and StringBuilder

classintroduce
StringImmutable character sequence. The bottom layer uses char [] to store characters
StringBufferVariable character sequence (variable is modifiable), thread safe, but inefficient. The bottom layer uses char [] to store characters
StringBuilderJDK5.0 new, variable character sequence, but high efficiency (fast), thread unsafe, the bottom layer uses char [] to store characters

Efficiency comparison of String, StirngBuffer and StringBuilder StringBuilder > StringBuffer > String. When thread safety is not involved, StringBuilder is preferred.

import org.junit.Test;

/**
 * About StringBuffer and StringBuilder
 * @author yangzhen
 * @create 2021-03-20 16:57
 */
public class StringBufferBuilder {
    
    @Test
    public void test1(){
        String str = new String();//char[] value = new char[0];
        String str1 = new String("abc");//char[] value = new char[]{'a','b','c'};

        StringBuffer sb1 = new StringBuffer();//char[] value = new char[16]; The bottom layer creates a char [] with a length of 16
        System.out.println(sb1.length());//0. Check the source code and know that the length() of the StringBuffer class does not return the length of the array, but the number of array elements
        sb1.append('a');//value[0] = 'a';
        sb1.append('b');//value[1] = 'b';

        StringBuffer sb2 = new StringBuffer("abc");//char[] value = new char["abc".length() + 16]
		/*Problem: capacity expansion problem: if the underlying array of data to be added cannot fit, the underlying array needs to be expanded.
		By default, the capacity expansion is 2 times + 2 of the original capacity, and the elements in the original array are copied to the new array.
		In practice, try to use StringBuffer(int capacity) {} or StringBuilder(int capacity) {}*/
        System.out.println(sb2.length());//3
        System.out.println(sb2);//abc, variable character sequence table, which is added directly on the basis of the original string
    }


    /*
    * StringBuffer Common methods of:
    * StringBuffer append(xxx): Add character or string
    * StringBuffer delete(int start,int end): Delete the characters in the index position between [start, end]
    * StringBuffer replace(int start,int end,String str): Replace the substring between [start, end] with str
    * StringBuffer insert(int offset,xxx): Insert xxx at the specified location
    * StringBuffer reverse(): Reverse the current character sequence
    * public int indexOf(String str): Same as String, returns the index of the first character containing the str substring position
    * public String substring(int start,int end): Returns a substring indexed from [start, end]
    * public int length()
    * public char charAt(int n)
    *public void setCharAt(int n,char ch)
    *
    * To sum up:
    *               Add: append(xxx)
    *               Delete: delete(int start,int end)
    *               Change: setCharAt(int n,char ch)/replace(int start,int end,String str)
    *               Check: charAt(int n)
    *               Insert: insert(int offset,xxx)
    *              Length: length()
    *              Traversal: toString()
     * */
    @Test
    public void test2(){
        StringBuffer s1 = new StringBuffer("abcdef");

        s1.append(1);
        s1.append('1');
        System.out.println(s1);//abcdef11, like String, is called by default without writing toString()

        s1.delete(2,4);
        System.out.println(s1);//abef11

        s1.replace(2,4,"hello");
        System.out.println(s1);//abhello11

        s1.insert(2,false);
        System.out.println(s1);//abfalsehello11
        s1.insert(2,"xyz");
        System.out.println(s1);//abxyzfalsehello11

        s1.reverse();
        System.out.println(s1);//11olleheslafzyxba

        System.out.println(s1.substring(0,4));//11ol

    }

}

The operation results are as follows:

9.2 date time API before jdk8

9.2.1 currentTimeMillis() of system class

**The time difference between the current time and 0:0:0:0 on January 1, 1970 (in ms) * * is called the timestamp, and currentTimeMillis() returns the timestamp (long data).

public void test1(){
    System.out.println(System.currentTimeMillis());//1616334595882
}

9.2.2 java.util.Date class

1. Constructor public Date(): when creating a Date object, it defaults to the Date and time of the object;
2. Constructor public Date(long time): when creating an object, the specified date and time is the date and time corresponding to the number of milliseconds time;

3.public String toString(): the Date object calls toString() to return a string that displays the Date and time of the current object in the format of Chinese standard time.
Remember: the overridden toString() is the same as the Object parent class, and returns the String type. Since it has been overridden, it is called by default and can not be written.

4.public long getTime(): Date object calls getTime() to return the "timestamp" of the date and time of the current object.
Remember: not to return the current timestamp. For example, if the date time of the date object is 2021-03-20 22:47:00, getTime() returns the timestamp corresponding to the time instead of the current 2021-03-21 22:17:25 timestamp.

@Test
public void test2(){
    Date date1 = new Date();
    System.out.println(date1);//Sun Mar 21 22:17:25 CST 2021, Chinese Standard Time
    System.out.println(date1.getTime());//1616336245552
    
    Date date2 = new Date(1616251620714L);
    System.out.println(date2);//Sat Mar 20 22:47:00 CST 2021
    System.out.println(date2.getTime());//1616251620714
}

9.2.4 java.sql.Date class

Inherited from Java util. Date class is mainly used in database. Here is a brief introduction

@Test
public void test3(){
    //Create Java sql. Date object
    java.sql.Date date1 = new java.sql.Date(1616251830081L);
    System.out.println(date1);//2021-03-20, the Date and time format here is inconsistent with the Date class under util package

    //How to convert Java util. Date object is converted to Java sql. Date object, that is, the parent object is converted into a child object
    //Method 1: use polymorphism and strong transformation to convert each other
    Date date2 = new java.sql.Date(1616251830081L);
    java.sql.Date date3 = (java.sql.Date)date2;
    System.out.println(date3);//2021-03-20
    //Method 2: recreate an object through the constructor
    Date date4 = new Date();
    //Like the public Date(long time) constructor under Util package, the following constructor with parameters (timestamp) is actually used when creating objects, but the timestamp is given through date4
    java.sql.Date date5 = new java.sql.Date(date4.getTime());
    System.out.println(date5);//2021-03-20
}

For more information on multiple cast types, see Downward and upward transformation.

9.2.3 SimpleDateFormat class

Because the default date format, such as Sun Mar 21 22:17:25 CST 2021, is not used to viewing, and it is inconvenient to watch in different countries and regions, this class is used to process the time to adapt it to the viewing habits of users.
SimpleDateFormat formats and parses the date and time. In fact, it can be understood from the literal meaning: simple date format.

Format: convert the date into a string; Parse: converts a string to date format. The following is an example through public String format(Date date) formatting and public Date parse(String date):

@Test
public void test4() throws ParseException {//Exception thrown during parsing
    //Instantiate SimpleDateFormat: use null argument constructor
    SimpleDateFormat sDF = new SimpleDateFormat();

    //Format: date - > string
    Date date = new Date();
    System.out.println(date);//Before formatting: Sun Mar 21 23:27:01 CST 2021
    String format = sDF.format(date);//Format returns the date after formatting (translated into Chinese format by default)
    System.out.println(format);//After formatting: 21-3-21 11:27 PM
    
    //Parsing: String ----- > date
    String str = "2021-3-21 5 pm:31";//First, an exception should be declared, and the format must be "Year Month Day morning / afternoon xx:xx", otherwise an exception will be reported
    Date date1 = sDF.parse(str);//Translated into standard time
    System.out.println(date1);//After parsing: Sun Mar 21 17:31:00 CST 2021
}

The above writing method is only for understanding. In the actual process of writing code, we are more accustomed to the following writing method of creating objects through the constructor with parameters (the parameter specifies the date format):

/*It is common practice to use a constructor with parameters to format the time*/
Date date2 = new Date();
SimpleDateFormat sDF1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//Specifies the format, where HH stands for 24-hour system and HH stands for 12 hour system

//format
System.out.println(sDF1.format(date2));//2021-03-21 23:27:01

//analysis
System.out.println(sDF1.parse(sDF1.format(date2)));//Sun Mar 21 23:27:01 CST 2021, the time format should be consistent with the format of its formal parameters, otherwise an exception is reported
System.out.println(sDF1.parse("2021-03-21 23:27:01"));//Sun Mar 21 23:27:01 CST 2021

9.2.4 Calendar

public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> {}

Looking at the source code, you can see that the Calendar class is an abstract class. To instantiate, you must use a subclass (Gregorian Calendar class). It's common to use public static Calendar getInstance() to instantiate. Its essence is to instantiate through subclasses, but calling the method can write one line of code less.

Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getClass());//GregorianCalendar
/*
 * Calendar Use of abstract classes
 */
@Test
public void testCalendar() {
    Calendar calendar = Calendar.getInstance();
    System.out.println(calendar.getClass());//GregorianCalendar, so getInstance is also instantiated through the subclass of GregorianCalendar

    //public int get()
    int days = calendar.get(Calendar.DAY_OF_MONTH);
    //Note: when getting the month, January is 0, February is 1, and so on. December is 11
    //When getting the week, Sunday is 1, Monday is 2, and Saturday is 7
    System.out.println(days);//23

    //public void set(int field,int value)
    calendar.set(Calendar.DAY_OF_MONTH, 21);
    System.out.println(calendar.get(Calendar.DAY_OF_MONTH));//21

    //abstract public void add(int field,int amount)
    calendar.add(Calendar.DAY_OF_MONTH, 2);
    System.out.println(calendar.get(Calendar.DAY_OF_MONTH));//23
    calendar.add(Calendar.DAY_OF_MONTH, -3);
    System.out.println(calendar.get(Calendar.DAY_OF_MONTH));//20

    //public final Date getTime(): Calendar Class -- > date class
    Date date1 = calendar.getTime();
    System.out.println(date1);//Sat Mar 20 13:12:53 CST 2021

    //public final void setTime(Date date):Date class -- > Calendar Class
    Date date2 = new Date();
    calendar.setTime(date2);
    System.out.println(calendar.get(Calendar.DAY_OF_MONTH));//23
}

The results are as follows:

9.3 new date and time API in jdk8

The date and time API before JDK 8 has many shortcomings, which makes programmers very painful when dealing with date and time problems. Therefore, there are many new optimized date and time APIs in JDK 8, which are more user-friendly. Therefore, the previous APIs are only introduced, and the new date and time API in JDK 8 is still used for real time processing.

9.3.1 LocalDate, LocalTime and LocalDateTime classes

Similar to Calendar Class

/*
 * LocalDate,LocalTime,LocalDateTime(Use of more common classes
 * */
@Test
public void test1(){
    //now() get the current date, time, date + time
    LocalDate localDate = LocalDate.now();
    LocalTime localTime = LocalTime.now();
    LocalDateTime localDateTime = LocalDateTime.now();
    System.out.println(localDate);//2021-03-23
    System.out.println(localTime);//14:36:58.610
    System.out.println(localDateTime);//2021-03-23T14:36:58.610

    System.out.println("***********************************");
    //of() sets the specified year, month, day, hour, minute and second
    LocalDate localDate1 = LocalDate.of(2020, 3, 23);
    LocalTime localTime1 = LocalTime.of(14, 33, 35);
    LocalDateTime localDateTime1 = LocalDateTime.of(2021, 3, 23,15,12,13);
    System.out.println(localDate1);//2020-03-23
    System.out.println(localTime);//14:36:58.610
    System.out.println(localDateTime1);//2021-03-23T15:12:13

    System.out.println("**********************************");
    //getXxx()
    System.out.println(localDateTime.getDayOfMonth());//23
    System.out.println(localDateTime.getDayOfWeek());//TUESDAY
    System.out.println(localDateTime.getMonth());//MARCH
    System.out.println(localDateTime.getMonthValue());//3
    System.out.println(localDateTime.getMinute());//36

    System.out.println("**********************************");
    //Similar to the immutability of String string: regenerate a specified time instead of modifying it at the current time
    LocalDate localDate2 = localDate.withDayOfMonth(11);
    System.out.println(localDate);//On March 23, 2021, the current date has not changed
    System.out.println(localDate2);//March 11, 2021, date of regeneration
    //Ditto: non variability
    LocalDateTime localDateTime2 = localDateTime.withHour(4);//Change hours
    System.out.println(localDateTime);//2021-03-23T14:45:06.270
    System.out.println(localDateTime2);//2021-03-23T04:45:06.270
    //Ditto: non variability
    LocalDate localDate3 = localDate.plusDays(12);//Current 3.23 plus 10 days
    System.out.println(localDate3);//2021-04-04
    LocalDate localDate4 = localDate.minusMonths(8);//Current 2021.3.23 minus 8 months
    System.out.println(localDate4);//2020-07-23

}

9.3.2 Instance class

Similar to Date class

@Test
public void test2(){
    //now(): get the standard time corresponding to the original meridian
    Instant instant = Instant.now();
    System.out.println(instant);//2021-03-23T07:06:18.337Z
    //Add the offset of the time to match the time zone
    OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
    System.out.println(offsetDateTime);//2021-03-23T15:07:34.445+08:00

    //Toepochmili(): get the number of milliseconds starting from 0:0:0 (UTC) on January 1, 1970 -- > getTime() of date class
    long milliSeconds = instant.toEpochMilli();
    System.out.println(milliSeconds);//1616483297713, return the timestamp of standard time

    //Ofepochmili(): get the instant instance -- > date (long millis) by the given number of milliseconds
    Instant instant1 = Instant.ofEpochMilli(1616483297713L);
    System.out.println(instant1);//2021-03-23T07:08:17.713Z
}

9.3.3 DateTimeFormatter class

Format or parse the date and time, similar to the SimpleDateFormat class. There are three ways to format the parsing time, of which the third custom method is the most commonly used. The first two are only introduced.

1. Mode 1:

//Method 1: predefined standard format. E.g. ISO_LOCAL_DATE_TIME,ISO_LOCAL_DATE,ISO_LOCAL_TIME
//Format: date -- > string
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
LocalDateTime localDateTime = LocalDateTime.now();
String str1 = formatter.format(localDateTime);
System.out.println(localDateTime);//2021-03-23T16:36:20.766
System.out.println(str1);//2021-03-23T16:36:20.766
//Parsing: String -- > date
TemporalAccessor parse = formatter.parse("2021-03-23T16:30:39.826");
System.out.println(parse);//{},ISO resolved to 2021-03-23T16:30:39.826

2. Mode 2:

//Mode 2: localize relevant formats. For example: oflocalized datetime (formatstyle. Long)
DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG);
//format
String str2 = formatter1.format(localDateTime);
System.out.println(str2);//March 23, 2021

DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
String str3 = formatter2.format(LocalDate.now());
System.out.println(str3);//Tuesday, March 23, 2021

3. Mode 3 (key points):

//Method 3 (most commonly used): custom format
DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//format
String str4 = formatter3.format(localDateTime.now());
System.out.println(str4);//2021-03-23 16:51:40
//analysis
TemporalAccessor accessor = formatter3.parse("2021-03-23 16:49:16");
System.out.println(accessor);//{},ISO resolved to 2021-03-23T16:49:16

The results are as follows:

The change of date time API is summarized as follows:

9.4 Java comparator (key)

Example of using compatible interface: 9.4

1. Both String and wrapper classes implement the Comparable interface, rewrite public int compareTo(Object obj), and give a way to compare the sizes of two objects.

2. After rewriting the compareTo() method for String and wrapper classes, they are arranged from small to large

3. Principle of rewriting compareTo():
If the current object this is greater than the formal parameter object obj, a positive integer is returned;
If the current object this is less than the formal parameter object obj, a negative integer is returned;
If the current object this is equal to the parameter object obj, zero is returned.

4. For a custom class, if you need to sort the objects of this class, we can let the custom class implement the Comparable interface, rewrite compareTo(obj), and define how to sort in compareTo(obj)

import org.junit.Test;

import java.util.Arrays;

/**
 * @author yangzhen
 * @create 2021-03-23 18:35
 */
public class Comparable {

    @Test
    public void test1(){
        Goods[] arr = new Goods[5];
        arr[0] = new Goods("microsoftMouse",34);
        arr[1] = new Goods("dellMouse",43);
        arr[2] = new Goods("xiaoMi",20);
        arr[3] = new Goods("huaweiMouse",50);
        arr[4] = new Goods("lenovoMouse",34);

        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));


    }
}

//Commodity category
class Goods implements java.lang.Comparable {
    private String name;
    private double price;

    public Goods() {
    }

    public Goods(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }

    //Indicates how items are compared in size
    public int compareTo(Object obj){
        if(obj instanceof Goods){
            Goods goods = (Goods)obj;
            if(this.price > goods.price){
                return 1;
            }else if(this.price == goods.price){
                return this.name.compareTo(goods.name);//When the prices are the same, they are sorted alphabetically (from low to high)
            }
            return -1;
        }
        throw new RuntimeException("The data type passed in is inconsistent!");
    }
}

The results are as follows:

9.4.2 example of comparator interface: customized sorting

When the element type does not implement the Comparable interface and it is inconvenient to modify the code, or implements the interface but the sorting rules are not suitable for the current operation (in other words, you want to customize the sorting method), you can consider implementing the Comparator interface to sort.

The principle of rewriting compare(Object o1,Object o2) in comparator interface:
If the method returns a positive integer, o1 is greater than o2;
If 0 is returned, it means equal;
If a negative integer is returned, o1 is less than o2

In the compare method, we call other methods, such as the compareTo method, to sort according to the rules we want

package pers.yangzhen.ordinaryclass.compare;

import org.junit.Test;

import java.util.Arrays;
import java.util.Comparator;

/**
 * Implement Comparator interface: custom sorting
 * @author yangzhen
 * @create 2021-03-23 18:36
 */
public class ComparatorInterface {

    @Test
    public void test1(){
        String[] arr = new String[]{"TT","KK","GG","AA","BB","CC","DD","EE"};
        Arrays.sort(arr,new Comparator(){//Anonymous object of anonymous implementation class

            //Arrange strings in descending order
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof String && o2 instanceof String){
                    String s1 = (String) o1;
                    String s2 = (String) o2;
                    return -s1.compareTo(s2);//A minus sign indicates from large to small

                }
                throw new RuntimeException("The data type entered is inconsistent");
            }
        });
        System.out.println(Arrays.toString(arr));
    }

    @Test
    public void test2(){
        Goods[] arr = new Goods[5];
        arr[0] = new Goods("microsoftMouse",34);
        arr[1] = new Goods("dellMouse",43);
        arr[2] = new Goods("xiaoMi",20);
        arr[3] = new Goods("huaweiMouse",50);
        arr[4] = new Goods("microsoftMouse",35);

        Arrays.sort(arr, new Comparator() {
            //Products are sorted from low to high by name first. If the names are the same, they are sorted from high to low by price
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof Goods && o2 instanceof Goods){
                    Goods goods1 = (Goods)o1;
                    Goods goods2 = (Goods)o2;
                    if(goods1.getName().equals(goods2.getName())){
                        //Call the compare method of the wrapper class
                        return -Double.compare(goods1.getPrice(),goods2.getPrice());
                    }else{
                        //compareTo() is overridden in the String class, which sorts strings from small to large by default
                        return goods1.getName().compareTo(goods2.getName());
                    }
                }
                throw new RuntimeException("Input type mismatch");
            }

        });
        System.out.println(Arrays.toString(arr));
    }
}

The results are as follows:

Once the method of the Comparable interface is determined, the size of the objects that can implement the class can be compared at any position. The Comparator interface is a temporary comparison

9.5 System class, Math class, BigInteger class and BigDecimal class

9.5.1 System class

1. The system class represents the system. Many properties and control methods are placed inside this class. This class is applicable to Java Lang package, imported by default.
2. Since the constructor of this class is private, the object of this class cannot be created, that is, it cannot be instantiated. Its internal member variables and member methods are static, so it is also convenient to call System Properties / methods.
3. Member variable (i.e. attribute): the System class contains three member variables: in, out and err, which represent standard input stream (keyboard input), standard output stream (display) and standard error output stream (display) respectively; IO stream

4. Membership method:
native long current currentTimeMillis() returns the timestamp (mentioned in the previous date time class);
void exit(int status) is used to exit the program. When the value of status is 0, it represents normal launch, and non-0 represents abnormal exit, the exit function of the program can be realized in graphical interface programming;
void gc() is used to request the system for garbage collection. As for whether to recycle immediately, it is subordinate to the implementation of garbage collection algorithm in the system and the implementation of the system;
String getProperty(String key) obtains the value corresponding to the property named key in the system. Common property names and functions are as follows

Attribute nameAttribute description
java.versionjava runtime environment version
java.homejava installation directory
os.nameOperating system name
os.versionOperating system version
user.nameUser account name
user.homeUser's home directory
user.dirUser's current working directory
import org.junit.Test;

/**
 * System Class's String getProperty(String key)
 * @author yangzhen
 * @create 2021-03-24 10:34
 */
public class Sys {
    @Test
    public void test(){
        System.out.println(System.getProperty("java.version"));
        System.out.println(System.getProperty("java.home"));
        System.out.println(System.getProperty("os.name"));
        System.out.println(System.getProperty("os.version"));
        System.out.println(System.getProperty("user.name"));
        System.out.println(System.getProperty("user.home"));
        System.out.println(System.getProperty("java.dir"));
    }
}

The results are as follows:

The properties and methods in the following classes will be called. If you encounter something you haven't seen, you can check it. There's no need to tangle.

9.5.2 Math class

java.lang.Math class provides a series of static methods for scientific calculation. The parameters and return values of its methods are generally double.

9.5.3 BigInteger and BigDecimal classes

Although the long class is the wrapper class of long, it can represent the range of integers [ − 2 63 , 2 63 − 1 ] [-2^{63},2^{63}-1] [− 263263 − 1] it is already very large, but there are still some things beyond this range. java. math. The BigInteger class can represent immutable integers of arbitrary precision and provide Java All relevant methods of lang.math. In addition, the following operations are provided: modular operation, GCD calculation, index test, prime generation, bit operation and some other operations.

The general Float class and Double class can be used for scientific calculation or engineering calculation. However, in Business Computing, the required digital accuracy is very high, so Java is used math. BigDecimal class.

@Test
public void test(){
    BigInteger bi = new BigInteger("12433241123");
    BigDecimal bd = new BigDecimal("12312.1213");
    BigDecimal bd2 = new BigDecimal("11");
    System.out.println(bi);

    System.out.println(bd.divide(bd2,BigDecimal.ROUND_HALF_UP));// bd/bd2, result rounded
    System.out.println(bd.divide(bd2,15,BigDecimal.ROUND_HALF_UP));// bd/bd2, the result is rounded to 15 bits
}

The results are as follows:

10. Enumeration class and annotation

10.1 use of enumeration class

When the number of objects of a class is limited and all of them are determined, this class is called enumeration class. When you need to define a set of constants, you can use the enumeration class. If there is only one object in the enumeration class, it can be used as the implementation of singleton mode.

10.1.1 JDK5. Before 0

/**
 * @author yangzhen
 * @create 2021-03-24 14:27
 */
public class BeforeJava5 {
    public static void main(String[] args) {
        Season spring = Season.SPRING;
        System.out.println(spring);
        System.out.println(Season.SUMMER);
        System.out.println(Season.AUTUMN);
        System.out.println(Season.WINTER);
    }
}

//Custom enumeration class
class Season{
    //1. Declare the attributes of Season object: private and final modifiers
    private final String seasonName;
    private final String seasonDesc;

    //2. Privatize the constructor and assign a value to the object attribute
    private Season(String seasonName, String seasonDesc) {
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }

    //3. Provide multiple objects of the current enumeration class: public static final modifier
    //In other words, the following four global constants of type Season are defined
    public static final Season SPRING = new Season("spring","in the warm spring , flowers are coming out with a rush");
    public static final Season SUMMER = new Season("summer","Summer heat");
    public static final Season AUTUMN = new Season("autumn","fresh autumn weather");
    public static final Season WINTER = new Season("winter","snow gleams white");

    //4. Other requirements 1: get the properties of enumeration objects
    public String getSeasonName() {
        return seasonName;
    }

    public String getSeasonDesc() {
        return seasonDesc;
    }

    //4. Other appeals 2: toString()
    @Override
    public String toString() {
        return "Season{" +
                "seasonName='" + seasonName + '\'' +
                ", seasonDesc='" + seasonDesc + '\'' +
                '}';
    }
}

The results are as follows:

It is enough to understand the custom enumeration class (because the steps are too cumbersome). It is more commonly used to define the enumeration class with enum keyword after JDK 5.0 (because you can write less code, lazy!!!)

10.1.2 JDK5. After 0

Enumeration class inherits from Java Lang. Enum class, which in turn inherits from the Object class.

Enum keyword defines three common methods of enum classes:
1.toString(): Enum class has overridden toString(), which returns the name of the object constant of the current enumeration class, so the enumeration class also inherits the toString() overridden by Enum. If there are no special display requirements, the enumeration class can directly call toString() to display the name of the constant (it can not be written out, and the toString method is called by default);
2. Value (): returns an object array of enumeration type. This method can easily traverse all enumeration values;
3.valueOf(String objName): returns the object whose object name is objName in the enumeration class

/**
 * @author yangzhen
 * @create 2021-03-24 14:43
 */
public class AfterJava5 {
    public static void main(String[] args) {
        System.out.println(Season.SPRING);
        System.out.println(Season.SUMMER);
        System.out.println(Season.AUTUMN);
        System.out.println(Season.WINTER);

        System.out.println("************************");
        //values(): returns an array of objects of enumeration type. This method can easily traverse all enumeration values
        Season1[] values = Season1.values();
        for (int i = 0; i < values.length; i++) {
            System.out.println(values[i]);
            
        }
        System.out.println("************************");
        //Enhanced for loop
//        for(Season1 s:Season1.values()){
//            System.out.println(s);
//        }

        System.out.println("************************");
        //valueOf(String objName): returns the object whose object name is objName in the enumeration class
        Season1 winter = Season1.valueOf("WINTER");
        System.out.println(winter);
        //If there is no enumeration class object of objName, an exception will be thrown, such as:
//        Season1 winter1 = Season1.valueOf("WINTER1");
//        System.out.println(winter1);//IllegalArgumentException


    }
}

enum Season1{
    //Provides the object of the current enumeration class. Multiple objects are separated by commas, and the end object is ended by a semicolon
    SPRING("spring","in the warm spring , flowers are coming out with a rush"),
    SUMMER("summer","Summer heat"),
    AUTUMN("autumn","fresh autumn weather"),
    WINTER("winter","snow gleams white");

    private final String Season1Name;
    private final String Season1Desc;

    private Season1(String Season1Name, String Season1Desc) {
        this.Season1Name = Season1Name;
        this.Season1Desc = Season1Desc;
    }

    public String getSeason1Name() {
        return Season1Name;
    }
    public String getSeason1Desc() {
        return Season1Desc;
    }
}

The results are as follows:

10.1.3 implement the interface with enum class defined by enum

1. Implement the interface and implement the abstract method in the enum class

//Make some changes in the previous code block:
/**
 * @author yangzhen
 * @create 2021-03-24 14:43
 */
public class AfterJava5 {
    public static void main(String[] args) {
        Season1[] values = Season1.values();
        for (int i = 0; i < values.length; i++) {
            System.out.println(values[i]);
            values[i].show();
        }
        
    }
}

interface Info{
    public void show();
}

enum Season1 implements Info{

    SPRING("spring","in the warm spring , flowers are coming out with a rush"),
    SUMMER("summer","Summer heat"),
    AUTUMN("autumn","fresh autumn weather"),
    WINTER("winter","snow gleams white");

    private final String Season1Name;
    private final String Season1Desc;

    private Season1(String Season1Name, String Season1Desc) {
        this.Season1Name = Season1Name;
        this.Season1Desc = Season1Desc;
    }

    public String getSeason1Name() {
        return Season1Name;
    }
    public String getSeason1Desc() {
        return Season1Desc;
    }

    public void show(){
        System.out.println("This is a season");
    }
}

The results are as follows:

2. The objects of enumeration classes implement the abstract methods in the interface respectively

//Again, make some changes in the previous code block:
/**
 * @author yangzhen
 * @create 2021-03-24 14:43
 */
public class AfterJava5 {
    public static void main(String[] args) {
        Season1[] values = Season1.values();
        for (int i = 0; i < values.length; i++) {
            System.out.println(values[i]);
            values[i].show();
        }

    }
}

interface Info{
    public void show();
}

enum Season1 implements Info{

    SPRING("spring","in the warm spring , flowers are coming out with a rush"){
        @Override
        public void show(){
            System.out.println("Where is spring");
        }
    },
    SUMMER("summer","Summer heat"){
        @Override
        public void show(){
            System.out.println("Ningxia");
        }
    },
    AUTUMN("autumn","fresh autumn weather"){
        @Override
        public void show(){
            System.out.println("Autumn doesn't come back");
        }
    },
    WINTER("winter","snow gleams white"){
        @Override
        public void show(){
            System.out.println("About winter");
        }
    };

    private final String Season1Name;
    private final String Season1Desc;

    private Season1(String Season1Name, String Season1Desc) {
        this.Season1Name = Season1Name;
        this.Season1Desc = Season1Desc;
    }

    public String getSeason1Name() {
        return Season1Name;
    }
    public String getSeason1Desc() {
        return Season1Desc;
    }

}

The results are as follows:

10.2 use of annotations

Annotations in Java se are easy to use and are very important in Java EE.

Use example 1: generate annotations related to documents;

Use example 2: format checking at compile time (three basic annotations built into JDK):
@Override defines the override method. This annotation can only be used for methods
@Deprecated is used to indicate that the modified classes and methods are outdated. Usually because the modified structure is dangerous or there is a better choice
@SuppressWarnings suppresses compiler warnings

Use example 3: track code dependencies and implement the alternative configuration file function

Meta annotation: explain the existing annotations, and the four types are as follows:
Retention: Specifies the life cycle of the modified Annotation: source \ class (default behavior) \ RUNTIME only annotations declared as RUNTIME life cycle can be obtained through reflection.
Target: used to specify which program elements can be modified by the modified Annotation
Documented: indicates that the modified annotation will be retained when it is parsed by javadoc
Inherited: the Annotation modified by it will be inherited

New features of annotation in JDK8: repeatable annotation and type annotation:
Repeatable notes:
① Declare @ Repeatable on MyAnnotation, and the member value is MyAnnotation class
② MyAnnotation has the same Target and Retention as MyAnnotation

11. Java collection

For the operation of multiple objects, array is used for processing before. However, array storage objects have some disadvantages:
① Once the array is initialized, its length and data type are determined and cannot be changed. Although polymorphism can slightly make up for the problem of data type, it is still inconvenient;
② The methods provided in the array are very limited. It is very inconvenient and inefficient to add, delete and insert data;
③ The requirement to obtain the number of actual elements in the array. There are no ready-made attributes and methods available in the array;
④ The data stored in the array is orderly and repeatable, but it can not meet the requirements of unnecessary and non repeatable.

Java collection can overcome the above shortcomings. It is more like a container than array. It can dynamically put the references of multiple objects into the container.

Methods in collection 11.1

Since the methods in the Collection interface are abstract methods, the following is a test with the implementation class ArrayList of the List sub interface.

Many methods will automatically call equals() of the class where the obj object is located for comparison during execution. Therefore, when adding data obj to the object of the implementation class of the Collections interface, the class where obj is located * * is required to override equals() * * comparison content.

1. Basic methods

@Test
public void test1() {
    Collection coll = new ArrayList();

    //add(Object e): add element e to the collection coll
    coll.add("AA");
    coll.add("BB");
    coll.add(123);//Automatic packing
    coll.add(new Date());

    //size(): get the number of added elements
    System.out.println(coll.size());//4

    //Add all (collection coll1): add all elements in the coll1 collection to the current collection
    Collection coll1 = new ArrayList();
    coll1.add(456);
    coll1.add(new Person("Tom", 18));
    coll.addAll(coll1);
    System.out.println(coll.size());//6
    System.out.println(coll);//Value of each element

    //clear() clears the collection elements
    coll.clear();

    //isEmpty(): judge whether there are elements in the current collection
    System.out.println(coll.isEmpty());//true
}

The results are as follows:

2.contains() and containsAll()

@Test
public void test2() {
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(345);
    coll.add("Hello");
    coll.add(new String("World"));
    coll.add(new Person("Tom", 12));

    //contains(Object obj): determines whether the current collection contains obj
    System.out.println(coll.contains(123));//true

    System.out.println(coll.contains(new String("World")));//true
    System.out.println(coll.contains(new Person("Tom", 12)));//false
    //When judging, it will call equals() of the class where the obj object is located. Therefore, when adding data obj to the object of the implementation class of the Collections interface by default, the class where obj is located is required to override equals()

    //containsAll(Collection coll1): judge whether all elements in the formal parameter coll2 exist in the current collection. Like contains(), equals() will be called
    Collection coll1 = Arrays.asList(123, 456);
    Collection coll2 = Arrays.asList(123, 345);
    System.out.println(coll.containsAll(coll1));//false
    System.out.println(coll.containsAll(coll2));//true
}

The results are as follows:

3.remove() and removeAll()

@Test
public void test3() {
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(456);
    coll.add(new Person1("Jerry", 20));
    coll.add(new String("Tom"));
    coll.add(false);

    //remove(Object obj) removes the specified element obj. Like contains(), equals() is called
    System.out.println(coll.remove(123));//true, the removal is successful
    System.out.println(coll);
    coll.remove(new Person1("Jerry", 20));//true, the removal is successful
    System.out.println(coll);//Because the two contents can be compared by overriding equals() in the Person1 class, it can be removed successfully

    //removeAll(Collection coll1): remove all elements in coll1 from the current collection, and call equals()
    Collection coll1 = Arrays.asList("Tom", false);
    coll.removeAll(coll1);
    System.out.println(coll);

}

The results are as follows:

4.retainAll()

@Test
public void test4() {
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(456);
    coll.add(new Person1("Jerry", 20));
    coll.add(new String("Tom"));
    coll.add(false);

    //removeAll is similar to the difference set in mathematics
    //Correspondingly, similar to intersection is retain all (collection coll1)
    Collection coll1 = Arrays.asList(123, 456, 789);
    coll.retainAll(coll1);
    System.out.println(coll);

}

The results are as follows:

5. Conversion between set and array

@Test
public void test5() {
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(456);
    coll.add(new Person1("Jerry", 20));
    coll.add(new String("Tom"));
    coll.add(false);
    //The hashCode() of the coll Object inherits from the hashCode() in the Object class and returns the hash value of the current Object
    System.out.println(coll.hashCode());//701070075

    //toArray(): set -- > array
    Object[] arr = coll.toArray();
    for (int i = 0; i < arr.length; i++) {
        System.out.println(arr[i]);
    }

    //Array -- > collection
    List<String> list = Arrays.asList(new String[]{"AA", "BB", "CC"});
    System.out.println(list);

    List arr1 = Arrays.asList(new int[]{123,456});
    System.out.println(arr1.size());//1. By default, the two elements of the above int array are treated as one element, that is, the internal elements of the anonymous array
    List arr2 = Arrays.asList(new Integer[]{123,456});
    System.out.println(arr2.size());//2. It is OK to wrap the class with Integer

}

The results are as follows:

11.2 iterator interface

The Iterator object is called an Iterator (a kind of design pattern) and is mainly used to traverse the elements in the Collection.

The Collection interface inherits Java Lang. Iterator interface, which has an iterator() method, then all Collection classes that implement the Collection interface have an iterator() method to return an object that implements the Iterator interface.

Iterator is only used to traverse collections and does not provide the ability to load objects by itself. If you need to create an iterator object, you must have a collection that is iterated.

Every time a collection object calls the iterator() method, it gets a new iterator object, and the default cursor is before the first element of the collection.

@Test
public void test1(){
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(456);
    coll.add(new Person1("Jerry", 20));
    coll.add(new String("Tom"));
    coll.add(false);

    Iterator iterator = coll.iterator();//The iterator() under the Collection class returns an object of type Iterator

    //        System.out.println(iterator.next());//next() returns the value of the next element
    //        System.out.println(iterator.next());
    //        System.out.println(iterator.next());
    //        System.out.println(iterator.next());
    //        System.out.println(iterator.next());
    //        for (int i = 0; i < coll.size(); i++) {
    //            System.out.println(iterator.next());
    //        }

    //The first two traversal methods are not commonly used. I'm more used to the following methods
    while (iterator.hasNext()){//hasNext() queries whether there are any elements after it
        //next(): ① move the pointer down ② return the elements at the collection position after moving down
        System.out.println(iterator);
    }

    //Note: the following two expressions are wrong
    //1.
    //        while(iterator.next() != null){
    //            System.out.println(iterator.next());
    //        }
    //2.
    //        while (coll.iterator().hasNext()){
    //            System.out.println(coll.iterator().next());
    //        }
}

The results are as follows:

//Test remove() in Iterator
@Test
public void test2(){
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(456);
    coll.add(new Person1("Jerry", 20));
    coll.add(new String("Tom"));
    coll.add(false);

    Iterator iterator = coll.iterator();
    while (iterator.hasNext()){
        Object obj = iterator.next();
        if("Tom".equals(obj)){
            iterator.remove();//The remove() method of this iterator is not the remove() method of the collection object
        }
    }

    //At this time, the cursor (or pointer) of the iterator has reached the end of the last one,
    //If you want to reenter the collection, you must regenerate an iterator so that the cursor precedes the first element
    iterator = coll.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }

}

The results are as follows:

Note: 1 IllegalStateException will be reported when the remove method is called before calling next(). Because there is no corresponding element before the pointer points to the first element, how to delete it? Naturally, it will report an exception.
2. If the remove method has been called after calling the next method, the same exception will still be reported if it is called again. Since the element pointed to by the cursor has been deleted, the position is empty. How to delete it again? Can you delete the air? Therefore, an exception is reported.

Tips: foreach loop (enhanced for loop)

JDK 5.0 adds a foreach loop to traverse sets and arrays

//Traverse collection elements
@Test
public void test1() {
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(456);
    coll.add(new Person1("Jerry", 20));
    coll.add(new String("Tom"));
    coll.add(false);

    //The type of the local variable of the for object
    //In fact, the iterator is still being called internally
    for (Object obj : coll) {
        System.out.println(obj);
    }

}

The results are as follows:

//Traversal array
@Test
public void test2(){
    int[] arr1 = new int[]{1,2,3,4,5,6};
    String[] arr2 = new String[]{"AA","BB","CC"};

    //For (type of array element, local variable: array object)
    for(int i : arr1){
        System.out.println(i);
    }

    for(String s : arr2){
        System.out.println(s);
    }
}

The results are as follows:

11.3 Collection sub interface 1: List (key!!!)

The elements in the List set are ordered and repeatable, and each element in the set has its corresponding sequential index. The elements in the List container correspond to an integer serial number, recording their position in the container. The elements can be taken according to the serial number, which is similar to the index index of the array. Therefore, the List interface is also called "dynamic array".
The implementation classes of List interface in JDK API are ArrayList, LinkedList and Vector

Similarities:
Because they all implement the List interface, they store orderly and repeatable data

Implementation classdifference
VectorThe ancient implementation class of the List interface (which appeared earlier and is almost unnecessary now. Just understand it), is thread safe and inefficient. The underlying layer uses Object[] elementData storage
ArrayListThe main implementation class of the List interface has unsafe threads and high efficiency. The underlying layer uses Object[] elementData storage
LinkedListFor frequent insert and delete operations, the efficiency of using this class is higher than that of ArrayList. The bottom layer uses two-way linked list (a data storage method in data structure) to store data

11.3.1 ArrayList source code analysis

1. In case of JDK 7

ArrayList list = new ArrayList();
list.add(123);

The bottom layer creates an Object[] elementData with a length of 10. At this time, adding an element (such as integer data 123) is actually equivalent to executing:

elementData[0] = new Integer(123);

If the addition results in insufficient capacity of the array (or exceeding the length of the array), the capacity will be expanded. By default, the capacity expansion is 1.5 times of the original, and the data in the original array needs to be copied to the new array.

In order to reduce capacity expansion (which requires copying and takes time), the constructor public ArrayList(int capacity) with parameters is generally used to initialize the capacity when creating objects:

ArrayList list = new ArrayList(int capacity);

2. In case of JDK 8

ArrayList list = new ArrayList();

The underlying Object[] elementData is initialized to {}, and an array with a length of 10 is not created. When the method is called for the first time to add, the bottom layer creates an array with a length of 10 and adds data 123 to Object[] elementData. Subsequent operations are consistent with those in JDK 7.

To sum up, the object creation of ArrayList in JDK 7 is similar to the hungry man type of singleton, while the object creation of ArrayList in JDK 8 is similar to the lazy man type of singleton, which delays the creation of array and saves memory.

11.3.2 LinkedList source code analysis

LinkedList list = new LinkedList();
list.add(123);

The first and last attributes of Node type are declared internally, and the default value is null. When the element is added, 123 is encapsulated into the Node and the Node object is created. Where, Node is defined as:

private static class Node<E> {//It embodies the two-way linked list of LinkedList
    E item;
    Node<E> next;
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

11.3.3 common methods of list interface

In addition to the methods inherited from the Collection collection, the List interface also adds some methods to operate the Collection elements according to the index.

@Test
public void test1(){
    ArrayList list = new ArrayList();
    list.add(123);
    list.add(456);
    list.add("AA");
    list.add(new Date());
    list.add(456);

    //boolean add(Object obj) adds the element obj at the end of the collection
    //boolean add(int index,Object ele): inserts an ele element at the index position
    list.add(1,"BB");
    System.out.println(list);

    //Add all (int index, collection ELES): add all elements in eles from the index position
    List list1 = Arrays.asList(1, 2, 3);
    list.addAll(list1);
    System.out.println(list);

    //Object get(int index): get the element at the specified index position
    System.out.println(list.get(0));

}

The results are as follows:

@Test
public void test2(){
    ArrayList list = new ArrayList();
    list.add(123);
    list.add(456);
    list.add("AA");
    list.add(new Date());
    list.add(456);

    //int indexOf(Object obj): returns the position where obj first appears in the collection. If it does not exist, it returns - 1
    int index = list.indexOf(456);
    System.out.println(index);
    System.out.println(list.indexOf(4567));//If there is no corresponding element, - 1 is returned

    //int lastIndexOf(Object obj): returns the last occurrence of obj in the collection. If it does not exist, it returns - 1
    System.out.println(list.lastIndexOf(456));

    //Object remove(int index): removes the element at the specified index position and returns this element, which constitutes an overload with the previous method remove in the Collection
    Object obj = list.remove(0);
    System.out.println(obj);
    System.out.println(list);

    //Object set(int index,Object ele): sets the element of the specified index position to ele
    list.set(1,"CC");
    System.out.println(list);

    //List subList(int fromIndex,int toIndex): returns the sublist between [fromindex, toindex]
    List subList = list.subList(2, 4);
    System.out.println(subList);
    System.out.println(list);
}

The results are as follows:

@Test
public void test3(){
    ArrayList list = new ArrayList();
    list.add(123);
    list.add(456);
    list.add("AA");
    list.add(new Date());
    list.add(456);

    //Method 1: Iterator iterator
    Iterator iterator = list.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
    System.out.println("***********************");
    //Mode 2: enhance for
    for(Object obj : list){
        System.out.println(obj);
    }
    System.out.println("***********************");
    //Method 3: ordinary for
    for (int i = 0; i < list.size(); i++) {
        System.out.println(list.get(i));
    }

}

The results are as follows:

//A small exercise: the difference between remove(int index) and remove(Object obj)
@Test
public void test4(){
    ArrayList list = new ArrayList();
    list.add(1);
    list.add(2);
    list.add(3);

    //        list.remove(2);// Delete element with index 2
    //        System.out.println(list);//1 2
    list.remove(new Integer(2));//Delete element with value 2
    System.out.println(list);//1 3
}

11.4 Collection sub interface 2: Set (less used)

Set interface: single column Collection, used to store objects one by one. There is no additional definition of new methods, and the methods declared in the Collection are used. There are three implementation classes: HashSet, LinkedSet and TreeSet. To customize the implementation class, you must override equals() and hashCode() in the Collection interface

HashSet: as the main implementation class of the Set interface, the thread is unsafe and can store null values
LinkedHashSet: subclass of HashSet. When traversing its internal data, it can be traversed in the order of addition
TreeSet: you can sort according to the specified attributes of the added object

11.4.1 HashSet

The process of adding element a to the HashSet (related to the following HashMap):

1. First call the hashCode() method of the class where element a is located to calculate the hash value of element a;
2. This hash value calculates the storage position or index (disorder) in the underlying array of HashSet through * * some algorithm (mentioned later) * * and judges whether there are elements in this position of the array;
If there is no element in the location, the addition is successful. If there are other elements b (or multiple elements in the form of linked list) in this position, compare the hash values of element a and element b:
① If the hash values are different, element a is added successfully;
② If the hash value is the same, you need to call equals() of the class where element a is located to compare whether the two contents are the same.
If true is returned, it means that the element values are the same, and the addition fails (non repeatability);
If false is returned, the element is added a successfully. Element a and the original element are stored in a linked list. The original element is still placed in the array, and then it points to element a.

The class of data added to the Set must override hashCode() and equals(), and the overridden hashCode() and equals() must be consistent as far as possible: that is, equal objects must have equal hash values.

//HashSet
@Test
public void test1(){
    HashSet hashSet = new HashSet();
    hashSet.add(123);
    hashSet.add("AA");
    hashSet.add(new Date());
    hashSet.add('B');
    hashSet.add(1.4);
    hashSet.add('B');
    System.out.println(hashSet);
}

The results are as follows:

11.4.2 LinkedHashSet

The disorder of the Set interface does not mean that the traversal order of elements is out of order, but that when adding elements to the Set, they are out of order, rather than adding elements sequentially by index like an array. As a subclass of HashSet, LinkedHashSet maintains two references while adding data, recording the previous data and the latter data of this data. Therefore, for frequent traversal operations, the efficiency of LinkedHashSet is higher than that of HashSet, and the traversal is printed in the order of addition.

//LinkedHashSet
@Test
public void test2(){
    LinkedHashSet linkedHashSet = new LinkedHashSet();
    linkedHashSet.add(123);
    linkedHashSet.add("AA");
    linkedHashSet.add(new Date());
    linkedHashSet.add('B');
    linkedHashSet.add(1.4);
    System.out.println(linkedHashSet);
}

The results are as follows:

11.4.3 TreeSet (just understand)

The data added to TreeSet must be objects of the same class.

In natural sorting, the standard for comparing whether two objects are the same is: compareTo() returns 0 instead of equals()
In custom sorting, the criterion for comparing whether two objects are the same is: compare() returns 0 and is no longer equal()

11.5 Map interface (key points!!!)

Map is double column data, which stores the data of key value pairs, similar to the function y=f(x) in mathematics
It has five implementation classes: HashMap, LinkedHashMap, TreeMap, Hashtable and Properties

Implementation classdifference
HashtableThe old implementation class (basically not used) is thread safe and inefficient. It can't store null key s and value s
PropertiesSubclass of Hashtable, which is commonly used to process configuration files. Key values are of String type
HashMapThe main implementation class of Map is thread unsafe and efficient. It can store null key and value
LinkedHashMapThe subclass of HashMap adds a pile of pointers to the previous and subsequent elements on the basis of the original underlying structure of HashMap. Therefore, when traversing map elements, traversal can be realized in the order of addition. For frequent traversal operations, the execution efficiency is higher than HashMap
TreeMapIn this case, you can sort by "key value" or "key value" of traversal

11.5.1 understanding of map structure

Keys in Map: unordered and non repeatable. Use the Set set to store all keys; - > The class where the key belongs needs to override equals() and hashCode() (take HashMap as an example here)
value in Map: unordered and unrepeatable. Use Collection to store all values; - > Class to override equals()
A key value pair constitutes an entry object
Entries in Map: unordered and non repeatable. Use Set set to store all entries

11.5.2 underlying implementation principle of HashMap Source code to see

Bottom layer of JDK7:

HashMap map = new HashMap();

After instantiation, the bottom layer creates a one-dimensional array Entry[] table with a length of 16,

.......
map.put(key1.value1);

1. First, call hashCode() of the class where key1 is located to calculate the hash value of key1. After the hash value is calculated by some algorithm, the storage location in the Entry array is obtained.
2. If the data in this position is empty, key1-value1 is added successfully;
3. If it is not empty (it means that there are one or more data in the form of linked list in this location), compare the hash value of key1 with the original data:
① If the hash value is different, key1-value1 is added successfully;
② If the hash value is the same as the hash value of a certain data (key2-value2), call equals() of the class where key1 is located to continue to compare whether the value of the key is the same. If false is returned, the addition is successful; If true is returned, Value2 is replaced with value1
③ Note: after the addition is successful, key1 and value1 and the original data are stored in a linked list.

In the process of continuous addition, the problem of capacity expansion will be involved. When the critical value is exceeded (and the location to be stored is not empty), the default capacity expansion method is: expand the capacity to twice the original capacity and copy the original data.

Compared with JDK7, the bottom layer of JDK8 is different:
① In new HashMap(), the bottom layer does not create an array with a length of 16;
② Array is Node [] instead of Entry [];
③ An array with a length of 16 is created only when put() is called for the first time to add elements;
④ The underlying structure of JDK7 is only array + linked list, while the underlying structure of JDK8 is array + linked list + red black tree. When the number of data in the form of linked list of elements at an index position of the array is > 8 and the length of the array is > 64, all data at the index position is stored in red black tree instead.

11.5.3 underlying implementation principle of LinkedHashMap (just understand)

//In the source code:
static class Entry<K,V> extends HashMap.Node<K,V> {
    Entry<K,V> before, after;//Be able to record the sequence of added elements
    Entry(int hash, K key, V value, Node<K,V> next) {
        super(hash, key, value, next);
    }
}

For example:

11.5.4 common methods in map

The following are common methods in Map, mainly including: add, query, modify and delete, namely CRUD

//Addition, modification and deletion
@Test
public void test2(){
    Map map = new HashMap();
    //Object put(Object key,Object value) adds the specified key value to the current map object
    //If the key s are the same, they will be replaced and modified in a disguised manner
    map.put("AA",123);
    map.put("BB",4214);
    map.put("DD",891);
    map.put("CC",523);
    map.put("AA",12613);//Modified the value corresponding to "AA"
    System.out.println(map);

    System.out.println("******************");
    Map map1 = new HashMap();
    map1.put("EE",198);
    map1.put("FF",198);
    map1.put("GG",198);
    System.out.println(map1);
    map1.put("AA",198);
    //void putAll(Map m) stores all key value pairs in m into the current map
    map1.putAll(map);
    System.out.println(map1);
    map1.put("AA",299);
    System.out.println(map1);

    System.out.println("******************");
    //Object remove(object key) removes the key value pair of the specified key and returns value
    Object value = map1.remove("CC");
    System.out.println(value);
    System.out.println(map1);

    System.out.println("******************");
    //void clear() clears all data in the current map
    map1.clear();//Different from map1 = null, only the element is cleared, and map1 still exists
    System.out.println(map1);
}

The results are as follows:

//check
@Test
public void test3(){
    Map map = new HashMap();
    map.put("AA",123);
    map.put("BB",4214);
    map.put("DD",891);
    map.put("CC",523);
    System.out.println(map);
    //Object get(Object key) gets the value corresponding to the specified key
    System.out.println(map.get("AA"));
    System.out.println("******************");

    //Whether the boolean containsKey(Object key) contains the specified key
    //Whether the boolean containsKey(Object value) contains the specified value
    System.out.println(map.containsKey("AA"));
    System.out.println(map.containsValue(891));

    System.out.println("******************");
    //int size() returns the number of key value pairs in the map
    //boolean isEmpty() determines whether the current map is empty
    //boolean equals(Object obj) determines whether the current map and parameter object obj are equal
    System.out.println(map.size());
    System.out.println(map.isEmpty());
}

The results are as follows:

//Value
@Test
public void test4(){
    Map map = new HashMap();
    map.put("AA",123);
    map.put("BB",4214);
    map.put("DD",891);
    map.put("CC",523);

    //Take out all keys: Set keySet()
    Set set = map.keySet();
    Iterator iterator = set.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }

    System.out.println("***************");
    //Take out all value: Collection values()
    Collection values = map.values();
    for(Object obj:values){
        System.out.println(obj);
    }

    System.out.println("***************");
    //Take out all key value: entrySet()
    //Method 1: entrySet()
    Set entrySet = map.entrySet();
    Iterator iterator1 = entrySet.iterator();
    while(iterator1.hasNext()){
        Object obj = iterator1.next();
        //All elements in the entry set collection are entries
        Map.Entry entry = (Map.Entry)obj;
        System.out.println(entry.getKey()+"------->"+entry.getValue());
    }
    //Mode 2:
    Set keySet = map.keySet();
    Iterator iterator2 = keySet.iterator();
    while (iterator.hasNext()){
        Object key = iterator2.next();
        Object value = map.get(key);
        System.out.println(key+"------->"+value);
    }

}

The results are as follows:

11.6 Collections tool class

Collections is a tool class that operates on sets, lists, maps, etc. (tool classes are generally static methods). It provides a series of static methods to sort, query and modify the Set elements. It also provides methods to Set immutable Set objects and realize synchronous control of Set objects.

Common methods are as follows:

methodfunction
public void reverse(List)Invert elements in List
public void shuffle(List)Randomly sort the List elements (the results are different each time)
public void sort(List)Sorts the elements of the specified List set in ascending order according to the natural sorting of the elements
public void sort(List, Comparator)Sort the List according to the order generated by the specified Comparator
public void swap(List list, int i, int j)Exchange the elements at i and j in the list set
methodfunction
public int frequency(Collection, Object)Returns the number of occurrences of the specified element in the specified collection
public void copy(List dest, List src)Copy the contents of src to dest
boolean replace(List list, Object oldVal, Object newVal)Replace the old value oldVal with the new value newVal

Synchronization control methods, such as public List synchronizedList(), public Map synchronizedMap()..., can make the specified collection packaged into a thread synchronized collection, which can solve the thread safety problem when multiple threads access the collection concurrently.

@Test
public void test1() {
    List list = new ArrayList();
    list.add(123);
    list.add(12);
    list.add(19);
    list.add(10);
    list.add(-3);
    list.add(89);
    System.out.println("The initial set is:" + list);

    Collections.reverse(list);
    System.out.println("Reverse order of previous set:" + list);

    Collections.shuffle(list);
    System.out.println("Random sorting of previous set:" + list);

    Collections.sort(list);
    System.out.println("Sort previous set in ascending order:" + list);

    Collections.swap(list, 0, 1);
    System.out.println("Previous set element exchange:" + list);

    int frequency = Collections.frequency(list, 123);
    System.out.println("123 A total of" + frequency + "second");

    //        Report exception Java lang.IndexOutOfBoundsException: Source does not fit in dest
    //        List dest = new ArrayList();
    //        Collections.copy(dest,list);

    List dest = Arrays.asList(new Object[list.size()]);
    Collections.copy(dest,list);
    System.out.println("Copy method copy" + dest);

    //list1 at this time is thread safe, and other collections are similar. I won't repeat it here
    List list1 = Collections.synchronizedList(list);
}

The results are as follows:

12. Generics

In traditional Chinese medicine stores, labels are pasted on the outside of each drawer, such as "Astragalus", "Angelica" and so on;
There are many bottles on the shopping rack in the supermarket. What's in each bottle has a label.

The collection container cannot determine what type of objects are stored in this container in the design phase / declaration phase, so before JDK 5.0, the element type can only be designed as Object. For example, public ArrayList(Object obj), but because the Object type is the parent class of all classes, and because of the polymorphism of the class, it can be any type. Sometimes when creating an Object, you only want to pass in String parameters or methods, and only return String data. At other times, I only want to use Integer type, so it is easy to cause confusion.
After JDK 5.0, use generics to solve the problem. Because at this time, except the type of the element is uncertain, other parts are determined, such as how to save and manage the element. Therefore, at this time, the type of the element is designed as a parameter, which is called generics. For example: Collection < E >, list < E >, ArrayList < E >, where < E > is the parameter type, that is, generic type.

The main advantage of using generics is the ability to check for errors at compile time rather than at run time

12.1 using generics in Collections

//Take ArrayList as an example
@Test
public void test2() {
    ArrayList<Integer> integers = new ArrayList<>();//The basic data type cannot be used here because it will not be boxed automatically
    integers.add(89);
    integers.add(92);
    integers.add(73);
    integers.add(70);
    //When compiling, type checking will be carried out to ensure the safety of data
    //        integers.add("Tom");// At this time, if you add a string, an error will be reported
    for (Integer score : integers){
        System.out.println(score);
    }
}

//Take HashMap as an example
@Test
public void test3(){
    Map<String,Integer> map = new HashMap<String,Integer>();
    map.put("Tom",12);
    map.put("Mary",123);
    map.put("Mike",35);

    //Nesting of generics
    //entrySet() returns the Set type. The generic type of Set type is Entry, and the generic type of Entry is String (type of key) and Integer (type of value)
    Set<Map.Entry<String, Integer>> entry = map.entrySet();
    //iterator() returns the iterator type, as above, using generic nesting
    Iterator<Map.Entry<String, Integer>> iterator = entry.iterator();
    while (iterator.hasNext()){
        Map.Entry<String,Integer> e = iterator.next();
        String key = e.getKey();
        Integer value = e.getValue();
        System.out.println(key + "----" + value);
    }
}

The results are as follows:

Summary:
1. When the collection interface or collection class is in JDK 5.0, it is modified to a generic structure;
2. When instantiating a collection, you can specify the specific generic type;
3. After specifying, when defining a class or interface in a collection class or interface, the internal structure (such as method, constructor, attribute, etc.) uses this type. For example, add (E) - > Add (integer E);
4. Note: the type of generic type must be a class. Where the basic data type is required, the packaging class can be used;
5. If the generic type is not specified during instantiation, the default type is Java Lang. object type.

12.2 custom generics

12.2.1 generic classes and generic interfaces

Taking generic classes as an example, generic interfaces are similar.

class Order<T> {//At present, we don't know what type it is. It will be given when instantiating
    String orderName;
    int orderId;

    //The internal structure of the class can use the generics of the class
    T orderT;

    public Order() {
    }

    public Order(String orderName, int orderId, T orderT) {
        this.orderName = orderName;
        this.orderId = orderId;
        this.orderT = orderT;
    }

    public T getOrderT() {
        return orderT;
    }

    public void setOrderT(T orderT) {
        this.orderT = orderT;
    }
}

class SubOrder extends Order<String> {//When the subclass inherits from the parent class, it indicates that the generic type is String, so SubOrder is not a generic class at this time
}

class SubOrder1<T> extends Order<T> {//SubOrder1 is still a generic class at this time
}
@Test
public void test1() {
    //If a generic class is defined and the instantiation does not specify the generic type of the class, the generic type is considered to be Object type
    //Requirement: if the custom class is generic, it is customary to specify the generic type of the class when instantiating
    Order<Integer> tOrder = new Order<>("Zhang San", 1, 123);//Indicates that the generic type is Integer type
    //Generally, Integer is written in the front, but not later. It can infer the type. This is a new feature of JDK 7.0
    System.out.println(tOrder.getOrderT());
    tOrder.setOrderT(456);
    System.out.println(tOrder.getOrderT());
}
@Test
public void test2() {
    //Because the subclass indicates the generic type when inheriting the parent class with generic type. When instantiating subclass objects, it is no longer necessary to specify generics
    SubOrder subOrder = new SubOrder();
    subOrder.setOrderT("Zhang San");
    //        subOrder.setOrderT(123);// Compilation failed
    System.out.println(subOrder.orderT);

    SubOrder1<String> subOrder1 = new SubOrder1<>();//Since SubOrder1 is a generic class, you need to specify the type
    subOrder1.setOrderT("Li Si");
    System.out.println(subOrder1.orderT);

}

The results are as follows:

Order<String> order1 = new Order();
Order<Integer> order2 = new Order();
order1 = order2;//Compilation fails. References with different generics cannot be assigned to each other
public static void show(T orderT){//The compilation fails. The generic type of class cannot be used in static methods
    System.out.println(orderT)
}
public class MyException<T> extends Exception{//Compilation failed because an exception class cannot be declared as a generic class
}

12.2.2 generic methods

Methods can also be generic, regardless of whether their class is generic or not. Generic parameters can be defined in generic methods. The type of parameter is the type of incoming data.

Generic methods can be declared static. Reason: generic parameter type E is determined at the time of call, not T at the time of instantiation.

//Generic method, assuming that it is declared in the generic class Order
//The method here can be declared as static, because the generic method has nothing to do with whether its class is generic or not
public static <E> List<E> copyFromArrayToList(E[] arr) {
    ArrayList<E> list = new ArrayList<>();
    for (E e : arr) {
        list.add(e);
    }
    return list;
}
@Test
public void test3() {
    Order<String> order = new Order();
    Integer[] arr = new Integer[]{1, 2, 3, 4};
    //When a generic method is called, it indicates the type of generic parameter
    List<Integer> list = order.copyFromArrayToList(arr);
    System.out.println(list);
}

The results are as follows:

Generic methods are mostly used for database operations.

12.3 the embodiment of generics in inheritance

Suppose class A is the parent / parent interface of class B, but there is no child parent / child parent interface relationship between G < a > and G < b > and they are in parallel.

@Test
public void test1(){
    //Suppose Person is the parent of Man
    Person[] persons = null;//For simplicity, the object is not created here, and null is directly assigned
    Man[] men = null;
    //Person is the parent class of Man, so according to polymorphism, the following assignment can be performed directly
    persons = men;
    Person p =,em[0];
    
    //But the following generics are not allowed
    List<Object> list1 = null;
    List<String> list2 = null;
    //    list1 = list2;// If the compilation fails, LIST1 and List2 do not have a child parent relationship at this time
}

In addition, at this time, a < g > is the parent of B < g >, such as abstractlist < Object > and ArrayList < Object >. The same applies to interfaces

@Test
public void test2(){
    AbstractList<String> list1 = null;//Parent class
    List<String> list2 = null;//Interface
    ArrayList<String> list3 = null;//Implementation class and subclass
    
    list1 = list3;//Abstractlist < string > class is the parent of ArrayList < string > class
    list2 = list3;//ArrayList < string > class is the implementation class of list < string > interface
	
    //list2 = list3 is equivalent to the following
    List<String> list4 = new ArrayList<>();

}

12.4 Wildcards

12.4.1 wildcards without restrictions

Write a method to print all elements of a collection Collectoin:

1. The most original way:

public void printColllection(Collection c){
    Iterator iterator = c.iterator();
    while(iterator.hasNext()){
        System.out.println(iterator.next());        
    }    
}

2. Use generics without wildcards:

public void printColllection(Collection<Object> c){
    for(Object e : c){
        System.out.println(e);
    }
}

Although using generics can reduce one line of code, it is much less useful than method 1, because method 1 can use any Collection implementation class type as a parameter, while method 2 can only use Collection < Object >, which is not the parent class of all collections. The parent class of all collections is Collection <? >, In fact, it is a Collection whose element type can match any type, which is called wildcard. The above only needs to change the object in the parameter to?, This is the following method 3.

3. Use generics with wildcards:

public void printColllection(Collection<?> c){
    for(Object e : c){
        System.out.println(e);
    }
}

Similarly, List <? > It is the parent class of various generic lists such as List < string >, List < Object >. The same is true for other types of wildcards, so I won't repeat it.

When reading the elements in c, it is always safe, because no matter what the real type of c is, it must be the Object type. You can call the get(int index) method to read its return value. Since the return value type is unknown, but it must be Object type, it is received by reference of Object type.

Object obj = c.get(0);//Returns the element value with index 0

Because we don't know the element type of c, we can't add objects to it, and objects of Person type can't be added / assigned to the reference of Man or other subclasses.

Collection<?> c = new ArrayList<String>();
c.add(new Object());//Compile time error. The type of c is unknown and cannot be added
//Although null can be passed, it has no practical significance

It should be noted that wildcards cannot be used in the declaration of generic methods and generic classes and the creation of objects.

12.4.2 Bounded Wildcards

Wildcard <? > Allow all generic reference calls. At this time, if you want to call a generic type with restrictions (such as inheriting a class or implementing an interface), you can set the restrictions through extensions and super.

①<? Extensions Number > only allows reference calls with generics of Number and Number subclasses (extensions - > inherit Number), similar to (- ∞, Number];
②<? Super Number > only allows reference calls with generic Number and Number parent class (super - > parent class Number), similar to [Number, ∞];
③<? Extensions compatible > only the generic type is allowed to be called by reference of the implementation class that implements the compatible interface.

class Person1 {
}

class Student extends Person1 {
}
//Wildcard with restrictions
@Test
public void test4() {
    List<? extends Person1> list1 = null;
    List<? super Person1> list2 = null;

    List<Student> list3 = new ArrayList<Student>();
    List<Person1> list4 = new ArrayList<Person1>();
    List<Object> list5 = new ArrayList<Object>();

    //        list1 = list2;// Compilation failed and the scope is inconsistent
    list1 = list3;//Generic Student is a subclass of Person1, and this reference can be assigned
    list1 = list4;//Generic Person1, which can be called
    //        list1 = list5;// The compilation fails. The generic Object is the parent class of Person1 and cannot be assigned. Similarly, the parent class Object cannot assign a value to the subclass reference

    //        list2 = list3;// Compilation failed. Student is not the parent class of Person1
    list2 = list4;//Generic Person1, which can be assigned
    list2 = list5;//Generic Object is the parent class of Person1 and can be assigned values

    //1. Read data
    list1 = list4;
    Object obj = list1.get(0);//Object type can receive
    Person1 person1 = list1.get(0);//A smaller range of Person types can also be accepted
    //        Student s = list1.get(0);// The student type cannot be smaller
    list2 = list4;
    Object object = list2.get(0);//Only Object can receive
    //        Person1 person2 = list2.get(0);// If the range is smaller, the person type can also be received

    //2. Write data: wildcard generics with restrictions can write some data
    //        list1.add(new Student()) / / the compilation fails and data cannot be added

    //Compile through
    list2.add(new Person1());
    list2.add(new Student());

}

Keywords: Java

Added by Haktar on Thu, 17 Feb 2022 17:25:32 +0200