java review notes -- Shang Silicon Valley

Keywords: Java Interview

Chapter 1 Java overview

1.1 Java history

Java was born in SUN (Stanford University Network), and SUN was acquired by Oracle (Oracle) in 2009.

The father of Java is James gosling.

JDK1.0 was released in 1996.

The latest version is java 12. We learned Java 8.

1.2 main features of Java language

  • Feature 1: object oriented

Two basic concepts: class and object

Three characteristics: encapsulation, inheritance and polymorphism

  • Feature 2: robustness

It absorbs the advantages of C/C + + language, but removes the parts that affect the robustness of the program (such as pointer, memory application and release, etc.), and provides a relatively safe memory management and access mechanism

  • Feature 3: cross platform

Cross platform: applications written in Java language can run on different system platforms. Write once, run anywhere.

Principle: just install a Java virtual machine (JVM) on the operating system that needs to run Java applications. The JVM is responsible for the running of Java programs in the system. Because of the JVM, the same Java program can be executed in three different operating systems. In this way, the cross platform of Java program is realized.

1.3 Java environment construction

1.3.1 JDK,JRE,JVM

Java developers need to install JDK. If you just run a java program, you only need to follow the JRE.

JDK (Java Development kits): Java development kit.

JRE (Java Runtime Environment): Java Runtime Environment.

JVM (Java Virtual Machine): Java Virtual Machine.

JDK = JRE + development tools (javac.exe,java.exe,javadoc.exe, etc.)

JRE = JVM + core class library (common classes: String, date time, mathematics, collection, IO, network, multithreading, etc.)

1.3.2 Java environment construction

1. Install JDK

2. Configure the JDK development tool directory to the path environment variable

For example: D: \ program files \ Java \ jdk1.8.0_ 51\bin;

Note: this installation directory is subject to your own installation directory

(1) Why configure path?

It is hoped that when using tools such as javac.exe on the command line, the directory where the tool is located can be found in any directory.

(2) How to configure environment variables?

Right click [Computer] properties, select [advanced system settings], select [advanced], select [environment variable], select [system environment variable], edit path, and add D: \ program files \ Java \ jdk1.8.0 in front of [original value of path]_ 51\bin;

1.4 first Java application

class HelloWorld{
    public static void main(String[] args){
        System.out.print("Hello Java!");
    }
}

1.4.1 development steps of Java program

Three steps:

1. Edit / write source code

Requirement: the source file must be a. java file

2. Compile

Purpose: compile the source file into a. class bytecode file (because the JVM only knows bytecode)

Tool: javac.exe

Format:

javac Source file name.java

3. Run

Tool: java.exe

Format:

java Class name
java Bytecode file name

Requirement: the class that can be run must contain the main method

1.4.2 structure and format of Java program

Structure:

class{
    method{
        sentence;
    }
}

Format:

(1) Indent one Tab at each level

(2) The left half of {} is at the end of the line, and the right half is a separate line, aligned with the beginning of the line of "{" paired with it

1.4.3 Java program entry

The entry to the Java program is the main method

public static void main(String[] args){
    
}

1.4.4 Java annotations

1. Single line note

//Note Content 

2. Multiline comment

/*
Note Content 
*/

3. Document notes

/**
Document notes (explained in the notes section later)
*/

1.5 problems needing attention when writing Java programs

1. Character encoding problem

When the character encoding of cmd command line window is inconsistent with that of. java source file, how to solve it?

[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-QhlgFJ2i-1631456883921)(imgs/1557881223916.png)]

Solution 1:

In Notepad + + and other editors, modify the character encoding of the source file

[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-2237zMk2-1631456883930)(imgs/1557881271819.png)]

Solution 2:

When using the javac imperative, you can specify the character encoding of the source file

javac -encoding utf-8 Review01.java

2. Case problem

(1) Source file name:

It is not case sensitive. We suggest that you still distinguish between cases

(2) Bytecode file name and class name

Case sensitive

(3) In code

Case sensitive

3. Is the source file name consistent with the class name?

(1) Must the source file name be consistent with the class name? public?

If the class is not public, the source file name can be inconsistent with the class name.

If the class is public, the source file name must be consistent with the class name.

We recommend that you, whether public or not, keep consistent with the source file name, and try to write only one class in a source file for easy maintenance.

(2) Can there be multiple classes in a source file? public?

There can be multiple classes in a source file, and multiple. class bytecode files will be generated after compilation.

However, a source file can only have one public class.

(3) Must main be in the public class?

no

However, when writing code later, basically main is used to being in the public class.

Chapter 2 basic syntax of Java

2.1 identifier

In short, any part named by the programmer can be called an identifier.

That is, the character sequence named for classes, variables, methods, packages, etc. is called identifiers.

1. Naming rules for identifiers

(1) Java identifiers can only use 26 English letters, uppercase and lowercase, 0-9 numbers, underscores and dollar symbols$

(2) Java keywords (including reserved words) and special values cannot be used

(3) The number cannot begin

(4) Cannot contain spaces

(5) Strictly case sensitive

2. Naming conventions for identifiers

(1) See the name and know the meaning

(2) Class name, interface name, etc.: the first letter of each word is capitalized in the form of xxxyyyzz,

For example: HelloWorld, String, System, etc

(3) Variable, method name, etc.: start from the second word with the first letter in uppercase and the rest in lowercase. Form: xxxyyyzz,

For example: age,name,bookName,main

(4) Package name, etc.: each word is lowercase, and points are used between words. Segmentation, form: xxx.yyy.zzz,

For example: java.lang

(5) Constant name, etc.: each word is capitalized and separated by underscore in the form of XXX_YYY_ZZZ,

For example: MAX_VALUE,PI

2.2 variables

2.2.1 concept of variable

Function of variable: it is used to store data and represents a storage area of memory. The value in the variable can be changed.

2.2.2 three elements of variables

1. Data type

2. Variable name

3. Value

2.2.3 what should we pay attention to when using variables?

1. Declare before use

If there is no declaration, an error "symbol not found" will be reported

2. Must be initialized before use

If it is not initialized, an "uninitialized" error will be reported

3. Variable has scope

If the scope is exceeded, an "symbol not found" error will also be reported

4. Cannot duplicate names in the same scope

2.2.4 declaration and assignment of variables, syntax format used?

1. Syntax format of variable declaration:

Data type variable name;
For example:
int age;
String name;
double weight;
char gender;
boolean isMarry;

2. Syntax format of variable assignment:

Variable name = value;
For example:
age = 18;
name = "Chai Linyan"; //The value of the string must use ''
weight = 44.4;
gender = 'female';//Single character values must use ''
isMarry = true;

3. Syntax format used for variable:

Direct reference by variable name

For example:
(1)The value of the output variable
System.out.print(name);
System.out.print("full name:" + name);//The contents of "" are displayed as is
System.out.print("name = " + name);
(2)calculation
age = age + 1;

2.3 data type

2.3.1 classification of Java data types

1. Basic data type

8 types: integer series (byte,short,int,long), floating point (float,double), single character (char), boolean (boolean)

2. Reference data type

Class, interface, array, enumeration

2.3.2 basic data types of Java

1. Integer series

(1) Byte: byte type

Memory occupied: 1 byte

Storage range: - 128 ~ 127

(2) Short: short integer type

Memory occupied: 2 bytes

Storage range: - 32768 ~ 32767

(3) int: integer

Memory occupied: 4 bytes

Storage range: - 31st power of 2 ~ 31st power of 2 - 1

(4) long: integer

Memory occupied: 8 bytes

Storage range: - 63rd power of 2 ~ 63rd power of 2 - 1

Note: if you want to represent a constant number, which is of type long, you need to add L after the number

2. Floating point series (decimal)

(1) float: single precision floating point

Memory occupied: 4 bytes

Precision: 6 ~ 7 digits after the decimal point of scientific notation

Note: if you want to indicate that a constant number is of float type, you need to add f or F after the number

(2) Double: double precision floating point

Memory occupied: 8 bytes

Accuracy: 15 ~ 16 digits after the decimal point of scientific notation

3. Single character type

char: character type

Memory occupied: 2 bytes

Character set used in Java: Unicode encoding set

Three representations of characters:

(1) 'one character'

For example, 'A', '0', 'not yet'

(2) Escape character

\n: Line feed
\r: enter
\t: Tab key
\\: \
\": "
\': 
\b: Delete key Backspace

(3) The hexadecimal type of the Unicode encoded value of the \ u character

For example: \ u5c1a stands for 'still'

4. Boolean type

boolean: only true or false can be stored

2.3.3 hexadecimal (understood, can be ignored temporarily)

1. Binary classification:

(1) Decimal system

Digital composition: 0-9

Carry rule: every decimal

(2) Binary

Digital composition: 0-1

Carry rule: every two into one

(3) Octal

Digital composition: 0-7

Carry rule: every eight into one

(4) Hex

Digital composition: 0-9, AF (or AF)

Carry rule: one every sixteen

2. Please use four types of hexadecimal to represent 10, and output its results: (understand)

(1) Decimal: normal representation

System.out.println(10);

(2) Binary: beginning with 0b or 0b

System.out.println(0B10);

(3) Octal: beginning with 0

System.out.println(010);

(4) Hex: beginning with 0x or 0x

System.out.println(0X10);

3. Why is byte - 128 ~ 127? (understanding)

1 byte: 8 bits

0000 0001 ~ 0111 111 ==> 1~127

1000 0001 ~ 1111 1111 ==> -127 ~ -1

0000 0000 ==>0

1000 0000 = = > - 128 (special provisions)

*Explanation: * storage of computer data (understand)

Computer data is stored in the form of binary complement, and the highest bit is sign bit, 1 is negative and 0 is positive.

Regulations: the complement of positive numbers is the same as the inverse code and the original code, which is called three in one;

The complement of a negative number is different from the inverse code and the original code:

Original code of negative numbers: convert decimal to binary, and then set the highest bit to 1

Inverse code of negative numbers: Based on the original code, the highest bit remains unchanged, and the other bits are reversed (0 becomes 1, 1 becomes 0)

Complement of negative number: inverse code + 1

For example: byte type (1 byte, 8 bits)

25 = = > original code 0001 1001 = = > inverse code 0001 1001 -- > complement code 0001 1001

-25 = = > original code 1001 1001 = = > inverse code 1110 0110 = = > complement code 1110 0111

The bottom layer uses addition instead of subtraction: - 128 = = "- 127-1 = =" - 127 + (- 1)

​ -127- -1 ==> -127 + 1

4. Student questions and answers?

(1) Why is the storage range of float (4 bytes) larger than that of long (8 bytes)?

(2) Why is double (8 bytes) more accurate than float (4 bytes)?

Because the bottom layer of float and double is also binary, first convert the decimal to binary, then express the binary as scientific notation, and then save only:

(1) Sign bit (2) exponential bit (3) trailing digit

For details, see storage methods of float and double data.docx

2.3.4 conversion of basic data types

1. Automatic type conversion

(1) When a value with a small storage range (constant value, variable value, result value of expression calculation) is assigned to a variable with a large storage range,

byte->short->int->long->float->double

​ char->

int i = 'A';//char is automatically upgraded to int
double d = 10;//int is automatically upgraded to double

(2) When a data type with a small storage range is mixed with a data type with a large storage range, it will be calculated according to the largest type

int i = 1;
byte b = 1;
double d = 1.0;

double sum = i + b + d;//Mixed operation, upgrade to double

(3) When the byte, short and char data types perform arithmetic operations, they are processed according to the int type

byte b1 = 1;
byte b2 = 2;
byte b3 = (byte)(b1 + b2);//b1 + b2 are automatically upgraded to int

char c1 = '0';
char c2 = 'A';
System.out.println(c1 + c2);//113 

(4) boolean type does not participate

2. Cast type

(1) When a value with a large storage range (constant value, variable value, result value of expression calculation) is assigned to a variable with a small storage range, forced type conversion is required

double->float->long->int->short->byte

​ ->char

Tip: there is a risk of loss of accuracy or overflow

double d = 1.2;
int num = (int)d;//Loss accuracy

int i = 200;
byte b = (byte)i;//overflow

(2) boolean type does not participate

(3) Cast can also be used when a value wants to promote a data type

int i = 1;
int j = 2;
double shang = (double)i/j;

Tip: there is no risk of cast in this case.

2.3.5 special data type conversion

1. When "+" operation is performed between any data type and String type, the result must be String type

System.out.println("" + 1 + 2);//12

2. However, the String type cannot be converted to another type through mandatory type ()

String str = "123";
int num = (int)str;//FALSE

2.4 operators

1. Classification by operands:

(1) Unary operator: there is only one operand

For example: positive sign (+), negative sign (-), self increasing (+ +), self decreasing (–), logical non (!), bitwise negation (~)

(2) Binary operator: there are two operands

For example: add (+), subtract (-), multiply (*), divide (/), modulus (%)

Greater than (>), less than (<), greater than or equal to (> =), less than or equal to (< =), equal to (= =), not equal to (! =)

Assignment (=, + =, - =, * =, / =,% =, > > =, < < =.)

Logical and (&), logical or (|), logical XOR (^), short circuit and (& &), short circuit or (|)

Shift left (< >), shift right (> >), unsigned shift right (> >), bitwise and (&), bitwise OR (|), bitwise XOR (^)

(3) Ternary operator: three operands

For example:?:

2. Operators for Java basic data types:

(1) Arithmetic operator

(2) Assignment operator

(3) Comparison operator

(4) Logical operator

(5) Conditional operator

(6) Bitwise operator (difficult)

2.4.1 arithmetic operators

Addition:+

Subtraction:-

Multiplication:*

Division:/

Note: integer is divided by integer, and only integer part is reserved

Mold taking:% remainder

Note: the sign of the modulus result only depends on the modulus

Positive sign:+

Minus sign:-

Self increment: + + will not be put into the operand stack

Self subtraction: - will not be put into the operand stack

Principle: self increase and self decrease

++/– in the previous, the value will be increased / decreased first and then taken

++/– in the latter, take the value first, and then increase / decrease automatically

The entire expression is scanned from left to right. If the latter is calculated first, the former is temporarily placed in the "operand stack"

Code example:

int i = 1;
i++;//i=2

int j = 1;
++j;//j=2

int a = 1;
int b = a++;//(1) First take the value "1" of a and put it on the operand stack (2), a will increase automatically, a=2(3), and then assign "1" in the operand stack to b,b=1

int m = 1;
int n = ++m;//(1)m increases automatically first, m=2(2), then take the value "2" of m and put it on the local variable stack (3), and then assign "1" in the operand stack to n,n=1

int i = 1;
int j = i++ + ++i * i++;
/*
Load from left to right
(1)Calculate i first++
①Take the value "1" of i and put it on the operand stack
②i Self increasing i=2
(2)Recalculate + + i
①i First self increasing i=3
②Then take the value "3" of i and put it in the local variable
(3)Recalculate i++
①Take the value "3" of local variable i
②i Self increasing i=4
(4)Multiply first
 Use 3 * 3 = 9 in the local variable and press 9 to the operand stack
(5)Recalculate and sum
 Use 1 + 9 = 10 in the local variable stack
(6)Final assignment
j = 10
*/

2.4.2 assignment operator

Basic assignment operators:=

Extended assignment operators: + =, - =, * =, / =,% =

Note: the = left side of all assignment operators must be a variable

Extended assignment operator = if the type of the calculation result on the right is larger than that on the left, the type conversion will be forced, so the result may be at risk.

Calculation of extended assignment operator: (1) the last assignment (2) the order of loading data is to load the value of the variable on the left first, and then calculate it with the expression on the right

int i = 1;
int j = 5;
j *= i++ + j++;//j = j *(i++ + j++);
/*
(1)Load j's value "5" first
(2)In calculating i++
①Load the value "1" of i first
②Then i increases automatically, i=2
(3)Recalculate j++
①Load j's value "5" first
②Then J increases automatically, j=6
(4)Arithmetic addition
i + 5 = 6
(5)Calculate multiplication
5 * 6 = 30
(6)assignment
j = 30
*/

2.4.3 comparison operator

Greater than: >

Less than:<

Greater than or equal to: >=

Up to:<=

Equal to: = = note the difference between assignment operators=

Not equal to:=

Note: the operation result of the comparison expression must only be true/false

Comparison expressions can be operands of (1) conditional (2) logical operators

2.4.4 logical operators

The operand of a logical operator must be Boolean and the result must be Boolean

Logic and:&
Operation rule: the result is true only if both sides are true.
For example: true & true, the result is true
False & true the result is false
True & false the result is false
False & false the result is false
Logical or:|
Operation rule: as long as one of the left and right sides is true, the result is true.
For example: true | true, the result is true
false | true the result is true
true | false the result is true
false | false the result is false
Logical XOR:^
Operation rule: the result is true only when the left and right sides are different.
For example: true ^ true, the result is false
false ^ true the result is true
true ^ false the result is true
false ^ false the result is false

Logical non:!
Operation rules: Boolean negation
For example:! true is false
! false is true

Short circuit and:&&
Operation rule: the result is true only if both sides are true.
For example: true & true, the result is true
True & false the result is false
false & ? The result is false
The difference between it and logic is that when && the left is false, the right is not seen.

Short circuit or:||
Operation rule: as long as one of the left and right sides is true, the result is true.
For example: true? The result is treu
false | true the result is true
false | false the result is false
The difference between it and logic or is that when the left is true, the right is not seen.

Short circuit and and short circuit are generally used in development or more

Interview question: & & and &?

&&When the left is false, the right is not calculated

&Whether the left side is true or false, the right side should be calculated

2.4.5 conditional operators

? :

Syntax format:

Conditional expression ? Result expression 1 : Result expression 2

Operation rules:

Result of the whole expression: when the conditional expression is true, the value of result expression 1 is taken; otherwise, the value of result expression 2 is taken

Code example:

(1)boolean type
boolean marry = true;
System.out.println(marry? "married" : "unmarried");

(2)Find the most value
int i = 3;
int j = 5;
int max = i>=j ? i : j;
//When i > = j, max is assigned the value of i, otherwise it is assigned the value of j

2.4.6 bitwise operators

Move left:<<

Operation rule: a few bits to the left is equivalent to multiplying by 2

Move right: > >

Operation rule: shifting a few bits to the right is equivalent to dividing by the power of 2

Unsigned right shift: > > >

Operation rule: after moving to the right, the empty bits on the left will be directly filled with 0 without looking at the symbol bits

Bitwise AND:&

Operation rules:

1 & 1 result is 1

1 & 0 results in 0

0 & 1 result is 0

0 & 0 results in 0

Bitwise OR:|

Operation rules:

1 | 1 the result is 1

1 | 0 result is 1

0 | 1 result is 1

0 & 0 results in 0

Bitwise exclusive or:^

Operation rules:

1 ^ 1 result is 0

1 ^ 0 result is 1

0 ^ 1 result is 1

0 ^ 0 results in 0

Bitwise inversion:~

Operation rule: ~ 0 is 1

~ 1 is 0

How to distinguish whether &, |, ^ is a logical operator or a bitwise operator?

If the operand is of boolean type, it is a logical operator. If the operand is an integer, it is a logical operator.

2.4.7 operator priority

[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-tgA8513q-1631456883938)(imgs/1553858424335.png)]

Prompt Description:

(1) The expression should not be too complex

(2) Use of first count ()

2.4.8 operator operand type description

1. Arithmetic operator

Arithmetic operators can be used for numbers and single characters.

Where +, when used for string, indicates splicing.

2. Assignment operator

The type of constant value, expression value and variable value on the right must be consistent or compatible with the variable on the left (automatic type conversion can be realized) or forced type conversion can be successful.

3. Comparison operator

Other comparison operators can only be used for 8 basic data types.

Where = = and= It can be used for the comparison of reference data types and the address of comparison objects. (later)

int i = 10;
int j = 10;
System.out.println(i==j);//true

char c1 = 'Handsome';
char c2 = 'Handsome';
System.out.println(c1 == c2);//true

4. Logical operator

The operand of a logical operator must be a boolean value

5. Conditional operator

? The preceding must be a condition and a boolean value

Result expression 1 and result expression 2 should be of the same type or compatible

6. Bitwise operator

Generally used for integer series

The above operators are designed for basic data types.

Only the basic assignment operator =, and the comparison operator = = and! =, can be used to reference data types. No other operators can be used to reference data types.

The string type also has a +, indicating splicing.

Chapter III structure of flow control statement

The structure of process control statement is divided into:

1. Sequential structure: execute from top to bottom

2. Branch structure: select one of multiple branches to execute

3. Loop structure: execute some code repeatedly

3.1 sequence structure

Execution process: from top to bottom

3.1.1 output statement

1. System.out.print (output content)# Do not wrap after output

2. System.out.println (output content)# Wrap after output

#Output constant
System.out.print(1);
System.out.print('still');
System.out.print(44.4);
System.out.print(true);
System.out.print("Shang Silicon Valley");

#Output variable
int a = 1;
char c = 'still';
double d = 44.4;
boolean b = true;
String school = "Shang Silicon Valley";
System.out.print(a);
System.out.print(c);
System.out.print(d);
System.out.print(b);
System.out.print(school);

#Output splicing results
System.out.print("a = " + a);
System.out.print("c = " + c);
System.out.print("d = " + d);
System.out.print("b = " + b);
System.out.print("school = " + school);

3.1.2 input statement

There are three steps for entering codes on the keyboard:

1. Prepare variables of Scanner type

2. Prompt for xx

3. Receive input

Example code:

//1. Prepare variables of Scanner type
java.util.Scanner input = new java.util.Scanner(System.in);//System.in represents keyboard input by default

//2. Prompt for xx
System.out.print("Please enter an integer:");

//3. Receive input
int num = input.nextInt();

//Lists inputs for various data types
int num = input.nextInt();
long bigNum = input.nextLong();
double d = input.nextDouble();
boolean b = input.nextBoolean();
String s = input.next();
char c = input.next().charAt(0);//First receive according to the string, and then take the first character of the string (subscript 0)

3.2 branch structure

Branch structure: selectively execute some code according to conditions

Divided into:

1. Conditional judgment: if... else series

2. Select structure: switch... case series

3.2.1 condition judgment

1. Single branch structure

Syntax format:

if(Conditional expression){
    When the conditional expression holds(true)Block of statements to execute when;
}

Execution process:

If the condition is true, execute {} the statement block. If not, do not execute.

be careful:

(1) The result of a conditional expression in if (conditional expression) must be of type boolean

(2) When the statement in {} has only one statement (a simple statement or a compound statement), you can omit {}, but we do not recommend omitting it

		//Omitting {}
		if(score<0 || score>100)
			System.out.println("Wrong input!");//Simple statement
		else
			//Compound statement
			if(score==100){
				System.out.println("Full mark");
			}else if(score>=80){
				System.out.println("excellent");
			}else if(score>=60){
				System.out.println("pass");
			}else{
				System.out.println("fail,");
			}

Example code:

int year = 2019;
int days = 28;
if(year%4==0 && year%100!=0 || year%400==0){
    days= 29;
}

2. Double branch structure

Syntax format:

if(Conditional expression){
    When the conditional expression holds(true)Statement block 1 to be executed at;
}else{
    When the conditional expression does not hold(false)Statement block 2 to be executed when;
}

Execution process:

Execute statement block 1 when the conditional expression is true, otherwise execute statement block 2

be careful:

(1) The result of a conditional expression in if (conditional expression) must be of type boolean

(2) When the statement in {} has only one statement (a simple statement or a compound statement), you can omit {}, but we don't recommend it

Example code:

int num = 10;
if(num%2==0){
    System.out.println(num + "It's an even number");
}else{
     System.out.println(num + "It's an odd number");
}

3. Multi branch structure

Syntax format:

if(Conditional expression 1){
    When the conditional expression 1 is true, the executed statement block 1;
}else if(Conditional expression 2){
    When conditional expression 1 does not hold,
      When conditional expression 2 is true, execute statement block 2;
}else if(Conditional expression 3){
    When conditional expression 1 does not hold,
       Conditional expression 2 does not hold,
      When conditional expression 3 is true, execute statement block 3;
}
. . . 
[else{
	When all the above conditional expressions are not true, the statement block to be executed n+1;
}]

Execution process:

(1) Multiple conditions are judged in sequence. If one of the above conditions is true, the following conditions will not be viewed

(2) Multiple branches will execute only one of them

be careful:

(1) Every conditional expression must be a boolean value

(2) When there is only one statement in {}, {} can also be omitted, but it is not recommended to omit

(3) When multiple conditions are mutually exclusive (no overlap), the order can be arbitrary;

When multiple conditions are "inclusive" (with overlapping parts), the order cannot be arbitrary. The small one is above and the large one is below

Example code:

			int score = 78;
			if(score==100){
				System.out.println("Full mark");
			}else if(score>=80){
				System.out.println("excellent");
			}else if(score>=60){
				System.out.println("pass");
			}else{
				System.out.println("fail,");
			}

4. Nesting

Execution process:

When it is nested in an if, it is only when the outer if is true that the inner conditional judgment can be seen;

When nested in else, only when the external else is satisfied will the inner condition be judged;

3.2.2 structure selection

Syntax format:

switch(expression){
    case Constant value 1:
        Statement block 1;
        [break;]
    case Constant value 2:
        Statement block 2;
        [break;]   
    . . . 
   [default:
        Statement block n+1;
        [break;]
     ]
}

Execution process:

(1) Entrance

① When the value of switch (expression) matches a constant value after case, it enters from this case;

② When the value of switch (expression) does not match all constant values after case, look for the default branch to enter;

(2) Once you enter the switch from the "entrance", it will be executed in sequence until you encounter the "exit"

(3) Export

① Natural exit: encountered the end of switch}

② Interrupt exit: encountered break, etc

be careful:

(1) The value types of switch (expression) can only be: four basic data types (byte,short,int,char) and two reference data types (enumeration, String)

(2) case must be followed by a constant value and cannot be repeated

Example code:

int month = 4;
switch(month){
    case 3:
    case 4:
    case 5:
        System.out.println("spring");
        break;
    case 6:
    case 7:
    case 8:
        System.out.println("summer");
        break;
    case 9:
    case 10:
    case 11:
        System.out.println("autumn");
        break;
    case 12:
    case 1:
    case 2:
        System.out.println("winter");
        break;
    default:
        System.out.println("Wrong input!");
}

3.3 circulation structure

Cycle structure:

"Repeat" execute some code

Classification of cyclic structures:

1. for loop

2. while loop

3. do... while loop

3.3.1 for loop

Syntax format:

for(;;){
    Circular aspect sentence block;
    if(Conditional expression){
    	break;
    }
}
for(Initialization expression; Cycle condition; Iterative expression){
    Circular aspect sentence block; (code that needs to be executed repeatedly)
}

Execution process:

(1) Initialization expression;

(2) Judge cycle conditions;

(3) If the loop condition holds, execute the loop body sentence block first; Then execute the iterated expression and return to (2)

(4) If the loop condition does not hold, it will end for;

Or if a break statement is encountered in the current loop, the current for loop will also be ended;

be careful:

(1) Two in for(;); It can't be more or less

(2) Loop condition must be of type boolean

Example code:

//Traverse even numbers between 1-100
for(int i=1; i<=100; i++){//The stride of each cycle is 1
    if(i%2==0){
        System.out.println(i);
    }
}

//Traverse even numbers between 1-100
for(int i=2; i<=100; i+=2){//The stride of each cycle is 2
    System.out.println(i);
}

3.3.2 while loop

Syntax format:

while(Cycle condition){
    Circular body chunks;
}

Classic form:
while(true){
	Circular body chunks;
    if(Conditional expression){
    	break;
    }
}

Execution process:

(1) Judge the cycle condition first

(2) If the loop condition is true, execute the loop body sentence block; Then go back to (1)

(3) If the loop condition is not true, end the while loop;

If a break is encountered in the loop style sentence block, the while loop will also be ended;

be careful:

(1) The loop condition in while must be of type boolean

Example code:

//Traverse even numbers between 1-100
int num = 2;
while(num<=100){
    System.out.println(num);
    num+=2;
}

3.3.3 do... while loop

Syntax format:

do{
    Circular body chunks;
}while(Cycle condition);

Execution process:

(1) First execute a circular body sentence block;

(2) Judge cycle conditions

(3) If the loop condition holds, execute the loop body sentence block again; Then go back to (2)

(4) If the loop condition does not hold, end the do... while loop;

If you encounter a break in the loop style sentence block, you will also end the do... while loop;

be careful:

(1) The loop condition in while must be of type boolean

(2)do{}while(); There is a semicolon at the end

(3) The loop body sentence of do... While structure will be executed at least once, which is different from for and while

Example code:

//Enter an integer from the keyboard, count the number of positive and negative numbers, and enter 0 to end
java.util.Scanner input = new java.util.Scanner(System.in);

int num;
int positive = 0;
int negative = 0;
do{
    System.out.print("Please enter an integer (ending with 0):");
    num = input.nextInt();
    
    if(num > 0){
        positive++;
    }else if(num < 0){
        negatvie++;
    }
}while(num!=0);

System.out.println("Number of positive numbers:" + positive);
System.out.println("Number of negative numbers:" + negatvie);

3.3.4 selection of three cycles

Principle: the three cycles can be converted to each other, and all of them can realize the function of cycle

Suggestion (habitually): when the number of times is obvious, or from several cycles to several, we generally consider for first;

When a circular body sentence block needs to be executed at least once, it is generally considered to do... while first;

When the loop condition is obvious, but the number of times is not obvious, and the loop body sentence block is not executed at least once, the while structure can be considered;

The three cycle structures have four elements:

(1) Initialization expression of loop variable

(2) Cycle condition

(3) Modified iterative expression for loop variables

(4) Circular body chunks

3.3.5 jump statement

1,break

be used for:

(1) switch structure

Function: end switch structure

(2) Cyclic structure

Function: end the current cycle

2,continue

be used for:

Can only be used for circular structures

Function: end this cycle in advance and continue the next cycle

3. return (later)

Chapter 4 array

4.1 array related concepts and nouns (understand)

1. Array:

A set of data with the same data type arranged in a certain order.

Use a name for a limited number of variables of the same type for unified management.

2. Array name:

(1) this array name represents a group of numbers

(2) the "first address" of the entire array stored in the array name

3. Index:

We use number, index and subscript to distinguish one of a group of numbers.

Range: [0, array length - 1]

For example: for (int i = 0; I < arr.length; I + +) {}

4. Element:

Every data in this group is an element.

How to represent array elements? Array name [subscript]

5. Length of array

The total number of elements in the array.

How to get the array length? Array name.length

Note: the name is for the convenience of communication, and the concept does not need to be memorized

4.2 array syntax

4.2.1 array declaration

Syntax format:

 //recommend
 The data type of the element[] Array name;

 //Yes, but not recommended
 The data type array name of the element[];

Example:

//To store a set of integers
int[] array;

//To store a set of single characters
char[] array;

//To store a set of strings
String[] array;

4.2.2 initialization of array

The purpose of initialization: (1) determine the length of the array (2) assign a value to the element

There are two initialization methods:

1. Dynamic initialization

Syntax format:

//Specify array length
 Array name = new The data type of the element[length];

//Assign values to elements
 Array name[subscript] = value; //This value can be a constant value, the calculation result of an expression, or keyboard input

//If the assignment of each element is regular, the for loop assignment is usually used
for(int i=0; i<length; i++){
    Array name[subscript] = value;
}

Q: if only the array length is specified and no manual assignment is made to the element, does the element have a value?

There are default values

(1) Basic data type

​ byte,short,int,long: 0

​ float,double: 0.0

​ char: \u0000

​ boolean: false

(2) Reference data type

It's all null

2. Static initialization

Syntax format:

Array name = new The data type of the element[]{Value list};

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

//More concise
//When the declaration is completed with static initialization, it can be simplified
 The data type of the element[] Array name = {Value list};

Applicable occasions:

Static initialization can be used when the elements of an array are known to be finite.

Example code:

String[] weeks = {"monday","tuesday","wednesday","thursday","friday","saturday","sunday"};

int[] daysOfMonths = {31,28,31,30,31,30,31,31,30,31,30,31};

char[] letters = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};

4.2.3 traversal of array

for loop traversal array:

for(int i=0; i<Array name.lenght; i++){
    //Or assignment
    Array name[i] = value;
    //Or display
    System.out.println(Array name[i]);
    //Or other operations
    //For example: judge whether it is an even number
    if(Array name[i]%2==0){
          //...
    }
}

4.2.4 memory analysis of array

Element is a one-dimensional array memory analysis of basic data type:

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

[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-pOa9fbQB-1631456883947)(imgs/1558400311779.png)]

int[] arr = new int[5];
for(int i=0; i<arr.length; i++){
    arr[i] = i+1;
}

[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-7nQm9H4f-1631456883955)(imgs/1558400323314.png)]

4.3 array related algorithms

4.3.1 array find the most value

1. Find the latest value in the array

Idea:

(1) First assume that the first element is Max / min

(2) Then compare max/min with the following elements one by one

Example code:

int[] arr = {4,5,6,1,9};
//Find maximum value
int max = arr[0];
for(int i=1; i<arr.length; i++){
    if(arr[i] > max){
        max = arr[i];
    }
}

2. Find the most value and its subscript in the array

Case 1: find the maximum value and its subscript for the first time

Idea:

(1) First assume that the first element is Max / min

(2) Then compare max/min with the following elements one by one

Example code:

int[] arr = {4,5,6,1,9};
//Find maximum value
int max = arr[0];
int index = 0;
for(int i=1; i<arr.length; i++){
    if(arr[i] > max){
        max = arr[i];
        index = i;
    }
}

or

int[] arr = {4,5,6,1,9};
//Find maximum value
int maxIndex = 0;
for(int i=1; i<arr.length; i++){
    if(arr[i] > arr[maxIndex]){
        maxIndex = i;
    }
}
System.out.println("Maximum:" + arr[maxIndex]);

Case 2: find the subscript of the maximum value and all its maximum values (i.e. the possible maximum value is repeated)

Idea:

(1) Find the maximum value first

① Assume that the first element is the largest

② Compare max with the following elements one by one

(2) Traverse the array to see which elements are the same as the maximum value

Example code:

int[] arr = {4,5,6,1,9};
//Find maximum value
int max = arr[0];
for(int i=1; i<arr.length; i++){
    if(arr[i] > max){
        max = arr[i];
    }
}

//Traverse the array to see which elements are the same as the maximum value
for(int i=0; i<arr.length; i++){
    if(max == arr[i]){
        System.out.print(i+"\t");
    }
}

4.3.2 array statistics: sum, mean, even number, etc

Idea: traverse the array, accumulate one by one, and judge each element

Example code:

int[] arr = {4,5,6,1,9};
//Sum and mean
int sum = 0;//Because 0 plus any number does not affect the result
for(int i=0; i<arr.length; i++){
    sum += arr[i];
}
double avg = (double)sum/arr.length;

Example code 2:

int[] arr = {4,5,6,1,9};

//Total product
long result = 1;//Because multiplying 1 by any number does not affect the result
for(int i=0; i<arr.length; i++){
    result *= arr[i];
}

Example code 3:

int[] arr = {4,5,6,1,9};
//Count even numbers
int even = 0;
for(int i=0; i<arr.length; i++){
    if(arr[i]%2==0){
        even++;
    }
}

4.3.3 reverse rotation

There are two methods:

1. With a new array

2. Head and tail corresponding position exchange

Example code of the first method:

int[] arr = {1,2,3,4,5,6,7,8,9};

//(1) Create a new array first
int[] newArr = new int[arr.length];

//(2) Copy element
int len = arr.length;
for(int i=0; i<newArr.length; i++){
    newArr[i] = arr[len -1 - i];
}

//(3) Discard the old and let arr point to the new array
arr = newArr;//Here, the first address of the new array is assigned to arr

//(4) Traversal display
for(int i=0; i<arr.length; i++){
    System.out.println(arr[i]);
}

Example code of the second method:

int[] arr = {1,2,3,4,5,6,7,8,9};

//(1) Calculate the number of times to exchange: number = arr.length/2
//(2) Head and tail exchange
for(int i=0; i<arr.length/2; i++){//The number of cycles is the number of exchanges
    //Head and tail exchange
    int temp = arr[i];
    arr[i] = arr[arr.length-1-i];
	arr[arr.length-1-i] = temp;
}

//(3) Traversal display
for(int i=0; i<arr.length; i++){
    System.out.println(arr[i]);
}

4.3.4 copying

Application scenario:

1. Capacity expansion

2. Backup

3. Intercept

Example code: capacity expansion

int[] arr = {1,2,3,4,5,6,7,8,9};

//If you want to expand the arr array, add 1 position
//(1) First create a new array, its length = the length of the old array + 1
int[] newArr = new int[arr.length + 1];

//(2) Copy element
//Note: I < arr.length because bit arr is shorter than newArr, avoid subscript out of bounds
for(int i=0; i<arr.length; i++){
    newArr[i] = arr[i];
}

//(3) Add the new element to the end of newArr
newArr[newArr.length-1] = New value;

//(4) If you continue to use arr below, you can make arr point to the new array
arr = newArr;

//(4) Traversal display
for(int i=0; i<arr.length; i++){
    System.out.println(arr[i]);
}

Example code: Backup

int[] arr = {1,2,3,4,5,6,7,8,9};

//1. Create a new array with the same length as the original array
int[] newArr = new int[arr.length];

//2. Copy element
for(int i=0; i<arr.length; i++){
    newArr[i] = arr[i];
}

//3. Traversal display
for(int i=0; i<arr.length; i++){
    System.out.println(arr[i]);
}

Example code: interception

int[] arr = {1,2,3,4,5,6,7,8,9};

int start = 2;
int end = 5;

//1. Create a new array. The length of the new array = end start + 1;
int[] newArr = new int[end-start+1];

//2. Assignment element
for(int i=0; i<newArr.length; i++){
    newArr[i] = arr[start + i];
}

//3. Traversal display
for(int i=0; i<newArr.length; i++){
    System.out.println(newArr[i]);
}

4.3.5 search

There are two types of lookups:

1. Sequential search: look one by one

No requirements for arrays

2. Binary search: half fold, half fold, and then half fold

There are requirements for arrays, and the elements must be in size order

Sequential lookup example code:

int[] arr = {4,5,6,1,9};
int value = 1;
int index = -1;

for(int i=0; i<arr.length; i++){
    if(arr[i] == value){
        index = i;
        break;
    }
}

if(index==-1){
    System.out.println(value + "non-existent");
}else{
    System.out.println(value + "The subscript is" + index);
}

Binary search example code:

/*
2,Write code and use the binary search method to find int value = 2 in the array; Whether it exists. If it exists, the display subscript does not exist. If it does not exist, the display does not exist.
Known array: int[] arr = {1,2,3,4,5,6,7,8,9,10};
*/
class Exam2{
	public static void main(String[] args){
		int[] arr = {1,2,3,4,5,6,7,8,9};//Arrays are ordered
		int value = 2;
		
        int index = -1;
		int left = 0;
        int right = arr.length - 1;
        int mid = (left + right)/2;
        while(left<=right){
            //Find end
            if(value == arr[mid]){
                index = mid;
                break;
            }//Can't find
            else if(value > arr[mid]){//Continue to find to the right
                //Move the left boundary so that the mid moves to the right
                left = mid + 1;
            }else if(value < arr[mid]){//Continue to the left
                right = mid - 1;
            }
            
            mid = (left + right)/2;
        }
        
        if(index==-1){
    		System.out.println(value + "non-existent");
		}else{
    		System.out.println(value + "The subscript is" + index);
		}
        
	}
}

Use for

class Exam2{
	public static void main(String[] args){
		int[] arr = {1,2,3,4,5,6,7,8,9};//Arrays are ordered
		int value = 2;
		
        int index = -1;
        
        for(int left=0,right=arr.length-1,mid = (left+right)/2; left<=right; mid = (left + right)/2){
             //Find end
            if(value == arr[mid]){
                index = mid;
                break;
            }//Can't find
            else if(value > arr[mid]){//Continue to find to the right
                //Move the left boundary so that the mid moves to the right
                left = mid + 1;
            }else if(value < arr[mid]){//Continue to the left
                right = mid - 1;
            }
        }
        
		
        
        if(index==-1){
    		System.out.println(value + "non-existent");
		}else{
    		System.out.println(value + "The subscript is" + index);
		}
        
	}
}

4.3.6 sorting

There are thousands of sorting algorithms for arrays. We only talk about two:

1. Bubble sorting

2. Simple direct sort

Example code: Bubble: compare from small to large, left to right

int[] arr = {5,4,6,3,1};
for(int i=1; i<arr.length; i++){//Number of outer loops = number of rounds = length of array - 1
    /*
    In the first round, i=1, compare two from left to right, arr[0] and arr[1]..... arr[3] and arr[4]
    In the second round, i=2, compare two from left to right, arr[0] and arr[1]..... arr[2] and arr[3]
    ...
    				arr[j]Comparison with arr[j+1]
    Find two key points: (1) the starting value of j: 0 (2) find the ending value of j, which is 3,2,1,0, and get j < arr.length-i
    */
    for(int j=0; j<arr.length-i; j++){
        //Pairwise comparison
        //From small to large, it means that the front one is larger than the back one, so exchange it
        if(arr[j] > arr[j+1]){
            int temp = arr[j];
            arr[j] = arr[j+1];
            arr[j+1] = temp;
        }
    }
}

Example code: from large to small, from right to left

char[] arr = {'h','e','l','l','o','j','a','v','a'};
for(int i=1; i<arr.length; i++){//Number of outer loops = number of rounds = length of array - 1
    /*
    Round 1, i=1, compare from right to left, arr[8] and arr[7], arr[7] and arr[6]....arr[1] and arr[0]
    Round 2, i=2, compare from right to left, arr[8] and arr[7], arr[7] and arr[6]....arr[2] and arr[1]
    ...
    Round 8, i=8, compare from right to left, arr[8] and arr[7]
    		   arr[j]And arr[j-1]
    Find two key points: (1) the starting value of j: 8 (2) find the ending value of j, which is 1, 2, 3,... 8, j > = I
    */
    for(int j=8; j>=i; j--){
        //From large to small, the following elements > the previous elements are exchanged
        if(arr[j]>arr[j-1]){
            int temp = arr[j];
            arr[j] = arr[j-1];
            arr[j-1] = temp;
        }
    }
}	
		

Example code: simple direct selection sorting

int[] arr = {3,2,6,1,8};

for(int i=1; i<arr.length; i++){//Number of outer loops = number of rounds = length of array - 1
    //(1) Find the latest value in the unordered elements in this round
    /*
    Unsorted elements:
    Round 1: i=1, unsorted, [0,4]
    Round 2: i=2, unsorted, [1,4]
    ...
    
    The starting subscript of each round of unordered elements: 0,1,2,3, which is exactly the starting subscript of i-1
    The following elements that are not sorted are:
    Round 1: [1,4] J = 1,2,3,4
    Round 2: [2,4] J = 2,3,4
    Round 3: [3,4] J = 3,4
    Round 4: [4,4] J = 4
    j The starting point is i and the ending point is 4
    */
    int max = arr[i-1];
    int index = i-1;
    for(int j=i; j<arr.length; j++){
        if(arr[j] > max){
            max = arr[j];
            index = j;
        }
    }
    
    //(2) If the maximum value is not in the position it should be, it is exchanged with the element in this position
    /*
    Round 1, the maximum value should be [0]
    In the second round, the maximum value should be [1]
    In the third round, the maximum value should be [2]
    Round 4, the maximum value should be [3]
    Exactly the value of i-1
    */
    if(index != i-1){
        //Exchange arr[i-1] and arr[index]
        int temp = arr[i-1];
        arr[i-1] = arr[index];
        arr[index] = temp;
    }
}



//Display results
for(int i=0; i<arr.length; i++){
	System.out.print(arr[i]);
}

4.4 two dimensional array

Tag for 2D array: [] []

4.4.1 relevant representations

(1) Length / rows of 2D array:

2D array name.length

(2) One row of 2D array:

2D array name [row subscript]

Range of row subscript: [0, 2D array name. length-1]

(3) Number of columns per row:

Two dimensional array name [row subscript]. length

Because each row of a two-dimensional array is a one-dimensional array

(4) Every element

Two dimensional array name [row subscript] [column subscript]

4.4.2 declaration and initialization of two-dimensional array

1. Declaration of two-dimensional array

  //recommend
  The data type of the element[][] The name of the 2D array;

 //Not recommended
 The data type of the element is a two-dimensional array name[][];
 //Not recommended
  The data type of the element[]  2D array name[];

interview:

int[] x, y[];
//x is a one-dimensional array and y is a two-dimensional array

2. Initialization of two-dimensional array

(1) Static initialization

2D array name = new The data type of the element[][]{
			{List of values in the first row}, 
			{List of values in the second row},
			...
			{The first n List of values for row}
		};
		
//If the declaration is completed with static initialization
 The data type of the element[][] The name of the 2D array = {
			{List of values in the first row}, 
			{List of values in the second row},
			...
			{The first n List of values for row}
		};

(2) Dynamic initialization (irregular: the number of columns in each row may be different)

//(1) Determine the total number of rows first
 2D array name = new The data type of the element[Total number of rows][];

//(2) Then determine the number of columns in each row
 2D array name[Row subscript] = new The data type of the element[Total number of columns in this row];

//(3) Then assign a value to the element
 2D array name[Row subscript][Column subscript] = value;

(3) Dynamic initialization (rule: the number of columns in each row is the same)

//(1) Determine the number of rows and columns
 2D array name = new The data type of the element[Total number of rows][Number of columns per row];

//(2) Then assign a value to the element
 2D array name[Row subscript][Column subscript] = value;

4.4.3 traversal of two-dimensional array

for(int i=0; i<2D array name.length; i++){
    for(int j=0; j<2D array name[i].length; j++){
        System.out.print(2D array name[i][j]);
    }
    System.out.println();
}

Chapter V object oriented Foundation

5.1 class and object

1. Class: an abstract description of a class of things with the same characteristics.

Object: an individual, instance, and concrete existence of a class.

Class is the design template of an object.

2. How to declare a class?

[Modifier] class Class name{
    Member list: attribute, method, constructor, code block, internal class
}

3. How do I create objects?

new Class name();  //Anonymous object

Class name object name = new Class name(); //Named object

5.2 one of the members of class: attribute

1. How to declare properties?

[Modifier] class Class name{
    [Modifier] data type attribute name;    //Property has a default value
    [Modifier] data type attribute name = value; //Property has an initial value
}

Note: the type of attribute can be any type in Java, including basic data type and reference data type (class, interface, array, etc.)

Summary: Java data types

(1) Basic data type

byte,short,int,long,float,double,char,boolean

(2) Reference data type

① Class:

For example: String, Student, Circle, System, Scanner, Math

② Interface: later

③ Array:

For example: int [], String [], char [], int [] []

int[] arr = new int[5];
Here put int[]As an array type, it is a reference data type. The object assigned on the right is an array object

Data type of element: int
 Data type of array: int[]

2. How to assign values to attributes?

(1) Explicit assignment when declaring attributes

[Modifier] class Class name{
    [Modifier] data type attribute name = value; //Property has an initial value
}

Code example:

class Student{
    String name;
    char gender = 'male';//Explicit assignment
}

class TestStudent{
    public static void main(String[] args){
        Student s1 = new Student();
        System.out.println("full name:" + s1.name);//null
        System.out.println("Gender:" + s1.gender);//male
        
        s1.name = "Wei";//Modify the default value of the attribute
        s1.gender = 'female';//Modify the initial value of the attribute
        System.out.println("full name:" + s1.name);//Wei
        System.out.println("Gender:" + s1.gender);//female
        
        Student s2 = new Student();
        System.out.println("full name:" + s2.name);//null
        System.out.println("Gender:" + s2.gender);//male
    }
}

(2) Assignment after object creation

[Modifier] class Class name{
    [Modifier] data type attribute name; //Property has a default value
}

//create object
 Class name object name = new  Class name();

//Assign values to the properties of the object
 Object name.Attribute name = value;

3. How do I access the value of a property?

(1) Access in methods of this class

Example code:

class Circle{
    double radius;
    
    double getArea(){
        return 3.14 * radius * radius;//Direct access
    }
}

(2) Access in methods of other classes

class Circle{
    double radius;
}

class TestCircle{
    public static void main(String[] args){
        Circle c1 = new Circle();
        double area = 3.14 * c1.radius * c1.radius;//Object name. Property name
    }
}

4. Characteristics of attributes

(1) Property has a default value

Basic data type:

​ byte,short,int,long: 0

​ float,double: 0.0

​ char: \u0000

​ boolean: false

Reference data type:

​ null

(2) The attributes of each object are independent and do not interfere with each other

5. Memory map of object properties

class Student{
    String name;
    char gender = 'male';//Explicit assignment
}

class TestStudent{
    public static void main(String[] args){
        Student s1 = new Student();
        System.out.println("full name:" + s1.name);//null
        System.out.println("Gender:" + s1.gender);//male
        
        s1.name = "Wei";
        s1.gender = 'female';
        System.out.println("full name:" + s1.name);//Wei
        System.out.println("Gender:" + s1.gender);//female
        
        Student s2 = new Student();
        System.out.println("full name:" + s2.name);//null
        System.out.println("Gender:" + s2.gender);//male
    }
}

[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-SbtiIF2W-1631456883966)(imgs/1558659534754.png)]

5.4 category 2: Methods

5.4.1 concept of method

method: represents an independent reusable function

Purpose / benefit:

(1) Reuse

(2) Simplified code

5.4.2 syntax of method

1. Method declaration format:

[Modifier] class Class name{
    [Modifier] return value type method name([Formal parameter list]){
        Method body: the code that implements the function
    }
}

explain:

(1) [modifier]: to be discussed

(2) Return value type:

① void: indicates no return value

② Non void: all Java data types are OK

(3) Method name: it can well reflect the function of the method

Naming standard: ① see the meaning of the name ② capitalize the first letter from the second word

(4) [formal parameter list]:

When completing the function of this method, we need some data, which should be determined by the "caller", so we can design formal parameters.

Syntax format:

(): no parameter, empty parameter

(data type parameter name): a parameter

(data type 1, parameter name 1,..., data type N, parameter name n): n parameters

(5) Method body: to realize the function of a method, the best method is to complete an independent function.

2. Method call format:

//Method call of the same level in this class: direct call
[variable = ] Method name([Argument list]);
//Call in other class methods
[variable = ] Object name.Method name([Argument list]);

(1) Pass arguments

See if the called method has formal parameters

(2) Receive return value

Check whether the called method is void. If it is void, it is unnecessary and cannot be received. If it is not void, it can be received.

3. Code example of declaration and call of method

(1) Parameterless return value method

//This category
class Circle{
    double radius;
    void printInfo(){
        System.out.println("Radius:" + radius);
    }
    
    void test(){
        printInfo();//In this class, we call no parameter no return value method.
    }
}
//Other classes
class Circle{
    double radius;
    void printInfo(){
        System.out.println("Radius:" + radius);
    }

}
class TestCircle{
    public static void main(String[] args){
        Circle c1 = new Circle();
        c1.printInfo(); //In other classes, no parameter can be returned.
    }
}

(2) Nonparametric return value method

//This category
class Circle{
    double radius;
    
    double getArea(){
        return 3.14 * radius * radius();
    }
    
    void printInfo(){
      //  System.out.println("radius:" + radius + ", area:" + getArea())// In this class, no parameter is returned and there is a return value.
       	double area = getArea();//In this class, no parameter is returned and there is a return value.
        System.out.println("Radius:" + radius + ",the measure of area:" + area);
    }
}
//Other classes
class Circle{
    double radius;
    
    double getArea(){
        return 3.14 * radius * radius();
    }
}
class TestCircle{
    public static void main(String[] args){
        Circle c1 = new Circle();
        double area = c1.getArea();
        System.out.println("the measure of area:" + area);
        //or
        System.out.println("the measure of area:" + c1.getArea());
    }
}

(3) Method with parameter and no return value

//This category
class GraphicTools{
    void printRectange(int line, int column, char sign){
        for(int i=1; i<=line; i++){
            for(int j=1; j<=column; j++){
                Sytem.out.print(sign);
            }
            System.out.println();
        }
    }
    
    void test(){
        printRectange(5,10,'%');//There is no return value method in this class.
    }
}
//Other classes
class GraphicTools{
    void printRectange(int line, int column, char sign){
        for(int i=1; i<=line; i++){
            for(int j=1; j<=column; j++){
                Sytem.out.print(sign);
            }
            System.out.println();
        }
    }
}
class Test{
    public static void main(String[] args){
        GraphicTools tools = new GraphicTools();
        tools.printRectange(5,10,'%');
    }
}

(4) Method with parameter and return value

//This category
class MyMath{
    int sum(int a,int b){
        return a+b;
    }
    
    void print(){
        int x = 4;
        int y = 7;
        System.out.println(x + "+" + y + "=" + sum(x,y);//In this class, there is a way to return values.
    }
}
//Other classes
class MyMath{
    int sum(int a,int b){
        return a+b;
    }
}
class Test{
    public static void main(String[] args){
        MyMath my = new MyMath();
        int x = 4;
        int y = 7;
        
        System.out.println(x + "+" + y + "=" + my.sum(x,y));
    }
}

4. Principles of method declaration and invocation

(1) the method must be declared before calling.

If you call a method, if the method name is written incorrectly or call a method that does not exist, the compilation will report an error

(2) The location of the method declaration must be outside the method in the class

Correct example:

class{
    Method 1(){
        
    }
    Method 2(){
        
    }
}

Examples of errors:

class{
    Method 1(){
        Method 2(){  //error
        
   		}
    }
}

(3) The calling location of the method is required

Correct example:

class{
    Method 1(){
        Call method
    }
}

Examples of errors:

class{
    Method 1(){
        
    }
    
    Call method  //error location
}

(4) The calling format of the method should correspond to the declaration format of the method

① Whether to add "object.": see whether it is in this class or in other classes

② Whether to receive the return value: check whether the called method is void

③ Whether to pass arguments: see if the called method has a formal parameter list

5.4.3 Overload of method

Concept: in the same class, there are two or more methods with the same method name and different formal parameter list. This form is called method overloading. It has nothing to do with the return value type.

Example code:

	//Find the maximum of two integers
public int max(int a,int b){
    return a>b?a:b;
}
	
	//Find the maximum of three integers
public int max(int a, int b, int c){
    return max(max(a,b),c);
}
	
	//Find the maximum of two decimals
public double max(double a, double b){
    return a>b?a:b;
}

5.4.4 parameter transfer mechanism of method

Parameter passing mechanism of method in Java: Value Passing

(1) When a formal parameter is a basic data type, the argument passes the data value to the formal parameter in the form of copy. The modification of the value by the formal parameter does not affect the argument.
(2) When a formal parameter refers to a data type, the argument passes the address value to the formal parameter. The modification of the object's attribute by the formal parameter will affect the attribute value of the actual parameter object, because at this time, the formal parameter and the actual parameter point to the same object.
Example code:

class Test{
    public static void swap(int a, int b){
        int temp = a;
        a = b;
        b = temp;
	}

	public static void main(String[] args){
        int x = 1;
        int y = 2;
        swap(x,y);//After the call, the values of x and y remain unchanged
    }
}

Example code:

class Test{
    public static void change(MyData my){
        my.num *= 2;
    }
    
    public static void main(String[] args){
        MyData m = new MyData();
        m.num = 1;
        
        change(m);//After the call, the num attribute value of the m object changes to 2
    }
}

class MyData{
    int num;
}

Trap 1:

/*
Trap 1: in the method, if the formal parameter = new object, it has nothing to do with the argument
*/
class Test{
    public static void change(MyData my){
        my = new MyData();//The parameter points to a new object
        my.num *= 2;
    }
    
    public static void main(String[] args){
        MyData m = new MyData();
        m.num = 1;
        
        change(m);//After the call, the num attribute value of the m object is still 1
    }
}

class MyData{
    int num;
}

Trap 2: see the string and wrapper classes section

5.3 object array

One dimensional array:

1. Element is a basic data type

2. Element is a reference data type, also known as an object array, that is, the element of the array is an object

Note: for an object array, first create the array object itself, that is, determine the length of the array, and then create each element object. If it is not created, the default value of the element of the array is null, so null pointer exception NullPointerException is easy to occur.

Example code:

class MyDate{
	int year;
	int month;
	int day;
}
class Test{
    public static void main(String[] args){
        MyDate[] arr = new MyDate[3];//Create the array object itself and specify the length of the array
        
        for(int i=0; i<arr.length; i++){
            arr[i] = new MyDate();//Each element creates an object
            arr[i].year = 1990 + i;
            arr[i].month = 1 + i;
            arr[i].day = 1 + i;
        }
    }
}

Memory map of object array:

[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-RnqLoY1w-1631456883975)(imgs/1558745138315.png)]

Chapter VI basic characteristics of object-oriented

Basic characteristics of object-oriented:

1. Encapsulation

2. Inherit

3. Polymorphism

6.1 packaging

1. Benefits:

(1) Hide implementation details for user convenience

(2) Safe, can control the visible range

2. How to implement encapsulation?

By permission modifier

Interview question: Please list the permission modifiers from small to large (from large to small) according to the visible range?

Modifier This categoryThis packageSubclasses of other packagesAny position
private×××
default××
protected×
public

What can permission modifiers modify?

Classes (classes, interfaces, etc.), properties, methods, constructors, internal classes

Class (external class): public and default

Attributes: 4

Methods: 4 kinds

Constructors: 4

Internal class: 4

3. What is the usual encapsulation of attributes?

Of course, the permission modifiers of attributes can be private, default, protected and public. But most of the time, what we see is private, and then we match them with get/set methods.

Example code: how to write standard Java beans

public class Student{
    //Property privatization
    private String name;
    private int age;
    private boolean marry;
    
    //Public get/set
    public void setName(String n){
        name = n;//Here, because you haven't learned this, it may be optimized
    }
    public String getName(){
        return name;
    }
    public void setAge(int a){
        age = a;
    }
    public int getAge(){
        return age;
    }
    public void setMarry(boolean m){
        marry = m;
    }
    public boolean isMarry(){//The get method of boolean type attribute is used to replacing get with is
        return marry;
    }
}

6.2 constructor

1. Function of constructor:
(1) Use with new to create objects

//Call parameterless construction to create an object
 Class name object name = new Class name();

//Call a parameterized construct to create an object
 Class name object name = new Class name(Argument list);

(2) You can assign values to attributes while creating objects

public class Circle{
    private double radius;
    
    public Circle(){
        
    }
    public Circle(double r){
        radius = r;//Assign a value to radius
    }
}

2. Syntax format of declaration constructor:

[Modifier] class Class name{
    [Modifier] class name(){//Nonparametric structure
        
    }
    [Modifier] class name(parameter list ){//Parametric structure
        
    }
}

3. Characteristics of constructor:

(1) All classes have constructors

(2) If a class does not explicitly / explicitly declare a constructor, the compiler will automatically add a default parameterless construct

(3) If a class explicitly / explicitly declares a constructor, the compiler will no longer automatically add the default parameterless constructor. If necessary, it needs to be added manually

(4) The constructor name must be the same as the class name

(5) Constructor has no return value type

(6) Constructors can be overloaded

Example code:

public class Circle{
    private double radius;
    
    public Circle(){
        
    }
    public Circle(double r){
        radius = r;//Assign a value to radius
    }
}

6.3 keyword this

1. this keyword:

Meaning: current object

(1) If it appears in the constructor: indicates the object being created

(2) If it appears in a member method: indicates the object that is calling this method

2. Usage of this:

(1) this. Attribute

When a local variable has the same name as a member variable, you can add "this." in front of the member variable to distinguish it

(2) this. Method

Call the member method of the current object, and you can omit "this."

(3) this() or this (argument list)

this() means to call the parameterless construction of this class

This (argument list) indicates that the parameterized construction of this class is called

this() or this (argument list) either does not exist or must appear in the first line of the constructor

Example code:

public class Student{
    private String name;
    private int score;
    
    public Student(){
        
    }
    public Student(String name){
        this.name = name;
    }
    public Student(String name, int score){
        this(name);
    }
    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
    public void setScore(int score){
        this.score = score;
    }
    public int getScore(){
        return score;
    }
}

3. What is the difference between member variables and local variables?

Only instance variables are discussed here (see the static section for class variables)

(1) The position of the declaration is different

Member variable: outside method in class

Local variables: in methods or code

① formal parameter list of method

② local variables in method body

③ local variables in code block

(2) The runtime is stored in different locations in memory

Member variables: heap

Local variables: stack

Variables of basic data type are on the stack, and variables of reference data type are on the heap: inaccurate

(3) Modifier

Member variable: there are many modifiers, such as permission modifier

Local variable: permission modifier cannot be added. The only one that can be added is final

(4) Initialization

Member variables: have default values

Local variable: it has no default value and must be initialized manually

(5) Life cycle

Member variable: it is created with the creation of the object and dies with the recycling of the object, that is, it lives and dies with the object. Each object is independent.

Local variable: it is allocated only when the method is called, and it is not available when the method runs. Each method call is independent

6.4 package

1. Function of package:

(1) You can avoid duplicate class names

With the package, the full name of the class becomes: package. Class name

(2) The classification organization manages a large number of classes

For example: java.lang package, java.util package, java.io package

(3) You can control the visibility of certain types or members

If the permission of a type or member is modified by default, it is only used in this package

2. Syntax format of declaration package:

package Package name;

be careful:

(1) Must be on the first line of code in the source file

(2) There can only be one source file

3. Naming conventions and habits of packages:
(1) All words are lowercase. Use. Segmentation between each word
(2) Used to invert the company's domain name

For example: com.atguigu.xxx;

It is recommended that you do not use the "java.xx" package when taking the package name

4. Classes using other packages:

Premise: the permission modifier of the used class or member is > default

(1) Use the full name of the type

For example: java.util.Scanner input = new java.util.Scanner(System.in);

(2) After using the import statement, the simple name is used in the code

5. import statement

import package.Class name;
import package.*;

Note: when using classes with the same name in two different packages, for example: java.util.Date and java.sql.Date.

One uses a full name and one uses a simple name

Example code:

package com.atguigu.test;

import java.util.Scanner;

public class Test{
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
    }
}

6.5 use of eclipse

1. eclipse manages the structure of projects and code

Workspace -- > Project -- > package – > class

A workspace can have multiple projects.

2. Shortcut key

General shortcut keys:

Ctrl + S: save

Ctrl + C: copy

Ctrl + V: paste

Ctrl + X: cut

Ctrl + Y: cancel undo

Ctrl + Z: undo

Ctrl + A: select all

Default shortcut keys in eclipse:

Ctrl + 1: quick fix

Alt + /: Code prompt

Alt +?: prompt for parameter list of Alt + Shift + / method

Ctrl + D: delete the selected row

Ctrl + Alt + ↓: copy rows down

Ctrl + Alt + ↑: copy rows up

Alt + ↓: swap position with the following line

Alt + ↑: swap position with the following line

Ctrl + Shift + F: quick format

Ctrl + /: single line comment, press again to cancel

Ctrl + Shift + /: multiline comment

Ctrl + Shift + \: uncomment multiline

Shift + Enter: insert SIA in the next line under the cursor to start editing

Ctrl + Shift + Enter: insert SIA on the cursor line to start editing

Alt + Shift + A: multiline editing press again to exit multiline editing mode

Alt + Shift + S: pop up the menu selection of automatic code generation, including automatic code generation constructor, get/set, equals

Ctrl + Shift + O: quick package Guide

Ctrl + Shift + T: open the source file of a class

Ctrl + O: open a summary outline of a certain type

3. Rapidly developed code templates

Code template + Alt +/

(1)main

public static void main(String[] args){

}

(2)sysout

System.out.println();

(3)for

For (int i = 0; I < array name. lenght; i + +){

}

For other details, see JavaSE Chai Linyan related tools. docx

6.6 the second basic feature of object-oriented: Inheritance

1. Why inherit? The benefits of inheritance? (understand)

(1) Code reuse

(2) Code extension

2. How to implement inheritance?

Syntax format:

[Modifier] class Subclass  extends Parent class{
    
}

3. Characteristics of inheritance

(1) The subclass inherits all the characteristics (properties, methods) of the parent class

However, private cannot be used directly in subclasses

(2) Subclasses do not inherit the constructor of the parent class

Because the constructor of the parent class is used to create the object of the parent class

(3) The constructor of the subclass must call the constructor of the parent class

When creating a subclass object, it initializes the attribute inherited from the parent class. You can assign a value to the attribute with the help of the code in the constructor of the parent class.

(4) Java only supports single inheritance: a subclass can have only one "direct" parent class

(5) Java also supports multi-layer inheritance: the parent class can also have a parent class, and the features will be passed on from generation to generation

(6) A parent class can have many subclasses at the same time

6.7 keyword super

super keyword: reference the parent class, find the xx of the parent class

Usage:

(1) super. Attribute

When a subclass declares a member variable with the same name as the parent class, if you want to indicate that a member variable is of the parent class, you can add "super."

(2) super. Method

When a child rewrites the parent class method, it calls for the method that the parent class is rewritten in the subclass, and the "super." can be used.

(3) super() or super (argument list)

super(): it means to call the parameterless construction of the parent class

Super (argument list): refers to the parameterized construction of the calling parent class

be careful:

(1) If you want to write super() or super (argument list), you must write it in the first line of the subclass constructor

(2) If: super() or super (argument list) is not written in the constructor of the subclass, there will be super() by default

(3) If the parent class does not have a parameterless construct, write Super (argument list) in the first line of the constructor of the child class

6.8 rewriting of methods

1. Method Override

When a subclass inherits the method of the parent class and feels that the implementation of the method body of the parent class is not suitable for the subclass, the subclass can choose to override it.

2. Method override requirements

(1) Method name: must be the same

(2) Formal parameter list: must be the same

(3) Modifier

Permission modifier: >=

(4) Return value type

In case of basic data type and void: must be the same

If it is a reference data type:<=

In Java, we believe that in the conceptual scope: subclass < parent class

3. The difference between Overload and Override

Overload: two or more methods in the same class with the same method name, different formal parameter lists, and independent of the return value type.

Override: between parent and child classes. The requirements for method signature are shown above.

Special overload:

public class TestOverload {
	public static void main(String[] args) {
		B b = new B();
		//b object can call several a methods
		b.a();
		b.a("");//From the point of view that the b object has two methods with the same name and different formal parameters at the same time, it is overloaded
	}
}
class A{
	public void a(){
		//...
	}
}
class B extends A{
	public void a(String str){
		
	}
}

6.9 non static code blocks

1. Syntax format

[Modifier] class Class name{
    {
        Non static code block
    }
}

2. Function

Purpose: in the process of creation, assign values to object attributes to assist in the process of instance initialization

3. When will it be implemented?

(1) Executes each time an object is created

(2) Takes precedence over constructor execution

6.10 instance initialization process

1. Concept description

  • Instance initialization process: the process of creating an instance object

  • Instance initialization method: the method to be executed when an instance object is created

  • The origin of the instance initialization method: it is compiled and generated by the compiler

  • Form of instance initialization method: () or (formal parameter list)

  • Composition of instance initialization method:

    ① Explicit assignment code for property

    ② Code for non static code blocks

    ③ Constructor code

    among

    ① And ② in order, from top to bottom

    ③ Behind ① and ②

Therefore, if a class has several constructors, there are several instance initialization methods.

2. Single class instance initialization method

Example code:

class Demo{
	{
		System.out.println("Non static code block 1");
	}
	
	private String str = assign();//Call the method to explicitly assign a value to str
	
	public Demo(){
		System.out.println("Nonparametric structure");
	}
	public Demo(String str){
		this.str = str;
		System.out.println("Parametric structure");
	}
	
	{
		System.out.println("Non static code block 2");
	}
	
	public String assign(){
		System.out.println("assign method");
		return "hello";
	}
}

Illustration:

[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-WnY5qU6n-1631456883983)(imgs/1558960549421.png)]

3. Instance initialization of parent and child classes

be careful:

(1) Originally, super() and super (argument list) were said to be constructors that call the parent class. Now it is necessary to correct it to call the instance initialization method of the parent class

(2) Originally, super() and super (argument list) said that they must be in the first line of the subclass constructor. Now they have to be corrected to the first line of the subclass instance initialization method

Conclusion:

(1) The execution order is to initialize the parent class instance first and then the child class instance

(2) If a subclass overrides a method and is called through a subclass object, the overridden method must be executed

Example code:

class Ba{
	private String str = assign();
	{
		System.out.println("(1)Non static code block of the parent class");
	}
	public Ba(){
		System.out.println("(2)Parameterless construction of parent class");
	}
	public String assign(){
		System.out.println("(3)Parent class assign()");
		return "ba";
	}
}
class Er extends Ba{
	private String str = assign();
	{
		System.out.println("(4)Non static code block of subclass");
	}
	public Er(){
		//Super () = = > calls the instance initialization method of the parent class, and it is in the first line of the instance initialization method of the child class
		System.out.println("(5)Nonparametric construction of subclasses");
	}
	
	public String assign(){
		System.out.println("(6)Subclass assign()");
		return "er";
	}
}
class Test{
    public static void main(String[] args){
        new Er();//612645
    }
}

Illustration:

[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-1kIqJASH-1631456883987)(imgs/1558961723911.png)]

6.11 the third basic feature of object-oriented: polymorphism

1. Polymorphism:

Syntax format:

Parent class reference/variable = Subclass object;

2. Premise:

(1) Inherit

(2) Method override

(3) Polymorphic reference

3. Phenomenon:

When compiling, look at the left / "parent class", and when running, look at the right / "child class".

During compilation, because the compilation is based on the parent class, only the methods of the parent class can be used, and the methods extended by the child class cannot be called;

The execution time must be the overridden method body of the running subclass.

Example code:

class Person{
	public void eat(){
		System.out.println("having dinner");
	}
	public void walk(){
		System.out.println("walk");
	}
}
class Woman extends Person{
	public void eat(){
		System.out.println("Eat slowly");
	}
	public void walk(){
		System.out.println("Graceful walking");
	}
	public void shop(){
		System.out.println("buy whatever you want...");
	}
}
class Man extends Person{
	public void eat(){
		System.out.println("A voracious meal");
	}
	public void walk(){
		System.out.println("Swagger");
	}
	public void smoke(){
		System.out.println("smoke opium");
	}
}
class Test{
    public static void main(String[] args){
        Person p = new Woman();//Polymorphic reference
        p.eat();//Perform subclass overrides
        p.walk();//Perform subclass overrides
        //p.shop();// Cannot call
    }
}

4. Application:

(1) Polymorphic parameter: the formal parameter is the parent class, and the actual parameter is the subclass object

(2) Polymorphic array: the array element type is the parent class, and the element stores the subclass objects

Example code: polymorphic parameters

class Test{
    public static void main(String[] args){
        test(new Woman());//Arguments are subclass objects
        test(new Man());//Arguments are subclass objects
    }
    public static void test(Person p){//The formal parameter is a parent type
        p.eat();
        p.walk();
    }
}

Example code: polymorphic array

class Test{
    public static void main(String[] args){
        Person[] arr = new Person[2];//Polymorphic array
        arr[0] = new Woman();
        arr[1] = new Man();
        
        for(int i=0; i<arr.length; i++){
            all[i].eat();
            all[i].walk();
        }
    }
}

5. Transformation up and down: transformation between parent and child classes

(1) Upward Transformation: automatic type conversion

When an object of a subclass is assigned to a variable of the parent class (i.e. polymorphic reference), the object will be transformed upward into the parent class at compile time. At this time, you can't see the "unique and extended" methods of the subclass.

(2) Downward Transformation: forced conversion. There are risks, and ClassCastException exceptions may be reported.

When you need to assign a parent class variable to a child class variable, you need to transition down.

To transform successfully, you must ensure that the runtime type of the object saved in the variable is < = forced conversion type

Example code:

class Person{
	//Method code omitted
}
class Woman extends Person{
    //Method code omitted
}
class ChineseWoman extends Woman{
	//Method code omitted
}
 public class Test{
     public static void main(String[] args){
		//Upward transformation
		Person p1 = new Woman();
		//Downward transformation
		Woman m = (Woman)p1; 
		//The object actually stored in the p1 variable is the Woman type, which is the same as the strongly converted Woman type

		//Upward transformation
		Person p2 = new ChineseWoman();
		//Downward transformation
		Woman w2 = (Woman) p2; 
		//The actual stored object in p2 variable is of Chinese Woman type, the mandatory type is of Chinese type, and Chinese Woman < of Chinese type     
     }
 }

6,instanceof

Expression syntax format:

object/variable  instanceof  type

Operation result: true or false

effect:

It is used to determine whether the object belongs to this type, or whether it is an object of this type or an object of a subclass of this type

Example code:

class Person{
	//Method code omitted
}
class Woman extends Person{
    //Method code omitted
}
class ChineseWoman extends Woman{
	//Method code omitted
}
 public class Test{
     public static void main(String[] args){
         Person p = new Person();
         Woman w = new Woman();
         ChineseWoman c = new ChineseWoman();
         
         if(p instanceof Woman){//false
             
         }
         if(w instanceof Woman){//true
             
         }
         if(c instanceof Woman){//true
             
         }
     }
 }

Chapter 7 advanced object-oriented features

The study of modifiers revolves around three questions:

(1) The meaning of the word

(2) What can be modified?

(3) What's the difference with it?

7.1 keyword: final

final: final

Usage:

(1) Decoration class (including external class and internal class)

Indicates that this class cannot be inherited and has no subclasses

(2) Modification method

Indicates that this method cannot be overridden

(3) Modified variables (member variables (class variables, instance variables), local variables)

Indicates that the value of this variable cannot be modified

Note: if a member variable is modified with final, it must also be assigned manually, and once this value is assigned, it cannot be modified, that is, there is no set method

7.2 keyword: native

native: native
Usage:

Can only modify methods

The method body code representing this method is not implemented in the Java language.

However, for Java programmers, they can call it normally as Java methods, or subclass rewrite it.

JVM memory management:

[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 oycbjtm5-1631456883994) (IMGs / 1555119319865. PNG)]

Method area: class information, constants, static variables, bytecode information generated by dynamic compilation

Virtual machine stack: local variables of methods implemented in Java language

Local method stack: the local variable of the method implemented in non Java language, that is, the memory area when the native method is executed

Heap: new objects

Program counter: records which instruction each thread currently executes

7.3 keyword: static

Static: static

Usage:

1. Member methods: we generally call them static methods or class methods

(1) Cannot be overridden

(2) Used

In this class: it can be used directly in other methods

In other classes, "class name. Method" can be used for calling, and "object name. Method" can also be used. It is recommended to use "class name. Method"

(3) In static methods, we can't appear: this, super, non static members

2. Member variable: we generally call it static variable or class variable

(1) The value of a static variable is shared by all objects of the class

(2) Static variables are stored in the method area

(3) The get/set corresponding to a static variable is also static

(4) When a static variable has the same name as a local variable, you can use "class name. Static variable" to distinguish it

3. Internal class: later

4. Code blocks: static code blocks

5. Static import (JDK1.5 import)

No static import

package com.atguigu.utils;

public class Utils{
    public static final int MAX_VALUE = 1000;
    public static void test(){
        //...
    }
}


package com.atguigu.test;

import com.atguigu.utils;

public class Test{
    public static void main(String[] args){
        System.out.println(Utils.MAX_VALUE);
        Utils.test();
    }
}

Use static import

package com.atguigu.utils;

public class Utils{
    public static final int MAX_VALUE = 1000;
    public static void test(){
        //...
    }
}
package com.atguigu.test;

import static com.atguigu.utils.Utils.*;

public class Test{
    public static void main(String[] args){
        System.out.println(MAX_VALUE);
        test();
    }
}

7.4 static code block

1. Syntax format:

[Modifier] class Class name{
    static{
        Static code block;
    }
}

2. Function:

Assist in class initialization and assign values to class variables.

3. Class initialization ()

Class initialization includes:

① Explicit assignment code for static variables

② Code in static code block

① and ② are executed in sequence

Note: there is only one class initialization method

4. Execution characteristics of class initialization:

(1) The () of each class is executed only once

(2) If a subclass finds that the parent class is not initialized during initialization, the parent class will be initialized first

(3) If you want both class initialization and instantiation initialization, you must complete class initialization first

7.5 classification and difference of variables

1. Variables are divided by data type:

(1) Variables of basic data type, in which data values are stored

(2) Reference a variable of data type, which stores the address value of the object

int a = 10;//Data values are stored in a

Student stu = new Student();//stu stores the address value of the object
int[] arr = new int[5];//arr stores the address value of an array object
String str = "hello";//str stores the address value of the "hello" object

2. Variables vary according to the declared location:

(1) Member variable

(2) Local variable

3. Differences between member variables and local variables

(1) The position of the declaration is different

Member variable: outside method in class

Local variable: (1) in () of the method, that is, in the local variable of {} of the formal parameter (2) method body (3) in the code block {}

(2) Different storage locations

Member variables:

If it is a static variable (class variable), in the method area

If it is a non static variable (instance variable), it is in the heap

Local variables: stack

(3) Different modifiers

Member variables: 4 kinds of permission modifiers, static, final....

Local variables: only final

(4) Life cycle

Member variables:

If it is a static variable (class variable), it is the same as the class

If it is a non static variable (instance variable), it is the same as the object to which it belongs, and each object is independent

Local variables: new for each execution

(5) Scope

Member variables:

If it is a static variable (class variable), use it casually in this class and use "class name. Static variable" in other classes“

If it is a non static variable (instance variable), it can only be used in non static members in this class, and "object name. Non static variable" can be used in other classes“

Local variables: scoped

7.7 root parent class

1. The java.lang.Object class is the root parent of the class hierarchy. It includes array objects.

(1) All methods declared in the Object class will be inherited into subclasses, that is, all objects have methods in the Object class

(2) Each Object creation will eventually call the Object instance initialization method ()

(3) Object type variables, formal parameters and arrays can store objects of any type

2. Common methods of Object class

(1)public String toString():

① By default, the return is the hexadecimal form of the hashCode value of the object's runtime type @ object“

② It is usually recommended to rewrite. In eclipse, you can use Alt +Shift + S – > generate tostring()

③ If we directly system. Out. Println (object), the toString() of this object will be called automatically by default

(2) Public final class <? > getclass(): get the runtime type of the object

(3) protected void finalize(): when an object is determined by the GC as garbage to be recycled, the GC will call this method for you before recycling. Moreover, this method will only be called once. Subclasses can choose to override it.

(4) public int hashCode(): returns the hash value of each object.

Provisions: ① if the hash values of two objects are different, the two objects must not be equal;

② if the hash values of two objects are the same, the two objects are not necessarily equal.

It is mainly used to improve performance when the object is stored in a hash table.

(5) public boolean equals(Object obj): used to judge whether the current object this is equal to the specified object obj

① By default, the implementation of the equals method is equivalent to "= =", comparing the address value of the object

② We can choose to rewrite some requirements:

A: If equals is overridden, the hashCode() method must be overridden together, because it stipulates:

a: if two objects call equals and return true, the hashCode values of the two objects must be equal;

b: if the hashCode values of two objects are different, it must be false for the two objects to call the equals method;

c: if the hashCode values of two objects are the same, the two objects calling equals may be true or false

B: If you rewrite equals, you must follow the following principles:

a: Reflexivity: x.equals(x) returns true

b: transitivity: x.equals(y) is true, y.equals(z) is true, and then x.equals(z) should also be true

c: consistency: as long as the attribute values involved in the equals comparison are not modified, the call results should be consistent at any time

d: symmetry: the results of x.equals(y) and y.equals(x) should be the same

e: non empty objects and null equals must be false

7.8 keyword: abstract

1. When will abstract methods and classes be used?

When declaring a parent class, the implementation of the method body of some methods in the parent class cannot be determined, but can only be determined by the child class. However, the parent class should also reflect the common characteristics of the child classes, that is, it should include this method in order to uniformly manage the objects of each sub class, that is, for polymorphic application.

At this point, you can choose to declare such a method as an abstract method. If a class contains abstract methods, the class must be an abstract class.

2. Syntax format of abstract classes

[Permission modifier] abstract class Class name{
    
}
[Permission modifier] abstract class Class name extends Parent class{
    
}

3. Syntax format of abstract method

[Other modifiers] abstract Return value type method name([Formal parameter list]);

Abstract method has no method body

4. Characteristics of abstract classes

(1) Abstract classes cannot be instantiated directly, that is, new objects cannot be instantiated directly

(2) Abstract classes are used to be inherited. After a subclass inherits an abstract class, it must override all abstract methods, otherwise the subclass must also be an abstract class

(3) the abstract class also has a constructor. The function of this structure is not to create the object of the abstract class, but to call the subclass in the instantiation process.

(4) Abstract classes can also have no abstract methods, so the purpose is not to let you create objects, but to let you create objects of its subclasses

(5) Variables of an abstract class and objects of its subclasses also constitute polymorphic references

5. Modifier that cannot be used with abstract?

(1) Final: and final cannot modify methods and classes together

(2) Static: and static cannot modify methods together

(3) Native: and native cannot modify methods together

(4) Private: and private cannot modify methods together

7.9 interface

1. Concept of interface

Interface is a standard. Pay attention to standards of conduct (i.e. methods).

There is one principle of object-oriented development: interface oriented programming.

2. Declaration format of interface

[Modifier] interface Interface name{
    Member list of interface;
}

3. Class implements the format of the interface

[Modifier] class Implementation class  implements Parent interfaces{
    
}

[Modifier] class Implementation class extends Parent class implements Parent interfaces{
    
}

4. Interface inherits the format of the interface

[Modifier] interface Interface name extends Parent interfaces{
    Member list of interface;
}

5. Characteristics of interface

(1) Interfaces cannot be instantiated directly, that is, new objects cannot be instantiated directly

(2) If only connected implementation class objects can be created, polymorphic references can be formed between the interface and its implementation class objects.

(3) When implementing an interface, the implementation class must override all abstract methods, otherwise the implementation class must also be an abstract class.

(4) Java stipulates that only single inheritance can be used between classes, but the relationship between Java classes and interfaces is multi implementation, that is, a class can implement multiple interfaces at the same time

(5) Java also supports multiple inheritance between interfaces.

6. Members of the interface

Before JDK1.8:

(1) Global static constants: public static final. These modifiers can be omitted

(2) Public Abstract: public abstract. These modifiers can also be omitted

After JDK1.8:

(3) Public static method: public static, which cannot be omitted

(4) The public default method: public default, which cannot be omitted

7. Default method conflict problem

(1) When an implementation class implements two or more interfaces at the same time, the signatures of the default methods of the multiple interfaces are the same.

Solution:

Scheme 1: choose to keep one of them

Interface name.super.Method name([Argument list]);

Scheme 2: complete rewriting

(2) When an implementation class inherits the parent class and implements the interface, a method in the parent class has the same signature as the default method of the interface

Solution:

Scheme 1: the default scheme keeps the parent class

Scheme 2: select reserved interface

Interface name.super.Method name([Argument list]);

Scheme 3: complete rewriting

8. Sample code

public interface Flyable{
	long MAX_SPEED = 7900000;
    void fly();
}
public class Bird implements Flyable{
    public void fly(){
        //....
    }
}

9. Common interfaces

(1) java.lang.Comparable interface: natural sorting

Abstract method: int compareTo(Object obj)

(2) java.util.Comparator interface: custom sorting

Abstract method: int compare (object obj1, object obj2)

(3) Sample code

If the employee types, the default order and the natural order are arranged in ascending order, then the Comparable interface is implemented

class Employee implements Comparable{
    private int id;
    private String name;
    private double salary;
    
    //Constructor, get/set,toString are omitted
    
    @Override
    public int compareTo(Object obj){
        return id - ((Employee)obj).id;
    }
}

If you find new requirements later and want to sort by salary, you can only choose to use custom sorting to implement the Comparator interface

class SalaryComparator implements Comparator{
    public int compare(Object o1, Object o2){
        Employee e1 = (Employee)o1;
        Employee e2 = (Employee)o2;
        if(e1.getSalary() > e2.getSalary()){
            return 1;
        }else if(e1.getSalary() < e2.getSalary()){
            return -1;
        }
        return 0;
    }
}

7.10 internal class

1. Concept of inner class

A class declared in another class is an inner class.

2. Four forms of inner classes

(1) Static inner class

(2) Non static member inner class

(3) Local inner class with name

(4) Anonymous inner class

7.10.1 anonymous inner class

1. Syntax format:

//Calling the anonymous structure of the parent class in the anonymous sub class
new Parent class(){
    Member list of inner class
}

//Calling the parameter structure of the parent class in the anonymous sub class
new Parent class(Argument list){
    Member list of inner class
}

//If the interface does not have a constructor, it means that the anonymous subclass calls its own parameterless construction and the parameterless construction of the default parent class Object
new Parent interface name(){
    
}

2. What is the difference between anonymous inner classes and anonymous objects?

System.out.println(new Student("Zhang San"));//Anonymous object

Student stu = new Student("Zhang San");//This object has a name, stu

//It has both an anonymous inner class and an anonymous object
new Object(){
    public void test(){
        .....
    }
}.test();

//The Object of this anonymous inner class uses the name obj to reference it. The Object has a name, but the subclass of this Object has no name
Object obj = new Object(){
    public void test(){
        .....
    }
};

3. Form used

(1) Example code: inherited

abstract class Father{
    public abstract void test();
}
class Test{
    public static void main(String[] args){
        //Use the objects of the parent class and the anonymous inner class to form a polymorphic reference
        Father f = new Father(){
            public void test(){
                System.out.println("Inherited with an anonymous inner class Father This abstract class is overridden test Abstract method")
            }
        };
        f.test();
    }
}

(2) Example code: Implementation

interface Flyable{
    void fly();
}
class Test{
    public static void main(String[] args){
        //The parent interface and the object of the anonymous inner class form a polymorphic reference
        Flyable f = new Flyable(){
            public void fly(){
                System.out.println("Implemented with anonymous inner classes Flyable This interface overrides the abstract method");
            }
        };
        f.fly();
    }
}

(3) Example code: call a method directly with an anonymous object of an anonymous inner class

new Object(){
    public void test(){
        System.out.println("Calling methods directly with anonymous objects of anonymous inner classes")
    }
}.test();

(4) Example code: use the anonymous object of the anonymous inner class as an argument directly

Student[] all = new Student[3];
all[0] = new Student("Zhang San",23);
all[1] = new Student("Li Si",22);
all[2] = new Student("Wang Wu",20);

//Use the anonymous object of the anonymous inner class as an argument directly
//This anonymous inner class implements the Comparator interface
//The object of this anonymous inner class is the object of the custom comparator
Arrays.sort(all, new Comparator(){
    public int compare(Obeject o1, Object o2){
        Student s1 = (Student)o1;
        Student s2 = (Student)o2;
        return s1.getAge() - s2.getAge();
    }
});

7.10.2 static internal class

1. Syntax format

[Modifier] class External class name[ extends Parent of external class][ implements Parent interface of external class]{
	[Other modifiers] static class  Static inner class[ extends Static internal class [its own parent][ implements Parent interface of static inner class]{
        Member list of static inner class;
	}
	
	List of other members of the external class;
}

2. Precautions for use

(1) Whether the included members have requirements:

Can contain all members of a class

(2) Modifier requirements:

  • Permission modifiers: 4 kinds
  • Other modifiers: abstract, final

(3) Are there requirements on members using external classes

  • Only static members of external classes can be used

(4) Is there a requirement to use static inner classes in outer classes

  • Normal use

(5) Is it required to use static inner classes outside the outer classes

(1)If you are using static members of a static inner class
		External class name.Static internal class name.Static member
(2)If you are using a non static member of a static inner class
		①First create the object of the static inner class
		External class name.Static internal class name object name = new External class name.Static internal class name([Argument list]);
		②Calling non static members through objects
		Object name.xxx

(6) Bytecode file form: external class name $static internal class name. Class

3. Sample code

class Outer{
    private static int i = 10;
    static class Inner{
        public void method(){
            //...
            System.out.println(i);//sure
        }
        public static void test(){
            //...
            System.out.println(i);//sure
        }
    }
    
    public void outMethod(){
        Inner in = new Inner();
        in.method();
    }
    public static void outTest(){
        Inner in = new Inner();
        in.method();
    }
}
class Test{
    public static void main(String[] args){
        Outer.Inner.test();
        
        Outer.Inner in = new Outer.Inner();
        in.method();
    }
}

7.10.3 non static internal class

1. Syntax format

[Modifier] class External class name[ extends Parent of external class][ implements Parent interface of external class]{
	[Modifier] class  Non static inner class[ extends [non static inner class's own parent][ implements Parent interface of non static inner class]{
        Member list of non static inner classes;
	}
	
	List of other members of the external class;
}

2. Precautions for use

(1) Whether the included members have requirements:

Static members are not allowed

(2) Modifier requirements

Permission modifiers: 4 kinds

Other modifiers: abstract, final

(3) Are there requirements on members using external classes

Can be used

(4) Is it required to use non static inner classes in external classes

Non static inner classes cannot be used in static members of an outer class

(5) Is it required to use non static inner classes outside the outer class

//Use non static members of non static inner classes
//(1) Create an object of an external class
 External class name object name 1 = new  External class name([Argument list]);

//(2) Create or obtain the object of non static internal class through the object of external class
//establish
 External class name.Non static internal class name object name 2 = Object name 1.new Non static internal class name([Argument list]);

//obtain
 External class name.Non static internal class name object name 2 = Object name 1.get Methods of non static inner class objects([Argument list]);

//(3) Call its non static members through a non static inner class
 Object name 2.xxx

(6) Bytecode file form: external class name $non static internal class name. Class

3. Sample code

class Outer{
    private static int i = 10;
    private int j = 20;
    class Inner{
        public void method(){
            //...
            System.out.println(i);//sure
            System.out.println(j);//sure
        }
    }
    
    public void outMethod(){
        Inner in = new Inner();
        in.method();
    }
    public static void outTest(){
       // Inner in = new Inner();// may not
    }
    
    public Inner getInner(){
        return new Inner();
    }
}
class Test{
    public static void main(String[] args){
        Outer out = new Outer();
        
        Outer.Inner in1 = out.new Inner();     //establish   	
        in1.method();
        
        Outer.Inner in2 = out.getInner();	//obtain
        in2.method();
    }
}

7.10.4 local internal class

1. Syntax format

[Modifier] class External class name[ extends Parent of external class][ implements Parent interface of external class]{
	[Modifier] return value type method name([Formal parameter list]){
        [Modifier] class  Local inner class[ extends Local internal class [its own parent][ implements Parent interface of local inner class]{
        	Member list of local inner class;
		}
	}	
	List of other members of the external class;
}

2. Precautions for use

(1) Are there any requirements for the included members

Static members are not allowed

(2) Modifier requirements

Permission modifier: cannot

Other modifiers: abstract, final

(3) Are there requirements for using members of external classes

① use static members of external classes: use them casually

② use non static members of external classes: whether they can be used depends on whether the method is static

③ local variable of the method used: it must be modified by final

(4) Is it required to use local inner classes in external classes

Scoped

(5) Is it required to use local inner classes outside the outer class

Can't use

(6) Bytecode file form: external class name $number, local internal class name. Class

3. Sample code

class Outer{
    private static int i = 10;
    private int j = 20;

    
    public void outMethod(){
        class Inner{
            public void method(){
                //...
                System.out.println(i);//sure
                System.out.println(j);//sure
            }
   		}
        Inner in = new Inner();
        in.method();
    }
    public static void outTest(){
        final int k = 30;
       class Inner{
            public void method(){
                //...
                System.out.println(i);//sure
                System.out.println(j);//may not
                System.out.println(k);//sure
            }
   		}
        Inner in = new Inner();
        in.method();
    }
}

Chapter 8 enumeration and annotation

8.1 enumeration

1. Enumeration (introduced in JDK1.5)

Objects of enumeration type are limited and fixed constant objects.

2. Syntax format

//Form 1: there is only a constant object list in the enumeration type
[Modifier] enum Enumeration type name{
    Constant object list
}

//Form 2: there is only a constant object list in the enumeration type
[Modifier] enum Enumeration type name{
    Constant object list;
    
    List of other members;
}

Description: the list of constant objects must be in the first line of enumeration type

Recall: first line

(1) super() or super (argument list): must be in the first line of the subclass constructor

(2) this() or this (argument list): must be in the first line of this class constructor

(3) Package; The statement declaring the package must be on the first line of the source file. java

(4) The list of enumeration constant objects must be on the first line of the enumeration type

3. How to get enumerated constant objects in other classes

//Get a constant object
 Enumeration type name.Constant object name

//Get a constant object
 Enumeration type name.valueOf("Constant object name")
    
//Get all constant objects
 Enumeration type name[] all = Enumeration type name.values();

4. Characteristics of enumeration types

(1) Enumeration type has a common basic parent class, which is java.lang.Enum type, so it can not inherit other types

(2) Constructor of enumeration type must be private

(3) Enumeration types can implement interfaces

interface MyRunnable{
    void run();
}
enum Gender implements MyRunnable{
    NAN,NV;
    public void run(){
        //...
    }
}
//or
enum Gender implements MyRunnable{
    NAN{
        public void run(){
       	 //...
    	}
    },NV{
        public void run(){
        //...
   		}
    };
    
}

5. Parent java.lang.Enum type

(1) Constructor

protected Enum(String name, int ordinal): automatically called by the compiler

(2) String name(): constant object name

(3) int ordinal(): returns the ordinal number of a constant object. The first ordinal number is 0

(4) String toString(): returns the name of the constant object. If the subclass wants to override it, it needs to be manually overridden

(5) int compareTo(Object obj): compare in the order of constant objects

8.2 notes

1. Annotation

It is a code level comment

2. Marking symbol:@

3. Three basic annotations predefined by the system:

(1) @ Override: indicates that a method is an overridden method

It can only be used on methods. It will let the compiler check the format of this method to see if it meets the rewriting requirements

(2) @ SuppressWarnings(xx): suppress warnings

(3) @ Deprecated: indicates that xx is obsolete

4. Comments related to document comments

(1) Document notes

/**
Documentation Comments 
*/

(2) Common document notes

@author: author

@since: added from version xx

@see: see also

@param: parameter

@Return: return value

@throws or @ exception: exception

5. Several notes related to JUnit

(1) @ Test: indicates that it is a unit Test method

This method needs to be: public void xxx() {}

(2) @ Before: indicates execution Before each unit test method

This method needs to be: public void xxx() {}

(3) @ After: indicates execution After each unit test method

This method needs to be: public void xxx() {}

(4) @ BeforeClass: indicates that it is executed during class initialization and only once

This method needs to be: public static void xxx() {}

(3) @ AfterClass: indicates that it is executed in the "uninstall" phase of the class and only once

This method needs to be: public static void xxx() {}

6. Meta annotation

(1) @ Target(xx): the annotation marked with it can be used in xx position

(xx): specified by 10 constant objects of ElementType enumeration TYPE, such as TYPE, METHOD, FIELD, etc

For example:

@Target(ElementType.TYPE)

@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
import static java.lang.annotation.ElementType.*;


@Target({TYPE,METHOD,FIELD})

(2) @ Retention (xx): the annotation marked with it can stay until xx stage

(xx): specified by three constant objects of RetentionPolicy enumeration type: SOURCE, CLASS and RUNTIME

Only annotations in the RUNTIME phase can be read by reflection

For example:

@Retention(RetentionPolicy.RUNTIME)

(3) @ Documentd: the annotations marked with it can be read into the API

(4) @ Inherited: the annotation marked with it can be Inherited by subclasses

7. Custom annotation

@Meta annotation
[Modifier] @interface Annotation name{
    
}

@Meta annotation
[Modifier] @interface Annotation name{
    Configuration parameter list
}

Syntax format of configuration parameters:

Data type configuration parameter name();

or

Data type configuration parameter name() default Default value;

About configuration parameters:

(1) The type of configuration parameters requires:

Eight basic data types, String, enumeration, Class type, annotation, and their arrays.

(2) If a custom annotation declares a configuration parameter, the configuration parameter must be assigned when using this annotation unless it has a default value

@Custom annotation name(Configuration parameter name 1=Value, configuration parameter name 2=Value...)

//If the configuration parameter type is an array, you can use {} to represent the array during assignment
@Custom annotation name(Configuration parameter name 1={value},Configuration parameter name 2=Value...)

(3) If there is only one configuration parameter and the name is value, value can be omitted during assignment=

(4) If you want to get the value of the configuration parameter when reading this annotation, you can access it as a method

Custom annotation object.configuration parameter();

Chapter IX exceptions

9.1 architecture of exception types

1. Super parent class of exception series: java.lang.Throwable

(1) Only objects of it or its subclasses can be "thrown" by the JVM or throw statement

(2) Only the objects of it or its subclasses can be caught

2. Throwable is divided into two factions

(1) Error: a serious error. You need to stop, redesign and upgrade to solve this problem

(2) Exception: a general exception, which can be avoided by judgment and inspection, or handled by try... catch

3. Exception s fall into two categories

(1) Runtime exception:

It is an object of RuntimeException or its subclass.

For this type of exception, the compiler will not remind you to throw or try... catch, but the runtime may cause a crash.

(2) Compile time exception:

Exceptions except runtime exceptions are compile time exceptions.

For this type of exception, the compiler forces you to handle throws or try... catch, otherwise the compilation fails.

4. List common exception types

(1) Runtime exception

RuntimeException, NullPointerException (null pointer exception), ClassCastException (type conversion exception), arithmetexception (arithmetic exception), NubmerFormatException (number formatting exception), IndexOutOfBoundsException (subscript out of bounds exception) (ArrayIndexOutOfBoundsException (array subscript out of bounds exception), StringIndexOutOfBoundsException (string subscript out of bounds exception), InputMisMatchException (input type mismatch exception)....

(2) Compile time exception

FileNotFoundException (exception not found in the file), IOException (input / output exception), SQLException (database sql statement execution exception)...

9.2 exception handling

1. Handle in current method: try... catch... finally

//Form 1: try...catch
try{
    Possible exception codes
}catch(Exception type exception name e){
    Code for handling exceptions (usually statements that print exception information)
}catch(Exception type exception name e){
    Code for handling exceptions (usually statements that print exception information)
}. . . 


//Form 2: try...finally
try{
    Possible exception codes
}finally{
    whether try Whether there is any abnormality in the, whether it is or not return,The part to be executed
}

//Form 3: try..catch..finally
try{
    Possible exception codes
}catch(Exception type exception name e){
    Code for handling exceptions (usually statements that print exception information)
}catch(Exception type exception name e){
    Code for handling exceptions (usually statements that print exception information)
}. . . 
finally{
    whether try It doesn't matter whether there are exceptions in the catch It doesn't matter whether exceptions can be caught try and catch Is there any in the return,The part to be executed
}

Execution features:

(1) If there is no exception in the code in the try, the code in the try will execute normally, the catch part will not execute, and finally will execute

(2) If the code in the try has an exception, the code with an exception in the try will not be executed. Find the corresponding catch branch for execution, and finally it will be executed

[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-mosdJNjb-1631456884004)(imgs/1559610439025.png)]

2. When finally and return are mixed

(1) If there is a return in finally, it must be returned from the return in finally.

At this time, the return statement in try and catch is half executed and the first action is executed. Therefore, the return statement in finally will overwrite the just returned value

Return return value; the statement has two actions: (1) put the return value into the "operand stack". After the current method ends, the value in the "operand stack" will be returned to the caller; (2) end the execution of the current method

(2) If there is no return in finally, the statement in finally will be executed, but the final return value will not be affected

That is, the return statements in try and catch are separated in two steps. First, (1) put the return value into the operand stack, (2) then go to the statement in finally (3) and then execute the second half of return to end the current method

3. Do not handle exceptions in the current method, and explicitly throw them to the caller for processing. Use throws

Syntax format:

[Modifier] return value type method name([Formal parameter list]) throws Exception list{
    
}

At this point, the caller knows which exceptions to handle.

Requirements for method Rewriting:

(1) Method name: same

(2) Formal parameter list: same

(3) Return value type:

Basic data type and void: the same

Reference data type:<=

(4) Modifier:

Permission modifier: >=

Other modifiers: static, final, private cannot be overridden

(5)throws: <=

Method overload:

(1) Method name: same

(2) Formal parameter list: must be different

(3) Return value type: irrelevant

(4) Modifiers: irrelevant

(5) throws: irrelevant

9.3 exception thrown manually: throw

throw Exception object;

//For example:
throw new AccountException("xxx");

Like the exception object thrown by the JVM, the exception object thrown by throw should also be handled with try... catch or throws.

If it is a runtime exception, the compiler will not force you to handle it. If it is a compile time exception, the compiler will force you to handle it.

9.4 custom exception

1. You must inherit Throwable or its subclasses

We often see the inheritance of RuntimeException and Exception

If you inherit RuntimeException or its subclass, the exception you customize is a runtime exception. The compiler won't remind you to handle it.

If you inherit Exception, it belongs to compile time Exception, and the compiler will force you to handle it.

2. I suggest you keep two constructors

//Nonparametric structure
public Custom exception name(){
    
}

//Parametric structure
public Custom exception name(String message){
    super(message);
}

3. Custom exception objects must be thrown manually and thrown with throw

9.5 several methods of exception

(1) e.printStackTrace(): print the details of the exception object, including exception type, message and stack trace information. This is very useful for debugging or log tracing

(2) e.getMessage(): just get the abnormal message information

Printing of exception information:

Printing with System.err and e.printStackTrace() are highlighted in red.

Print with System.out as general information.

These two printing are two independent threads, and the order cannot be accurately controlled.

Chapter 10 multithreading

10.1 related concepts

1. Program

A set of instructions written in a programming language to implement a function and complete a task.

2. Process

A run of a program. The operating system allocates resources (memory) to the process.

A process is the smallest unit of resources allocated by the operating system.

The memory between processes is independent and cannot be shared directly.

The earliest DOS operating system was single task and could only run one process at a time. Later, the current operating systems support multitasking and can run multiple processes at the same time. Switch back and forth between processes. The cost is relatively high.

3. Thread

A thread is one of the execution paths in a process. A process can have at least one thread or multiple threads. Threads are sometimes called lightweight processes.

Some memory can be shared among multiple threads of the same process (method area and heap), and some memory is independent (stack (including virtual machine stack and local method stack) and program counter).

The cost of switching between threads is relatively low compared with processes.

4. Parallelism: multiple processors can execute multiple execution paths at the same time.

5. Concurrency: multiple tasks are executed at the same time, but there may be a sequence relationship.

10.2 two ways to implement multithreading

1. Inherit Thread class

Steps:

(1) Write a Thread class to inherit the Thread class

(2) Override public void run() {}

(3) Create thread object

(4) Call start()

class MyThread extends Thread {
    public void run(){
        //...
    }
}
class Test{
    public static void main(String[] args){
        MyThread my = new MyThread();
        my.start();//Thread object with name starts
        
        new MyThread().start();//Anonymous thread object start
        
        //Anonymous object startup of anonymous inner class
        new Thread(){
            public void run(){
                //...
            }
        }.start();
        
        //Anonymous internal class, but start the thread through the variable polymorphic reference of the parent class
        Thread t =  new Thread(){
            public void run(){
                //...
            }
        };
        t.start();
    }
}

2. Implement Runnable interface

Steps:

(1) Write a thread class to implement the Runnable interface

(2) Override public void run() {}

(3) Create thread object

(4) Start a Thread with the object of the Thread class

class MyRunnable implements Runnable{
    public void run(){
        //...
    }
}
class Test {
    public static void main(String[] args){
        MyRunnable my = new MyRunnable();
        Thread t1 = new Thread(my);
        Thread t2 = new Thread(my);
        t1.start();
        t2.start();
        
        //Two anonymous objects
        new Thread(new MyRunnable()).start();
        
        //The anonymous object of the anonymous inner class is passed directly to the constructor of Thread as an argument
        new Thread(new Runnable(){
            public void run(){
                //...
            }
        }).start();
            
    }
}

10.3 thread life cycle

[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-7AGJMmdf-1631456884011)(imgs/1559782705811.png)]

10.4 Thread related API

1. Constructor

  • Thread()
  • Thread(String name)
  • Thread(Runnable target)
  • Thread(Runnable target, String name)

2. Other methods

(1)public void run()

(2)public void start()

(3) Get current thread object: Thread.currentThread()

(4) Get the name of the current thread: getName()

(5) Set or get the priority of the thread: set/getPriority()

Priority range: [1,10], there are three constants in Thread class: MAX_PRIORITY(10),MIN_PRIORITY(1),NORM_PRIORITY(5)

Priority only affects probability.

(6) Thread sleep: thread.sleep (MS)

(7) Interrupt thread: interrupt()

(8) Pause current thread: Thread.yield()

(9) Thread to plug: join()

The code of xx.join() is written in which thread body and which thread is blocked, which has nothing to do with other threads.

(10) Determine whether the thread has started but not terminated: isAlive()

10.5 keyword: volatile

Volatile: volatile, unstable, not necessarily when

Modifiers: member variables

Function: when multiple threads access a member variable at the same time and access it frequently, if they find that its value has not been modified after multiple accesses, the Java execution engine will cache the value of this member variable. Once cached, if a thread modifies the value of this member variable at this time, the Jav execution engine still reads it from the cache, resulting in the value being not up-to-date. If you don't want the Java execution engine to cache the value of this member variable, you can add volatile in front of the member variable. Every time you use this member variable, it is read from main memory.

10.6 keyword: synchronized

1. Under what circumstances can thread safety problems occur?

(1) Multiple threads

(2) Shared data

(3) In the thread body of multiple threads, when multiple statements operate the shared data again

2. How to solve thread safety problems? Synchronous lock

Form 1: synchronous code block

Form 2: synchronization method

3. Synchronous code block

synchronized(Lock object){
    //One time task code, in which the code does not want other threads to intervene during execution
}

Lock object:

(1) Any type of object

(2) Ensure that these threads that share data use the same lock object

4. Synchronization method

synchronized [Modifier] return value type method name([Formal parameter list])throws Exception list{
    //Only one thread can run at a time
}

Lock object:

(1) Non static method: this (cautious)

(2) Static method: the Class object of the current Class

10.7 thread communication

1. In order to solve the "producer and consumer problem".

When some threads are responsible for putting data into the "data buffer", another thread is responsible for fetching data from the "data buffer".

Question 1: producer threads and consumer threads use the same data buffer, that is, they share data, so synchronization should be considered

Problem 2: when the data buffer is full, the producer thread needs to wait(). After the consumer consumes the data, it needs to notify or notifyAll

When the data buffer is empty, the consumer thread needs wait(). When the producer produces data, it needs notify or notifyAll

2. The java.lang.Object class declares:

(1) wait(): must be called by the synchronization lock object

(2) Notify() and notifyAll(): must be called by the synchronization lock object

3. Interview question: the difference between sleep() and wait

(1) sleep() does not release the lock, wait() releases the lock

(2) sleep() is declared in the Thread class, and wait() is declared in the Object class

(3) sleep() is a static method, which is Thread.sleep()

wait() is a non static method and must be called by the synchronization lock object

(4) After the sleep() method causes the current thread to enter the blocking state, when the time is up or interrupt() wakes up

After the wait() method causes the current thread to enter the blocking state, notify or notifyAll() is used

4. What actions release the lock?

(1) The lock is automatically released after the synchronization code block or synchronization method is normally executed once

(2) The synchronization code block or synchronization method ends prematurely when it encounters return

(3)wait()

5. Do not release the lock

(1)sleep()

(2)yield()

(3)suspend()

Chapter XI common categories

11.1 packaging

11.1.1 packaging

When you want to use API s or new features designed only for objects (such as generics), the data of basic data types needs to be wrapped with wrapper classes.

Serial numberBasic data typePackaging
1byteByte
2shortShort
3intInteger
4longLong
5floatFloat
6doubleDouble
7charCharacter
8booleanBoolean
9voidVoid

11.1.2 packing and unpacking

After JDK1.5, it can automatically pack and unpack.

Note: automatic packing and unpacking can only be realized between the corresponding types.

Integer i = 1;
Double d = 1;//Wrong, 1 is of type int

Packing: convert the basic data type to a packing class object.

Objects that are converted to wrapper classes are designed to use API s and features specifically designed for objects

Unpacking: unpacks packaging objects into basic data types.

The conversion to basic data type is generally due to the need for operation. Most operators in Java are designed for basic data types. Comparison, arithmetic, etc

Summary: what operators can be used for objects (reference data types)?

(1)instanceof

(2) =: assignment operator

(3) = = and! =: It is used to compare addresses, but the types of objects on the left and right sides are consistent or have parent-child class inheritance relationship.

(4) For special objects such as strings, "+" is supported to indicate splicing.

11.1.3 some API s for packaging

1. Conversion between basic data type and string

(1) Convert basic data type to string

int a = 10;
//String str = a;// FALSE
//Mode 1:
String str = a + "";
//Mode 2:
String str = String.valueOf(a);

(2) Convert string to basic data type

int a = Integer.parseInt("String of integers");
double a = Double.parseDouble("Decimal string");
boolean b = Boolean.parseBoolean("true or false");

2. Max min value of data type

Integer.MAX_VALUE and Integer.MIN_VALUE
Long.MAX_VALUE and Long.MIN_VALUE
Double.MAX_VALUE and Double.MIN_VALUE

3. Case conversion

Character.toUpperCase('x');
Character.toLowerCase('X');

4. Conversion system

Integer.toBinaryString(int i) 
Integer.toHexString(int i)
Integer.toOctalString(int i)

11.1.4 caching of wrapper objects

PackagingCache object
Byte-128~127
Short-128~127
Integer-128~127
Long-128~127
FloatNo,
DoubleNo,
Character0~127
Booleantrue and false
Integer i = 1;
Integer j = 1;
System.out.println(i == j);//true

Integer i = 128;
Integer j = 128;
System.out.println(i == j);//false

Integer i = new Integer(1);//The new is in the heap
Integer j = 1;//This uses a buffered constant object in the method area
System.out.println(i == j);//false

Integer i = new Integer(1);//The new is in the heap
Integer j = new Integer(1);//Another new is in the heap
System.out.println(i == j);//false

Integer i = new Integer(1);
int j = 1;
System.out.println(i == j);//true, all comparisons with basic data types will be unpacked first and compared according to the rules of basic data types

11.2 string

11.2.1 characteristics of string

1. The String type itself is declared by final, which means that we cannot inherit String.

2. The object of the string is also an immutable object, which means that once it is modified, a new object will be generated

After we modify the string, if we want to get new content, we must accept it again.

If the program involves a large number of string modification operations, the time and space consumption is relatively high. You may need to consider using StringBuilder or StringBuffer.

3. String objects are stored internally in character arrays

There is a char[] value array before JDK1.9 and a byte [] array after JDK1.9

4. The char[] values array in the String class is also final modified, which means that the array is immutable, and then it is private modified. It cannot be operated directly externally. All the methods provided by the String type use new objects to represent the modified contents, so it ensures the immutability of the String object.

5. Because the string object is designed to be immutable, the string has a constant pool to hold many constant objects

The constant pool is in the method area.

If detailed division:

(1) JDK1.6 and before: method area

(2) JDK1.7: reactor

(3) JDK1.8: meta space

11.2.2 comparison of string objects

1. = =: the address of the comparison object

true is returned only if both string variables are constant objects pointing to strings

String str1 = "hello";
String str2 = "hello";
str1 == str2//true

2. Equals: the comparison is the content of the object, because the String type overrides equals and is case sensitive

As long as the character contents of the two strings are the same, true will be returned

String str1 = new String("hello");
String str2 = new String("hello");
str1.equals(strs) //true

3. equalsIgnoreCase: compares the contents of objects and is not case sensitive

String str1 = new String("hello");
String str2 = new String("HELLO");
str1.equalsIgnoreCase(strs) //true

4. compareTo: the String type overrides the abstract method of the Comparable interface. It is sorted naturally. It compares the size according to the Unicode encoded value of the character, and is strictly case sensitive

String str1 = "hello";
String str2 = "world";
str1.compareTo(str2) //Values less than 0

5. compareToIgnoreCase: case insensitive. Other characters are compared according to their Unicode encoding values

String str1 = new String("hello");
String str2 = new String("HELLO");
str1.compareToIgnoreCase(str2)  //Equal to 0

11.2.3 comparison of empty characters

1. What are empty strings

String str1 = "";
String str2 = new String();
String str3 = new String("");

Empty string: length 0

2. How to determine whether a string is an empty string

if("".equals(str))

if(str!=null  && str.isEmpty())

if(str!=null && str.equals(""))

if(str!=null && str.length()==0)

11.2.4 number of string objects

1. String constant object

String str1 = "hello";//1 in constant pool

2. Normal object of string

String str2 = new String();
String str22 = new String("");
//Two objects, one is an empty string object in the constant pool and the other is an empty string object in the heap

3. The normal object of the string is used together with the constant object

String str3 = new String("hello");
//str3 first points to a string object in the heap, and then the value array of strings in the heap points to the value array of constant objects in the constant pool

11.2.5 string splicing results

principle:

(1) Constant + constant: the result is a constant pool

(2) Constants and variables or variables and variables: the result is the heap

(3) call intern after splicing: the result is in constant pool.

	@Test
	public void test06(){
		String s1 = "hello";
		String s2 = "world";
		String s3 = "helloworld";
		
		String s4 = (s1 + "world").intern();//Put the splicing results into the constant pool
		String s5 = (s1 + s2).intern();
		
		System.out.println(s3 == s4);//true
		System.out.println(s3 == s5);//true
	}
	
	@Test
	public void test05(){
		final String s1 = "hello";
		final String s2 = "world";
		String s3 = "helloworld";
		
		String s4 = s1 + "world";//s4 string content is also helloworld, s1 is a constant, "world" constant, and constant + constant results are in the constant pool
		String s5 = s1 + s2;//s5 string contents are also helloworld, s1 and s2 are constants, and constant + constant results are in the constant pool
		String s6 = "hello" + "world";//Constant + constant results are in the constant pool because the results can be determined during compilation
		
		System.out.println(s3 == s4);//true
		System.out.println(s3 == s5);//true
		System.out.println(s3 == s6);//true
	}
	
	@Test
	public void test04(){
		String s1 = "hello";
		String s2 = "world";
		String s3 = "helloworld";
		
		String s4 = s1 + "world";//s4 string content is also helloworld, s1 is a variable, "world" constant, and the result of variable + constant is in the heap
		String s5 = s1 + s2;//s5 string content is helloworld, s1 and s2 are variables, and the result of variable + variable is in the heap
		String s6 = "hello" + "world";//Constant + constant results are in the constant pool because the results can be determined during compilation
		
		System.out.println(s3 == s4);//false
		System.out.println(s3 == s5);//false
		System.out.println(s3 == s6);//true
	}

11.2.6 string API

(1)boolean isEmpty()

(2)int length()

(3) String concat(xx): splicing, equivalent to+

(4)boolean contanis(xx)

(5) int indexOf(): find from front to back. If not, return - 1

(6) int lastIndexOf(): find from the back to the front. If not, return - 1

(7)char charAt(index)

(8) new String(char []) or new String(char [], int, int)

(9)char[] toCharArray()

(10) byte[] getBytes(): encoding, changing the string into a byte array and encoding according to the default character encoding of the platform

Byte [] GetBytes (character encoding method): encode according to the specified encoding method

(11) new String(byte []) or new String(byte[], int, int): decode according to the default character encoding of the platform

new String(byte [], character encoding method) or new String(byte[], int, int, character encoding method): decode according to the specified encoding method

(12) String subString(int begin): from [begin] to the end

String subString(int begin,int end): from [begin, end]

(13) Boolean matches (regular expressions)

(14) String replace(xx,xx): regular is not supported

String replacefirst (regular, value): replace the first matching part

String repalceall (regular, value): replace all matching parts

(15) String [] split (regular): split according to certain rules

(16) boolean startsWith(xx): whether it starts with xx

boolean endsWith(xx): whether it ends with xx

(17) String trim(): remove the white space before and after the string, and the white space in the middle of the string will not be removed

(18) String toUpperCase(): convert to uppercase

(19) String toLowerCase(): convert to lowercase

Interview question: what is the difference between the length of a string and the length of an array?

length() of string, length attribute of array

11.3 variable character sequence

1. Variable character sequences: StringBuilder and StringBuffer

StringBuffer: old, thread safe (because its method is decorated with synchronized)

StringBuilder: thread unsafe

2. Interview question: what is the difference between String, StringBuilder and StringBuffer?

String: immutable object, immutable character sequence

StringBuilder, StringBuffer: variable character sequence

3. The common API s, StringBuilder and StringBuffer, are identical

(1) append(xx): splice, append

(2) insert(int index, xx): Insert

(3)delete(int start, int end)

deleteCharAt(int index)

(4)set(int index, xx)

(5) reverse(): reverse

... replace, intercept, find

11.4 mathematics related

1. java.lang.Math class

(1) sqrt(): square root

(2) pow(x,y): find the Y power of X

(3) random(): returns the decimal number in the [0,1) range

(4) max(x,y): find the maximum value of x,y

min(x,y): find the minimum value

(5) round(x): round

ceil(x): enter one

floor(x): back one

...

2. java.math package

BigInteger: large integer

BigDecimal: number of sizes

The operation is completed by the method: add(),subtract(),multiply(),divide()

11.5 date time API

11.5.1 before JDK1.8

1,java.util.Date

new Date(): current system time

long getTime(): returns the millisecond value between 0.0.0 milliseconds from 1970-1-1 for the date time object

new Date(long millisecond): converts the millisecond value into a date time object

2,java.util.Calendar:

(1) getInstance(): get the tinning of Calendar

(2) Get (constant)

3. java.text.SimpleDateFormat: format of date and time

y: Indicates year

M: Month

d: Oh, my God

H: 24-hour system

h: Hour, 12 hour system

m: Cent

s: Second

S: Millisecond

E: Week

D: Number of days in the year

	@Test
	public void test10() throws ParseException{
		String str = "2019 Thursday, June 6, 2006 16:03:14.545 MS +0800";
		SimpleDateFormat sf = new SimpleDateFormat("yyyy year MM month dd day HH Time mm branch ss second SSS millisecond  E Z");
		Date d = sf.parse(str);
		System.out.println(d);
	}
	
	@Test
	public void test9(){
		Date d = new Date();

		SimpleDateFormat sf = new SimpleDateFormat("yyyy year MM month dd day HH Time mm branch ss second SSS millisecond  E Z");
		//Convert the Date into a string and convert it in the specified format
		String str = sf.format(d);
		System.out.println(str);
	}
	
	@Test
	public void test8(){
		String[] all = TimeZone.getAvailableIDs();
		for (int i = 0; i < all.length; i++) {
			System.out.println(all[i]);
		}
	}
	
	@Test
	public void test7(){
		TimeZone t = TimeZone.getTimeZone("America/Los_Angeles");
		
		//getInstance(TimeZone zone)
		Calendar c = Calendar.getInstance(t);
		System.out.println(c);
	}
	
	@Test
	public void test6(){
		Calendar c = Calendar.getInstance();
		System.out.println(c);
		
		int year = c.get(Calendar.YEAR);
		System.out.println(year);
		
		int month = c.get(Calendar.MONTH)+1;
		System.out.println(month);
		
		//...
	}
	
	@Test
	public void test5(){
		long time = Long.MAX_VALUE;
		Date d = new Date(time);
		System.out.println(d);
	}
	
	@Test
	public void test4(){
		long time = 1559807047979L;
		Date d = new Date(time);
		System.out.println(d);
	}
	@Test
	public void test3(){
		Date d = new Date();
		long time = d.getTime();
		System.out.println(time);//1559807047979
	}
	
	@Test
	public void test2(){
		long time = System.currentTimeMillis();
		System.out.println(time);//1559806982971
		//The time difference between the current system time and 1970-1-1 0:0:0 0 milliseconds, in milliseconds
	}
	
	@Test
	public void test1(){
		Date d = new Date();
		System.out.println(d);
	}

11.5.2 after JDK1.8

java.time and its sub packages.

1,LocalDate,LocalTime,LocalDateTime

(1) now(): get the system date or time

(2) of(xxx): or the specified date or time

(3) Operation: a new object is obtained after operation and needs to be accepted again

plusXxx(): adds xx to the current date or time object

minusXxx(): subtract xx from the current date or time object

methoddescribe
now() / now(ZoneId zone)Static method to create an object based on the current time / an object with a specified time zone
of()Static method to create an object based on a specified date / time
getDayOfMonth()/getDayOfYear()Days of acquisition month (1-31) / days of acquisition year (1-366)
getDayOfWeek()Gets the day of the week (returns a DayOfWeek enumeration value)
getMonth()Get the Month and return a Month enumeration value
getMonthValue() / getYear()Acquisition month (1-12) / acquisition year
getHours()/getMinute()/getSecond()Obtain the hour, minute and second corresponding to the current object
withDayOfMonth()/withDayOfYear()/withMonth()/withYear()Modify the month days, year days, month and year to the specified value and return a new object
with(TemporalAdjuster t)Sets the current date and time to the date and time specified by the proofreader
plusDays(), plusWeeks(), plusMonths(), plusYears(),plusHours()Add days, weeks, months, years, hours to the current object
minusMonths() / minusWeeks()/minusDays()/minusYears()/minusHours()Subtract months, weeks, days, years, hours from the current object
plus(TemporalAmount t)/minus(TemporalAmount t)Add or remove a Duration or Period
isBefore()/isAfter()Compare two localdates
isLeapYear()Determine whether it is a leap year (declared in the LocalDate class)
format(DateTimeFormatter t)Format the local date and time, and return a string
parse(Charsequence text)Parses the string in the specified format into date and time

2. DateTimeFormatter: date time formatting

This class provides three formatting methods:

Predefined standard formats. For example: ISO_DATE_TIME;ISO_DATE

Localization related formats, such as ofLocalizedDate(FormatStyle.MEDIUM)

Custom format. For example: ofPattern("yyyy MM DD HH: mm: SS")

	@Test
	public void test10(){
		LocalDateTime now = LocalDateTime.now();
		
//		Datetimeformatter DF = datetimeformatter.oflocalizeddatetime (formatstyle. Long); / / June 6, 2019, 04:40:03 PM
		DateTimeFormatter df = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);//19-6-6 4:40 pm
		String str = df.format(now);
		System.out.println(str);
	}
	@Test
	public void test9(){
		LocalDateTime now = LocalDateTime.now();
		
		DateTimeFormatter df = DateTimeFormatter.ISO_DATE_TIME;//2019-06-06T16:38:23.756
		String str = df.format(now);
		System.out.println(str);
	}
	
	@Test
	public void test8(){
		LocalDateTime now = LocalDateTime.now();
		
		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy year MM month dd day HH Time mm branch ss second  SSS millisecond  E It's this year D day");
		String str = df.format(now);
		System.out.println(str);
	}
	
	@Test
	public void test7(){
		LocalDate now = LocalDate.now();
		LocalDate before = now.minusDays(100);
		System.out.println(before);//2019-02-26
	}
	
	@Test
	public void test06(){
		LocalDate lai = LocalDate.of(2019, 5, 13);
		LocalDate go = lai.plusDays(160);
		System.out.println(go);//2019-10-20
	}
	
	@Test
	public void test05(){
		LocalDate lai = LocalDate.of(2019, 5, 13);
		System.out.println(lai.getDayOfYear());
	}
	
	
	@Test
	public void test04(){
		LocalDate lai = LocalDate.of(2019, 5, 13);
		System.out.println(lai);
	}
	
	@Test
	public void test03(){
		LocalDateTime now = LocalDateTime.now();
		System.out.println(now);
	}
	
	@Test
	public void test02(){
		LocalTime now = LocalTime.now();
		System.out.println(now);
	}
	
	@Test
	public void test01(){
		LocalDate now = LocalDate.now();
		System.out.println(now);
	}

Chapter XII collection

12.1 concept

Data structure: a structure that stores data

(1) Underlying physical structure

① Array: open up continuous storage space, and each element is distinguished by [subscript]

② Chained: there is no need to open up a continuous storage space, but a "node" is needed to package the data to be stored. The node contains two parts:

A. data

B. record the addresses of other nodes, such as next, pre, left, right, parent, etc

(2) Logical structure: dynamic array, one-way linked list, two-way linked list, queue, stack, binary tree, hash table, graph, etc

12.2 manually implement some logical structures

1. Dynamic array

contain:

(1) An array is used internally to store data

(2) A total is used internally to record the number of elements actually stored

public class MyArrayList {
	//Why use Object? It's just that this container is used to hold objects, but I don't know what objects it is used to hold.
	private Object[] data;
	private int total;
	
	public MyArrayList(){
		data = new Object[5];
	}
	
	//Add an element
	public void add(Object obj){
		//Check whether capacity expansion is required
		checkCapacity();
		data[total++] = obj;
	}

	private void checkCapacity() {
		//If the data is full, the capacity will be doubled
		if(total >= data.length){
			data = Arrays.copyOf(data, data.length*2);
		}
	}
	
	//Returns the number of actual elements
	public int size(){
		return total;
	}
	
	//Returns the actual capacity of the array
	public int capacity(){
		return data.length;
	}
	
	//Get element at [index] position
	public Object get(int index){
		//Check the rationality range of the index
		checkIndex(index);
		return data[index];
	}

	private void checkIndex(int index) {
		if(index<0 || index>=total){
			throw new RuntimeException(index+"The element at the corresponding position does not exist");
//			throw new IndexOutOfBoundsException(index + "out of bounds");
		}
	}
	
	//Replace the element at [index]
	public void set(int index, Object value){
		//Check the rationality range of the index
		checkIndex(index);
		
		data[index] = value;
	}
	
	//Insert an element value at [index]
	public void insert(int index, Object value){
		/*
		 * (1)Consider the rationality of subscript
		 * (2)Is the total length sufficient
		 * (3)[index]And the following elements move back to free up the [index] position
		 * (4)data[index]=value  Add new element
		 * (5)total++  The number of effective elements increases
		 */
		
		//(1) Consider the rationality of subscript: check the rationality range of index
		checkIndex(index);
		
		//(2) Whether the total length is enough: check whether the capacity needs to be expanded
		checkCapacity();
		
		//(3) Move the [index] and the following elements back to make room for the [index] position
		/*
		 * Suppose total = 5, data.length= 10, index= 1
		 * Subscript of valid element [0,4]
		 * Move: [1] - [2], [2] - [3], [3] - [4], [4] - [5]
		 * Number of elements moved: total index
		 */
		System.arraycopy(data, index, data, index+1, total-index);
		
		//(4) Put data [index] = value into the new element
		data[index] = value;
		
		//(5) The number of total + + valid elements increases
		total++;
	}
	
	//Returns all the actually stored elements
	public Object[] getAll(){
		//Return total
		return Arrays.copyOf(data, total);
	}
	
	//Delete the element at [index]
	public void remove(int index){
		/*
		 * (1)Check the rationality range of the index
		 * (2)Move the element and move [index+1] and the following elements forward
		 * (3)Set data[total-1]=null and let the garbage collector recycle as soon as possible
		 * (4)total elements reduced--
		 */
		
		//(1) Consider the rationality of subscript: check the rationality range of index
		checkIndex(index);
		
		//(2) Move the element and move [index+1] and the following elements forward
		/*
		 * Suppose total=8, data.length=10, index = 3
		 * Range of valid elements [0,7]
		 * Move: [4] - [3], [5] - [4], [6] - [5], [7] - [6]
		 * Moved 4: total-index-1
		 */
		System.arraycopy(data, index+1, data, index, total-index-1);
		
		//(3) Set data[total-1]=null and let the garbage collector recycle as soon as possible
		data[total-1] = null;
		
//		(4) total elements reduced--
		total--;
	}
	
	//Query the subscript of an element
	public int indexOf(Object obj){
		if(obj == null){
			for (int i = 0; i < total; i++) {
				if(data[i] == null){//Equivalent to if(data[i] == obj)
					return i;
				}
			}
		}else{
			for (int i = 0; i < data.length; i++) {
				if(obj.equals(data[i])){
					return i;
				}
			}
		}
		return -1;
	}
	
	//Delete an element in the array
	//If there are duplicates, only the first one will be deleted
	public void remove(Object obj){
		/*
		 * (1)First query the [index] of obj
		 * (2)If it exists, call remove(index) to delete it
		 */
		
		//(1) First query the [index] of obj
		int index = indexOf(obj);
		
		if(index != -1){
			remove(index);
		}
		//It doesn't exist. You can do nothing
		//If it does not exist, you can throw exceptions
		//throw new RuntimeException(obj + "does not exist");
	}
	
	public void set(Object old, Object value){
		/*
		 * (1)Query [index] of old
		 * (2)If it exists, set(index, value) is called
		 */
		
//		(1) Query [index] of old
		int index = indexOf(old);
		if(index!=-1){
			set(index, value);
		}
		
		//It doesn't exist. You can do nothing
	}
}

2. Unidirectional linked list

contain:

(1) Contains a Node type member variable first: used to record the address of the first Node

If the linked list is empty and there are no nodes, then first is null.

The feature of the last node is that its next is null

(2) A total is used internally to record the number of elements actually stored

(3) An internal class Node is used

private class Node{
    Object data;
    Node next;
}
public class SingleLinkedList {
	//There is no need for arrays or other complex structures. I just need to record the "head" node of the one-way linked list
	private Node first;//First records the address of the first node
	private int total;//Here I record total for the convenience of later processing. For example, when the user obtains the number of effective elements in the linked list, he does not need to present the number, but directly returns total, etc
	
	/*
	 * Internal class, because this type of Node node is useless elsewhere. It is only used in the one-way linked list to store and represent its Node relationship.
	 * Because I'm dealing with internal types here.
	 */
	private class Node{
		Object data;//Because data can be any type of Object, it is designed as Object
		Node next;//Because the address of the next node is recorded in next, the type is the node type
		//Here, data and next are not privatized. It is hoped that get/set is not required in the external class, but can be directly used by "node object. Data" and "node object. Next"
		Node(Object data, Node next){
			this.data = data;
			this.next = next;
		}
	}
	
	public void add(Object obj){
		/*
		 * (1)Wrap obj data into a Node object of Node type
		 * (2)Link the new node to the end of the current linked list
		 * ①The current new node is the first node
		 * How to determine whether it is the first if(first==null) indicates that there is no first if yet
		 * ②First find the last node and link the new node to its next
		 * How to determine whether it is the last if (a node. next == null) indicates that this node is the last
		 */
//		(1) Wrap obj data into a Node object of Node type
		//Here, the next value of the new node is null, indicating that the new node is the last node
		Node newNode = new Node(obj, null);
		
		//① The current new node is the first node
		if(first == null){
			//Description newNode is the first
			first = newNode;
		}else{
			//② First find the last node and link the new node to its next
			Node node = first;
			while(node.next != null){
				node = node.next;
			}
			//When exiting the loop, node points to the last node
			
			//Link the new node to its next
			node.next = newNode;
		}
		
		total++;
	}
	
	public int size(){
		return total;
	}
	
	public Object[] getAll(){
		//(1) Create an array with the length of total
		Object[] all = new Object[total];
		
		//(2) Take the data in each node of the one-way linked list and put it into the all array
		Node node = first;
		for (int i = 0; i < total; i++) {
//			all[i] = node. data;
			all[i] = node.data;
			//Then point to the next node
			node = node.next;
		}
		
		//(3) Return array
		return all;
	}
	
	public void remove(Object obj){
		if(obj == null){
			//(1) First consider whether it is the first one
			if(first!=null){//The linked list is not empty
				
				//The node to be deleted is exactly the first node
				if(first.data == null){
					//Let the first node point to its next node
					first = first.next;
					total--;
					return;
				}
				
				//The node to be deleted is not the first node
				Node node = first.next;//Second node
				Node last = first;
				while(node.next!=null){//The last one is not included here, because node.next==null does not enter the loop, and node.next==null is the last one
					if(node.data == null){
						last.next = node.next;
						total--;
						return;
					}
					last = node;
					node = node.next;
				}
				
				//Judge whether the last node is the node to be deleted
				if(node.data == null){
					//The last node to be deleted
					last.next = null;
					total--;
					return;
				}
			}
		}else{
			//(1) First consider whether it is the first one
			if(first!=null){//The linked list is not empty
				
				//The node to be deleted is exactly the first node
				if(obj.equals(first.data)){
					//Let the first node point to its next node
					first = first.next;
					total--;
					return;
				}
				
				//The node to be deleted is not the first node
				Node node = first.next;//Second node
				Node last = first;
				while(node.next!=null){//The last one is not included here, because node.next==null does not enter the loop, and node.next==null is the last one
					if(obj.equals(node.data)){
						last.next = node.next;
						total--;
						return;
					}
					last = node;
					node = node.next;
				}
				
				//Judge whether the last node is the node to be deleted
				if(obj.equals(node.data)){
					//The last node to be deleted
					last.next = null;
					total--;
					return;
				}
			}
		}
	}

	public int indexOf(Object obj){
		if(obj == null){
			Node node = first;
			for (int i = 0; i < total; i++) {
				if(node.data == null){
					return i;
				}
				node = node.next;
			}
		}else{
			Node node = first;
			for (int i = 0; i < total; i++) {
				if(obj.equals(node.data)){
					return i;
				}
				node = node.next;
			}
		}
		return -1;
	}
}

12.3 Collection

Because there are many types of collections, we call them collection frameworks.

The collection framework is divided into two families: Collection (a set of objects) and Map (a set of mapping relationships and a set of key value pairs)

12.3.1 Collection

A Collection represents a Collection of objects. It is the root interface of the Collection family.

Although some of them may be ordered, some may be disordered, some may be repeatable, and some cannot be repeated, they have common operation specifications, so the specifications of these operations are abstracted as the Collection interface.

Common methods:

(1) boolean add(Object obj): add a

(2) boolean addAll (Collection c): add multiple

(3) boolean remove(Object obj): deletes an object

(4) boolean removeAll(Collection c): delete multiple

(5) boolean contains(Object c): whether to include a

(6) boolean containsAll(Collection c): whether to include all

(7) boolean isEmpty(): is it empty

(8) int size(): get the number of elements

(9) void clear(): clear the collection

(10) Object[] toArray(): get all elements

(11) Iterator iterator(): gets the iterator object that traverses the current collection

(12) Retain all (collection c): find the intersection of the current set and the c set

12.3.2 traversal of Collection Series

1. Explicitly use Iterator iterators

Collection c = ....;

Iterator iter = c.iterator();
while(iter.hashNext()){
    Object obj = iter.next();
    //...
}

Methods of Iterator interface:

(1)boolean hasNext()

(2)Object next()

(3)void remove()

2,foreach

Collection c = ....;

for(Object  obj :  c){
    //...
}

What kind of collection (container) can be traversed using foreach?

(1) Array:

(2) The java.lang.Iterable interface is implemented

This interface has an abstract method: Iterator iterator()

Iterator is also an interface. Its implementation class is usually implemented with internal classes in collection (container) classes. And create its object in the method of iterator().

public class MyArrayList implements Iterable{
	//Why use Object? It's just that this container is used to hold objects, but I don't know what objects it is used to hold.
	private Object[] data;
	private int total;
	
	//Other codes are omitted

	@Override
	public Iterator iterator() {
		return new MyItr();
	}
	
	private class MyItr implements Iterator{
		private int cursor;//cursor

		@Override
		public boolean hasNext() {
			return cursor!=total;
		}

		@Override
		public Object next() {
			return data[cursor++];
		}
	}
}

Think: if you traverse an array, under what circumstances do you choose foreach and for loop?

When your operation involves [subscript] operation, it is best to use for.

When you just look at the content of the element, choose foreach to be more concise.

Thinking: if you traverse the Collection series, under what circumstances do you choose foreach, and can you choose the for loop?

First, consider using foreach. If the set also has index information, you can also operate through for. If there is no subscript information, do not use for. That is, if the physical structure of the set is array, you can use for. If the physical structure is chain, the operation efficiency of using subscript is very low.

Think: if you traverse the Collection series, under what circumstances do you choose foreach and Iterator?

If you just look at the elements of the collection, the code will be more concise using foreach.

However, if it involves operations such as deleting elements according to certain conditions while traversing the collection, choose Iterator.

12.4 List

12.4.1 List overview

List: is the sub interface of Collection.

A collection of List series: ordered and repeatable

Common collections of List series: ArrayList, Vector, LinkedList, Stack

12.4.2 API of list

Common methods:

(1) boolean add(Object obj): add a

(2) boolean addAll (Collection c): add multiple

(3) void add(int index, Object obj): add one at the specified location

(4) void addAll(int index, Collection c): add multiple

(5) boolean remove(Object obj): deletes an object

(6) Object remove(int index): deletes the element at the specified position and returns the element just deleted

(7) boolean removeAll(Collection c): delete multiple

(8) boolean contains(Object c): whether to include a

(9) boolean containsAll(Collection c): whether to include all

(10) boolean isEmpty(): is it empty

(11) int size(): get the number of elements

(12) void clear(): clear the collection

(13) Object[] toArray(): get all elements

(14) Iterator iterator(): gets the iterator object that traverses the current collection

(15) Retain all (collection c): find the intersection of the current set and the c set

(16) ListIterator listIterator(): get the iterator object that traverses the current collection. This iterator can traverse forward and backward

(17) ListIterator listIterator(int index): traverse forward or backward from the [index] position

(18) Object get(int index): returns the element at the index position

(19) List subList(int start, int end): intercept the sublist of the [start,end) part

12.4.3 ListIterator interface

Methods of Iterator interface:

(1)boolean hasNext()

(2)Object next()

(3)void remove()

ListIterator is a sub interface of Iterator: the following methods are added

(4)void add(Object obj)

(5)void set(Object obj)

(6)boolean hasPrevious()

(7)Object previous()

(8)int nextIndex()

(9)int previousIndex()

12.4.4 differences between list implementation classes

ArrayList,Vector,LinkedList,Stack

(1) ArrayList and Vector: both are dynamic arrays

Vector is the earliest version of dynamic array. It is thread safe. The default capacity expansion mechanism is 2 times. It supports the iterator Enumeration of the old version

ArrayList is a dynamic array added later. The thread is unsafe. The default capacity expansion mechanism is 1.5 times

(2) The difference between dynamic array and LinkedList

Dynamic array: the underlying physical structure is an array

Advantages: fast access according to [subscript]

Disadvantages: need to open up continuous storage space, and need to expand capacity, move elements and other operations

LinkedList: the underlying physical structure is a two-way linked list

Advantages: when adding or deleting elements, you do not need to move the elements, but only need to modify the reference relationship between the front and rear elements

Disadvantages: when we look for elements, we can only start from first or last

(3) Stack: stack

It is a subclass of Vector. It has several more methods than Vector and can show the characteristics of "first in, last out or last in, first out".

① Object peek(): access stack top element

② Object pop(): pop up stack top element

③ push(): push the element to the top of the stack

(4) LinkedList can be used as many data structures

Single linked list: just focus on next

Queue: first in first out, find the corresponding method

Double ended queue (joined by JDK1.6): both ends can go in and out. Find the corresponding method

Stack: first in, last out, find the corresponding method

Suggestion: Although LinkedList supports index operation because it implements all methods of the List interface, we do not recommend calling methods like this because of its low efficiency.

12.4.5 source code analysis

(1)Vector

    public Vector() {
        this(10);//Specify an initial capacity of 10
    }
	public Vector(int initialCapacity) {
        this(initialCapacity, 0);//Specify a capacityIncrement increment of 0
    }
    public Vector(int initialCapacity, int capacityIncrement Increment is 0) {
        super();
        //The validity of the formal parameter initial capacity initialCapacity is judged
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        //Created an array of type Object []
        this.elementData = new Object[initialCapacity];//The default is 10
        //Increment: the default is 0. If it is 0, it will be increased by 2 times later. If it is not 0, it will be increased by the specified increment later
        this.capacityIncrement = capacityIncrement;
    }
//synchronized means thread safe   
	public synchronized boolean add(E e) {
        modCount++;
    	//See if capacity expansion is needed
        ensureCapacityHelper(elementCount + 1);
    	//Store the new element in [elementCount]. After saving, the number of elementCount elements increases by 1
        elementData[elementCount++] = e;
        return true;
    }

    private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        //See if the capacity of the current array is exceeded
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);//Capacity expansion
    }
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;//Gets the length of the current array
        //If the capacity increment is 0, the new capacity = 2 times the oldCapacity
        //If the capacityIncrement increment is 0, the new capacity = oldCapacity + capacityIncrement increment;
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        
        //If the new capacity calculated above is not enough, expand the minCapacity according to the minimum capacity you specify
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        
        //If the new capacity exceeds the maximum array limit, it is processed separately
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        
        //Copy the data from the old array to the new array. The length of the new array is newCapacity
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
    public boolean remove(Object o) {
        return removeElement(o);
    }
    public synchronized boolean removeElement(Object obj) {
        modCount++;
        //Find the subscript of obj in the current Vector
        int i = indexOf(obj);
        //If I > = 0, it indicates that it exists. Delete the element at [i]
        if (i >= 0) {
            removeElementAt(i);
            return true;
        }
        return false;
    }
    public int indexOf(Object o) {
        return indexOf(o, 0);
    }
    public synchronized int indexOf(Object o, int index) {
        if (o == null) {//The element to find is a null value
            for (int i = index ; i < elementCount ; i++)
                if (elementData[i]==null)//If it is a null value, use = = null to judge
                    return i;
        } else {//The element to find is a non null value
            for (int i = index ; i < elementCount ; i++)
                if (o.equals(elementData[i]))//If it is a non null value, use equals to judge
                    return i;
        }
        return -1;
    }
    public synchronized void removeElementAt(int index) {
        modCount++;
        //Judge the legitimacy of subscript
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                     elementCount);
        }
        else if (index < 0) {
            throw new ArrayIndexOutOfBoundsException(index);
        }
        
        //j is the number of elements to be moved
        int j = elementCount - index - 1;
        //If the element needs to be moved, call System.arraycopy to move it
        if (j > 0) {
            //Move the index+1 position and the following elements forward
            //Move the element at the position of index+1 to the position of index, and so on
            //Move j in total
            System.arraycopy(elementData, index + 1, elementData, index, j);
        }
        //The total number of elements decreased
        elementCount--;
        //Empty the location of elementData[elementCount] to add new elements. The elements in the location are waiting to be recycled by GC
        elementData[elementCount] = null; /* to let gc do its work */
    }

(2) ArrayList source code analysis

JDK1.6:

    public ArrayList() {
		this(10);//Specify an initial capacity of 10
    }
    public ArrayList(int initialCapacity) {
		super();
        //Check the validity of the initial capacity
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        //The array is initialized to an array of length initialCapacity
		this.elementData = new Object[initialCapacity];
    }

JDK1.7

    private static final int DEFAULT_CAPACITY = 10;//Default initial capacity 10
	private static final Object[] EMPTY_ELEMENTDATA = {};
	public ArrayList() {
        super();
        this.elementData = EMPTY_ELEMENTDATA;//The array is initialized to an empty array
    }
    public boolean add(E e) {
        //Check whether the current array has enough more than one element
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == EMPTY_ELEMENTDATA) {//If the current array is still empty
            //minCapacity is processed according to the default initial capacity and the maximum value in minCapacity
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
		//See if capacity expansion is required
        ensureExplicitCapacity(minCapacity);
    }
	//...

JDK1.8

private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//Initialize to an empty array
    }
    public boolean add(E e) {
        //Check whether the current array has enough more than one element
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        
        //Save the new element to the [size] position, and then increase the size by 1
        elementData[size++] = e;
        return true;
    }
    private void ensureCapacityInternal(int minCapacity) {
        //If the current array is still empty
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            //Then minCapacity takes default_ Maximum value of capacity and minCapacity
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
		//Check whether capacity expansion is required
        ensureExplicitCapacity(minCapacity);
    }
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//Number of modifications plus 1

        // If the required minimum capacity is larger than the length of the current array, that is, the current array is not enough, expand the capacity
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;//Current array capacity
        int newCapacity = oldCapacity + (oldCapacity >> 1);//The capacity of the new array is 1.5 times that of the old array
        //See if 1.5 times the old array is enough
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        //See if the 1.5 times of the old array exceeds the maximum array limit
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        
        //Copy a new array
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
    public boolean remove(Object o) {
        //First find o the subscript in the array of the current ArrayList
        //Discuss whether o is blank or not
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {//null values are compared with = =
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {//Non null values are compared with equals
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }
    private void fastRemove(int index) {
        modCount++;//Number of modifications plus 1
        //Number of elements to be moved
        int numMoved = size - index - 1;
        
        //If you need to move elements, use System.arraycopy to move elements
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        
        //Empty the elementData[size-1] position to allow the GC to reclaim space and reduce the number of elements
        elementData[--size] = null; // clear to let GC do its work
    }
    public E remove(int index) {
        rangeCheck(index);//Check whether the index is legal

        modCount++;//Number of modifications plus 1
        
        //Take out the element at [index]. The element at [index] is the element to be deleted. It is used to return the deleted element finally
        E oldValue = elementData(index);
        
		//Number of elements to be moved
        int numMoved = size - index - 1;
        
        //If you need to move elements, use System.arraycopy to move elements
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        //Empty the elementData[size-1] position to allow the GC to reclaim space and reduce the number of elements
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }
    public E set(int index, E element) {
        rangeCheck(index);//Check whether the index is legal

        //Take out the element at [index]. The element at [index] is the element to be replaced, which is used to return the replaced element finally
        E oldValue = elementData(index);
        //Replace the element at [index] with element
        elementData[index] = element;
        return oldValue;
    }
    public E get(int index) {
        rangeCheck(index);//Check whether the index is legal

        return elementData(index);//Returns the element at the [index] position
    }
    public int indexOf(Object o) {
        //There are two cases: o is empty or not
        if (o == null) {
            //Look from front to back
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }
    public int lastIndexOf(Object o) {
         //There are two cases: o is empty or not
        if (o == null) {
            //Look from the back
            for (int i = size-1; i >= 0; i--)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = size-1; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

(3) LinkedList source code analysis

int size = 0;
Node<E> first;//Record the position of the first node
Node<E> last;//Record the position of the last node

    private static class Node<E> {
        E item;//Element data
        Node<E> next;//Next node
        Node<E> prev;//Previous node

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }
    public boolean add(E e) {
        linkLast(e);//By default, the new element is linked to the end of the linked list
        return true;
    }
    void linkLast(E e) {
        final Node<E> l = last;//Record the original last node with l
        
        //Create a new node
        final Node<E> newNode = new Node<>(l, e, null);
        //Now the new node is the last node
        last = newNode;
        
        //If l==null, the original linked list is empty
        if (l == null)
            //Then the new node is also the first node
            first = newNode;
        else
            //Otherwise, link the new node to the next of the original last node
            l.next = newNode;
        //Number of elements increased
        size++;
        //Increase in modification times
        modCount++;
    }
    public boolean remove(Object o) {
        //There are two cases: whether o is empty or not
        if (o == null) {
            //Find the node x corresponding to o
            for (Node<E> x = first; x != null; x = x.next) {
                if (x.item == null) {
                    unlink(x);//Delete x node
                    return true;
                }
            }
        } else {
            //Find the node x corresponding to o
            for (Node<E> x = first; x != null; x = x.next) {
                if (o.equals(x.item)) {
                    unlink(x);//Delete x node
                    return true;
                }
            }
        }
        return false;
    }
    E unlink(Node<E> x) {//x is the node to be deleted
        // assert x != null;
        final E element = x.item;//Data of deleted node
        final Node<E> next = x.next;//The next node of the deleted node
        final Node<E> prev = x.prev;//The previous node of the deleted node

        //If there is no node in front of the deleted node, the deleted node is the first node
        if (prev == null) {
            //Then the next node of the deleted node becomes the first node
            first = next;
        } else {//The deleted node is not the first node
            //The next of the previous node of the deleted node points to the next node of the deleted node
            prev.next = next;
            //Disconnect the link between the deleted node and the previous node
            x.prev = null;//Make GC recycle
        }

        //If there is no node after the deleted node, the deleted node is the last node
        if (next == null) {
            //Then the previous node of the deleted node becomes the last node
            last = prev;
        } else {//The deleted node is not the last node
            //The prev of the next node of the deleted node executes the previous node of the deleted node
            next.prev = prev;
            //Disconnect the deleted node from the next node
            x.next = null;//Make GC recycle
        }
		//The data of the deleted node is also set to be empty, so that GC can recycle
        x.item = null;
        //Decrease in the number of elements
        size--;
        //Increase in modification times
        modCount++;
        //Returns the data of the deleted node
        return element;
    }

12.5 Set

12.5.1 Set overview

Set of set series: non repeatable

Set series of sets, both ordered and disordered. HashSet is out of order. TreeSet traverses in the order of element size, and LinkedHashSet traverses in the order of element addition.

12.5.2 characteristics of implementation class

(1)HashSet:

The bottom layer is the HashMap implementation. The element added to the HashSet is the key of the HashMap, and value is a constant Object PRESENT of type Object.

The hashCode() and equals() that depend on the element ensure that the element is not repeated. The storage location is related to the hashCode() value. Calculate its [index] in the underlying table array according to the hashCode()

(2)TreeSet

The bottom layer is the TreeMap implementation. The element added to TreeSet is the key of TreeMap, and value is a constant Object PRESENT of Object type.

Depending on the size of the element, either the compareTo(Object obj) of the java.lang.Comparable interface or the compare(Object o1, Object o2) of the java.util.Comparator interface are used to compare the size of the element. Two elements of equal size are considered to be repeating elements.

(3)LinkedHashSet

The bottom layer is LinkedHashMap. The element added to the LinkedHashSet is the key of the LinkedHashMap, and value is a constant Object PRESENT of type Object.

LinkedHashSet is a subclass of HashSet, which maintains the addition order of elements more than the parent class.

Use it if and only if you want elements to be non repeatable and ensure the order in which they are added.

12.6 Map

12.6.1 Map overview

Used to store key value pairs, a collection of mapping relationships. All Map keys cannot be duplicate.

Type of key value pair and mapping relationship: Entry type

Entry Interface is Map Internal interface of the interface. be-all Map All types of key value pairs implement this interface.
HashMap There is an internal class to implement the mapping relationship in Entry The interface of, JDK1.7 It's a man called Entry Internal class implementation of Entry Interface.
JDK1.8 It's a man called Node Internal class implementation of Entry Interface.
TreeMap The mapping relationship in has an internal class Entry To achieve Entry Interface

12.6.2 API

(1) put(Object key, Object value): adds a pair of mapping relationships

(2) putAll(Map m): add a multi pair mapping relationship

(3) clear(): clear the map

(4) remove(Object key): deletes a pair according to the key

(5) int size(): get the logarithm of valid elements

(6) containsKey(Object key): whether to include a key

(7) containsValue(Object value): whether to include a value

(8) Object get(Object key): get value according to the key

(9) Several methods of traversal

Collection values(): get all values for traversal

Set keySet(): get all keys for traversal

Set entrySet(): get all mapping relationships for traversal

12.6.3 differences between map implementation classes

(1)HashMap:

Ensure whether the key is repeated according to the hashCode() and equals() of the key.

If the key is repeated, the new value will replace the old value.

hashCode() determines the storage location of the mapping relationship in the table array. Index = hash (key. hashCode()) & table.length-1

The underlying implementation of HashMap: JDK1.7 is array + linked list; JDK1.8 is array + linked list / red black tree

(2)TreeMap

Ensure whether the key is repeated according to the size of the key. If the key is repeated, the new value will replace the old value.

The size of the key depends on java.lang.Comparable or java.util.Comparator.

(3)LinkedHashMap

Ensure whether the key is repeated according to the hashCode() and equals() of the key. If the key is repeated, the new value will replace the old value.

LinkedHashMap is a subclass of HashMap and has more addition order than HashMap

12.6.4 HashMap source code analysis

JDK1.6 source code:

    public HashMap() {
        //this.loadFactor is a loading factor that affects the frequency of capacity expansion
        //DEFAULT_LOAD_FACTOR: the default loading factor is 0.75
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        //threshold = capacity * loading factor
        //Threshold. When the size reaches threshold, capacity expansion is considered
        //Two conditions must be met for capacity expansion: (1) size > = thread (2) table[index]= null, that is, the location to store the new mapping relationship is not empty
        threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
        //table is an array,
        //DEFAULT_ INITIAL_ Capability: 16 by default
        table = new Entry[DEFAULT_INITIAL_CAPACITY];
        init();
    }

JDK1.7 source code:

    public HashMap() {
    	//DEFAULT_ INITIAL_ Capability: default initial capacity 16
    	//DEFAULT_LOAD_FACTOR: the default loading factor is 0.75
        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
    }
    public HashMap(int initialCapacity, float loadFactor) {
        //Verify the validity of initialCapacity
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
        //Verify the validity of initialCapacity (initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        //Verify the legitimacy of loadFactor
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
		//Load factor, initialized to 0.75
        this.loadFactor = loadFactor;
        // threshold is the initial capacity                                  
        threshold = initialCapacity;
        init();
    }
public V put(K key, V value) {
        //If the table array is empty, create the array first
        if (table == EMPTY_TABLE) {
            //threshold is initially the value of the initial capacity
            inflateTable(threshold);
        }
        //If the key is null, handle it separately
        if (key == null)
            return putForNullKey(value);
        
        //Interfere with the hashCode of the key and calculate a hash value
        int hash = hash(key);
        
        //Calculate that the new mapping relationship should be saved to table[i],
        //i = hash & table.length-1, which can ensure that i is within the range of [0,table.length-1]
        int i = indexFor(hash, table.length);
        
        //Check whether the key under table[i] duplicates the key of my new mapping relationship. If so, replace value
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        //Add a new mapping relationship
        addEntry(hash, key, value, i);
        return null;
    }
    private void inflateTable(int toSize) {
        // Find a power of 2 >= toSize
        int capacity = roundUpToPowerOf2(toSize);//The capacity is equal to the nearest n-th power of 2 of the toSize value
		//Calculation threshold = capacity * loading factor
        threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
        //Create Entry [] array with length of capacity
        table = new Entry[capacity];
        initHashSeedAsNeeded(capacity);
    }
	//If the key is null, it is directly stored in the location of [0]
    private V putForNullKey(V value) {
        //Judge whether there are duplicate key s. If there are duplicates, replace value
        for (Entry<K,V> e = table[0]; e != null; e = e.next) {
            if (e.key == null) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }
        modCount++;
        //Store the new mapping relationship in [0], and the hash value of the key is represented by 0
        addEntry(0, null, value, 0);
        return null;
    }
    void addEntry(int hash, K key, V value, int bucketIndex) {
        //Determine whether storage capacity is required
        //Capacity expansion: (1) size reaches the threshold (2) table[i] is not empty
        if ((size >= threshold) && (null != table[bucketIndex])) {
            //The capacity of the table is doubled, and after the capacity expansion, the storage locations of all mapping relationships will be readjusted
            resize(2 * table.length);
            //The hash and index of the new mapping relationship will also be recalculated
            hash = (null != key) ? hash(key) : 0;
            bucketIndex = indexFor(hash, table.length);
        }
		//Save in table
        createEntry(hash, key, value, bucketIndex);
    }
    void createEntry(int hash, K key, V value, int bucketIndex) {
        Entry<K,V> e = table[bucketIndex];
        //The mapping relationship under the original table[i] is used as the new mapping relationship next
        table[bucketIndex] = new Entry<>(hash, key, value, e);
        size++;//Increase in number
    }

1,put(key,value)

(1) When the mapping relationship is added for the first time, the array is initialized to a * * HashMap with a length of 16 E n t r y ∗ ∗ of number group , this individual H a s h M a p An array of Entry * *, this HashMap The HashMapEntry type implements the java.util.Map.Entry interface

(2) Special consideration: if the key is null, the index is directly [0]

(3) Before calculating the index, the hashCode() value of the key will be hashed again, so that the Entry object can be more hashed and stored in the table

(4) Calculate index = table.length-1 & hash;

(5) If the key of the existing mapping relationship under table[index] is the same as the key of the new mapping relationship I want to add, the old value will be replaced with the new value.

(6) If not, the new mapping relationship will be added to the header of the linked list, and the Entry object under the original table[index] will be connected to the next of the new mapping relationship.

(7) Judge if (size > = threshold & & table [index]! = null) before adding. If the condition is true, the capacity will be expanded

​ if(size >= threshold && table[index]!=null){

① capacity expansion

② the hash of the key will be recalculated

③ the index will be recalculated

​ }

2,get(key)

(1) Calculate the hash value of the key. Use this method to hash(key)

(2) Find index = table.length-1 & hash;

(3) If table[index] is not empty, the key of each Entry will be compared one by one, and its value will be returned

3,remove(key)

(1) Calculate the hash value of the key. Use this method to hash(key)

(2) Find index = table.length-1 & hash;

(3) If the table[index] is not empty, compare which Entry has the same key one by one, delete it, and change the value of the next of the Entry in front of it to the next of the deleted Entry

JDK1.8 source code

Several constants and variables:
(1)DEFAULT_INITIAL_CAPACITY: Default initial capacity 16
(2)MAXIMUM_CAPACITY: Maximum capacity 1 << 30
(3)DEFAULT_LOAD_FACTOR: Default load factor 0.75
(4)TREEIFY_THRESHOLD: The default treelization threshold is 8. When the length of the linked list reaches this value, treelization should be considered
(5)UNTREEIFY_THRESHOLD: The default de tree threshold is 6. When the number of nodes in the tree reaches this threshold, it should be considered to become a linked list
(6)MIN_TREEIFY_CAPACITY: Minimum tree capacity 64
		When the number of nodes in a single linked list reaches 8, and table Only when the length reaches 64 can it be trealized.
		When the number of nodes in a single linked list reaches 8, but table If the length of does not reach 64, the capacity will be expanded first
(7)Node<K,V>[] table: array
(8)size: Record the logarithm of the effective mapping relationship, also Entry Number of objects
(9)int threshold: Threshold, when size Consider capacity expansion when the threshold is reached
(10)double loadFactor: The loading factor affects the frequency of capacity expansion
    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; 
        // All other fields are defaulted
    }
    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
	//Purpose: to interfere with hashCode value
    static final int hash(Object key) {
        int h;
		//If the key is null, the hash is 0
		//If the key is not null, use the hashCode value of the key to XOR with the hashCode value of the key higher than 16
		//		That is, the high 16 bits and low 16 bits of the hashCode value of the key are used for XOR interference operation
		
		/*
		index = hash & table.length-1
		If you use the original hashCode value of the key to perform bitwise sum with table.length-1, you basically have no chance to use high 16.
		This will increase the probability of conflict. In order to reduce the probability of conflict, the high 16 bits are added to the hash information.
		*/
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
        Node<K,V>[] tab; //array
		Node<K,V> p; //A node
		int n, i;//n is the length of the array and i is the subscript
		
		//tab and table are equivalent
		//If table is empty
        if ((tab = table) == null || (n = tab.length) == 0){
            n = (tab = resize()).length;
            /*
			tab = resize();
			n = tab.length;*/
			/*
			If the table is empty, resize() completes ① creating an array with a length of 16 ② threshold = 12
			n = 16
			*/
        }
		//I = (n - 1) & hash, subscript = array length - 1 & hash
		//p = tab[i] 1st node
		//if(p==null) condition is satisfied, it means that table[i] has no element
		if ((p = tab[i = (n - 1) & hash]) == null){
			//Put the new mapping relationship directly into table[i]
            tab[i] = newNode(hash, key, value, null);
			//The newNode () method creates a new Node of Node type, and the next of the new Node is null
        }else {
            Node<K,V> e; 
			K k;
			//p is the first node in table[i]
			//If (the first node of table [i] duplicates the key of the new mapping relationship)
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k)))){
                e = p;//Record the first node of this table[i] with e
			}else if (p instanceof TreeNode){//If the first node of table[i] is a tree node
                //Handle tree nodes separately
                //If there is a duplicate key in the tree node, return the duplicate node and receive it with E, that is, e= null
                //If there is no duplicate key in the tree node, put the new node into the tree and return null, that is, e=null
				e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            }else {
				//The first node of table[i] is not a tree node, nor does it duplicate the key of the new mapping relationship
				//binCount records the number of nodes under table[i]
                for (int binCount = 0; ; ++binCount) {
					//If the next node of P is empty, it means that the current p is the last node
                    if ((e = p.next) == null) {
						//Connect the new node to the end of table[i]
                        p.next = newNode(hash, key, value, null);
						
						//If bincount > = 8-1, when it reaches 7
                        if (binCount >= TREEIFY_THRESHOLD - 1){ // -1 for 1st
                            //Either expand or tree
							treeifyBin(tab, hash);
						}
                        break;
                    }
					//If the key is repeated, it will jump out of the for loop. At this time, node e records the node with the repeated key
            if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k)))){
                        break;
					}
                    p = e;//The next cycle, e=p.next, is similar to e=e.next, moving under the linked list
                }
            }
			//If this e is not null, it indicates that there is a duplicate key, so consider replacing the original value
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null){
                    e.value = value;
				}
                afterNodeAccess(e);//Nothing
                return oldValue;
            }
        }
        ++modCount;
		
		//Number of elements increased
		//size reached threshold
        if (++size > threshold){
            resize();//Once the capacity is expanded, readjust the position of all mapping relationships
		}
        afterNodeInsertion(evict);//Nothing
        return null;
    }	
	
   final Node<K,V>[] resize() {
        Node<K,V>[] oldTab = table;//oldTab original table
		//oldCap: the length of the original array
        int oldCap = (oldTab == null) ? 0 : oldTab.length;
		
		//oldThr: original threshold
        int oldThr = threshold;//The initial threshold is 0
		
		//newCap, new capacity
		//newThr: new threshold
        int newCap, newThr = 0;
        if (oldCap > 0) {//Description: the original array is not empty
            if (oldCap >= MAXIMUM_CAPACITY) {//Whether the maximum limit of the array has been reached
                threshold = Integer.MAX_VALUE;
                return oldTab;
            }else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                     oldCap >= DEFAULT_INITIAL_CAPACITY){
				//newCap = old capacity * 2, new capacity < maximum array capacity limit
				//New capacity: 32,64
				//Oldcap > = initial capacity 16
				//New threshold recalculation = 24, 48
                newThr = oldThr << 1; // double threshold
			}
        }else if (oldThr > 0){ // initial capacity was placed in threshold
            newCap = oldThr;
        }else {               // zero initial threshold signifies using defaults
            newCap = DEFAULT_INITIAL_CAPACITY;//The new capacity is the default initialization capacity of 16
			//New threshold = default load factor * default initialization capacity = 0.75 * 16 = 12
            newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
        }
        if (newThr == 0) {
            float ft = (float)newCap * loadFactor;
            newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
                      (int)ft : Integer.MAX_VALUE);
        }
        threshold = newThr;//The threshold value is assigned to the new threshold value 12, 24...
		
		//A new array is created with a length of newCap, 16, 32, 64..
        @SuppressWarnings({"rawtypes","unchecked"})
            Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
        table = newTab;
		
		
        if (oldTab != null) {//It is not an empty array
			//Invert the mapping relationship from the original table to the new table
            for (int j = 0; j < oldCap; ++j) {
                Node<K,V> e;
                if ((e = oldTab[j]) != null) {//e is the node under the table
                    oldTab[j] = null;//Empty the old table[j] position
                    if (e.next == null)//If it is the last node
                        newTab[e.hash & (newCap - 1)] = e;//Recalculate the storage location of e in the new table and put it into
                    else if (e instanceof TreeNode)//If e is a tree node
						//Disassemble the original tree and put it into a new table
                        ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
                    else { // preserve order
                        Node<K,V> loHead = null, loTail = null;
                        Node<K,V> hiHead = null, hiTail = null;
                        Node<K,V> next;
						/*
						Move the entire linked list under the original table[i] to the new table
						*/
                        do {
                            next = e.next;
                            if ((e.hash & oldCap) == 0) {
                                if (loTail == null)
                                    loHead = e;
                                else
                                    loTail.next = e;
                                loTail = e;
                            }
                            else {
                                if (hiTail == null)
                                    hiHead = e;
                                else
                                    hiTail.next = e;
                                hiTail = e;
                            }
                        } while ((e = next) != null);
                        if (loTail != null) {
                            loTail.next = null;
                            newTab[j] = loHead;
                        }
                        if (hiTail != null) {
                            hiTail.next = null;
                            newTab[j + oldCap] = hiHead;
                        }
                    }
                }
            }
        }
        return newTab;
    }	
	
    Node<K,V> newNode(int hash, K key, V value, Node<K,V> next) {
		//Create a new node
	   return new Node<>(hash, key, value, next);
    }

    final void treeifyBin(Node<K,V>[] tab, int hash) {
        int n, index; 
		Node<K,V> e;
		//MIN_ TREEIFY_ Capability: minimum tree capacity 64
		//If the table is empty, or the length of the table does not reach 64
        if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
            resize();//Capacity expansion first
        else if ((e = tab[index = (n - 1) & hash]) != null) {
			//Use e to record the address of the node of table[index]
            TreeNode<K,V> hd = null, tl = null;
			/*
			do...while,Change the Node node of the table[index] linked list into a TreeNode type Node
			*/
            do {
                TreeNode<K,V> p = replacementTreeNode(e, null);
                if (tl == null)
                    hd = p;//hd record root node
                else {
                    p.prev = tl;
                    tl.next = p;
                }
                tl = p;
            } while ((e = e.next) != null);
			
            //If the table[index] is not empty
            if ((tab[index] = hd) != null)
                hd.treeify(tab);//Tree the linked list under table[index]
        }
    }	

1. Add process

(1) When the mapping relationship is added for the first time, the array is initialized to a * * HashMap with a length of 16 N o d e ∗ ∗ of number group , this individual H a s h M a p Array of Node * *, this HashMap The HashMapNode type implements the java.util.Map.Entry interface

(2) Before calculating the index, the hashCode() value of the key will be hashed again, so that the Entry object can be more hashed and stored in the table

The implementation of hash(key) method in JDK 1.8 is simpler than that in JDK 1.7. key.hashCode() ^ key.Code()>>>16;

(3) Calculate index = table.length-1 & hash;

(4) If the key of the existing mapping relationship under table[index] is the same as the key of the new mapping relationship I want to add, the old value will be replaced with the new value.

(5) If you don't have the same,

① table[index] if the length of the linked list does not reach 8, the new mapping relationship will be added to the end of the linked list

② table[index] the length of the linked list reaches 8, but the table.length does not reach 64. The capacity of the table will be expanded first and then added

③ table[index] when the length of the linked list reaches 8 and the table.length reaches 64, the branch will be treed first, the node type will be changed to TreeNode, and then the linked list will be transformed into a red black tree

④ table[index] is already a red black tree. If you connect directly to the tree, you may also consider left-hand and right-hand rotation to ensure the balance of the tree

(6) Judge if after adding (size > threshold){

① capacity expansion

② the hash of the key will be recalculated

③ the index will be recalculated

​ }

2,remove(key)

(1) Calculate the hash value of the key. Use this method to hash(key)

(2) Find index = table.length-1 & hash;

(3) If the table[index] is not empty, compare which Entry has the same key one by one, delete it, and change the value of the next of the Entry in front of it to the next of the deleted Entry

(4) If there is a red black tree under the table[index], and the number of nodes is less than or equal to 6 after deletion, the red black tree will be changed into a linked list

12.6.5 interview questions about HashMap

1. The underlying implementation of HashMap

A: JDK1.7 is array + linked list, and JDK1.8 is array + linked list / red black tree

2. Element type of the array of HashMap

Answer: java.util.Map$Entry interface type.

The HashMap of JDK1.7 has an internal class Entry to implement the Entry interface

In the HashMap of JDK1.8, there are internal classes Node and TreeNode to implement the Entry interface

3. Why use arrays?

A: because the access efficiency of array is high

4. Why do arrays need linked lists? Or how to solve hash or [index] conflicts?

A: to resolve the hash and [index] conflicts

(1) The hashCode values of two different key s may themselves be the same

(2) For two keys with different hashcodes, the [index] obtained by hash(key) and hash & table.length-1 operation may be the same

This means that the mapping relationship objects of multiple entries may need to be stored under table[index], so a linked list is required

5. Initialization length of HashMap array

A: the default initial capacity value is 16

6. How to calculate the storage index of the mapping relationship of HashMap

Answer: hash & table.length-1

7. Why use hashCode()? Space for time

A: because hashCode() is an integer value, it can be used to directly calculate index, which is more efficient. Although using array structure will waste some space, it can improve query efficiency.

8. What is the function of hash()

A: before calculating the index, the hashCode() value of the key will be hashed again. This can make the Entry object more hashed and stored in the table

The implementation of the hash(key) method in JDK1.8 is simpler than that in JDK1.7. Key. hashCode() ^ key. Code() > > > 16; this allows the upper 16 bits of hashCode to participate in the operation

9. Why must the array length of HashMap be to the power of 2

A: because the binary value of the nth power - 1 of 2 is 0 in the front and 1 in the back. In this way, the result of & operation with hash can be guaranteed to be within the range of [0,table.length-1] and uniform.

10. Why does HashMap use & bitwise and instead of% modulo?

Answer: because & efficiency is high

11. When will the HashMap array be expanded?

A: JDK1.7: when adding a new Entry object, it is found that (1) when the size reaches threshold (2) table[index]!=null, the capacity will be expanded if the two conditions are met at the same time

JDK1.8: when adding a new Entry object, it is found that (1) the size reaches the threshold (2) when the number of nodes under table[index] reaches 8, but the table.length does not reach 64. Meeting either of the two conditions will lead to array expansion

Moreover, once the array is expanded, no matter which version, it will cause all mapping relationships to readjust the storage location.

12. How to calculate the capacity expansion threshold (critical value)?

A: threshold = capacity * loadactor

13. Why is loadFactor 0.75? If it is 1 or 0.1, what is the difference?

Answer: 1. The number of nodes under a table[index] may be very long

0.1 will cause the frequency of array expansion to be too high

14. When will the HashMap of JDK1.8 be treed?

A: when the number of nodes under table[index] reaches 8, but the table.length has reached 64

15. When will the HashMap of JDK1.8 be de treed?

A: when the number of tree nodes under table[index] is less than 6

16. Why should the HashMap of JDK1.8 be treelized?

A: because when the number of nodes under table[index] exceeds 8, the query efficiency is low. If it is modified to red black tree, the query efficiency can be improved

17. Why should the HashMap of JDK1.8 be de treed?

A: because when the number of nodes in the tree under table[index] is less than 6, the use of red black tree is too complex. At this time, the use of linked list is simple and efficient

18. What are the requirements for overriding the equals and hashCode methods as the key type of HashMap

(1) equals and hashCode are rewritten together

(2) Rewrite the equals() method, but there are some precautions;

  • Reflexivity: x.equals(x) must return true.
    Symmetry: the return values of x.equals(y) and y.equals(x) must be equal.
    Transitivity: if x.equals(y) is true and y.equals(z) is also true, then x.equals(z) must be true.
    Consistency: if the information used by objects x and Y in equals() does not change, the x.equals(y) value remains unchanged.
    Non null: if x is not null and Y is null, x.equals(y) must be false.

(3) precautions for rewriting hashCode()

  • If equals returns two objects that are true, the hashCode value must be the same, and the hashCode value cannot be modified as long as the attributes participating in equals judgment are not modified;
    If equals returns two objects that are false, the hashCode value can be the same or different;
    If the hashCode values are different, equals must return false;
    hashCode should not be too simple, too simple will lead to serious conflicts, and hashCode should not be too complex, which will lead to low performance;

19. Why do most hashcode methods use 31?

A: because 31 is a prime number

20. Can I modify the object attribute of the key stored in the HashMap? Why?

A: if this attribute is involved in hashCode calculation, do not modify it. Because once the hashCode() is modified, it is no longer the original value.
When stored in the HashMap, the hashCode() – > hash () – > hash of the key has been determined and will not be recalculated. When you query get(key) / remove(key) with the new hashCode value, the calculated hash value is different from the original, so the original mapping relationship cannot be found.

21. Why, in our actual development, the type of key is generally String and Integer

A: because they are immutable.

22. Why do hash variables and key variables of Node or Entry type in HashMap add final declaration?

A: because I don't want you to modify the hash and key values

23. Why should Node or Entry types in HashMap store hash separately?

A: in order to improve the efficiency of hash comparison in the process of adding, deleting and searching, it is not necessary to recalculate the hash value of the key every time

24. Can the object attribute of value stored in HashMap be modified? Why?

A: Yes. Because we store, delete, etc. according to the key, which has nothing to do with value.

25. If the key is null, how is it stored?

A: it will exist in table[0]

12.7 assembly frame diagram

[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-yk3tgV0j-1631456884028)(imgs/1560348912361.png)]

Chapter 13 generics

13.1 overview of generics

Generics: parameterized types

Type parameter:,,,,,....

Type argument: must be a reference data type, not a basic data type

​ ,,,<ArrayList>. . .

13.2 form 1: generic class and generic interface

1. Declaration syntax format:

[Modifier] class Class name/Interface<Type parameter list>{
    
}

[Modifier] class Class name/Interface<Type parameter 1 extends Upper limit of parent class>{
    
}
[Modifier] class Class name/Interface<Type parameter 1 extends Upper limit of parent class & Parent interface upper limit>{
    
}

Generic parameter types declared after the class name or interface name can be used in the current class or interface to declare member variables, formal parameters of methods, and return values of methods.

However, it cannot be used on static members

2. Use syntax format

(1) specify specific types for generic parameters when creating objects of generic classes and generic interfaces

(2) specify specific types for generic parameters when inheriting generic classes or implementing generic interfaces

Sample code

ArrayList<String> list = new ArrayList<String>();

ArrayList<String> list = new ArrayList<>();//It can be omitted after JDK1.7

class MyStringArrayList extends ArrayList<String>{
    
}

class Employee implements Comparable<Employee>{
    public int compareTo(Employee e){
        
    }
}

Arrays.sort(array,  new  Comparator<Generic argument>(){
    public int compare(Generic argument type  o1, Generic argument type  o2){
        
    }
});

3. If a generic type is not specified, it will be erased and processed according to the leftmost upper limit. If no upper limit is specified, it will be processed according to Object

13.3 form 2: generic method

1. Syntax format of the declaration

[Modifier] <Generic parameter list>  Return value type method name([[data parameter list])[throws [exception list]{}
[Modifier] <Generic parameter extends Upper limit of parent class & Parent interface upper limit>  Return value type method name([[data parameter list])[throws [exception list]{}

(1) The generic parameter type declared before the method return value type can only be used in the current method. It is used to represent the type of parameter or return value type, or the type of method local variable, which has nothing to do with other methods.

(2) Generic methods can be static or non static

2. Use

When a method is called, the type of the generic argument will be determined according to the type of the argument of the specific data.

13.4 wildcard?

(1)?: Represents any reference data type

(2)? Extensions upper limit: represents the upper limit itself or its subclasses

(3)? super lower limit: represents the lower limit itself or its parent class

For example:

ArrayList<?>: Indicates that any type is acceptable

ArrayList<?> list = new ArrayList<String>();
ArrayList<?> list = new ArrayList<Integer>();
ArrayList<?> list = new ArrayList<Animal>();

ArrayList<? Extensions upper limit >:

ArrayList<? extends Person> list = new ArrayList<Person>();
ArrayList<? extends Person> list = new ArrayList<Animal>();//Animal can't, because animal is the parent class
ArrayList<? extends Person> list = new ArrayList<Student>();
ArrayList<? extends Person> list = new ArrayList<Dog>();//Neither can Dog

ArrayList<? Super lower limit >:

ArrayList<? super Person> list = new ArrayList<Person>();
ArrayList<? super Person> list = new ArrayList<Animal>();
ArrayList<? super Person> list = new ArrayList<Student>();//Student, because student is a subclass
ArrayList<? super Person> list = new ArrayList<Dog>();//Neither can Dog

ArrayList<?>: Cannot add element except null

ArrayList<? Extensions upper limit >: cannot add elements except null

ArrayList<? Super lower limit >: you can add objects of lower limit or lower limit subclass

13.5 Collections tool class

java.util.Collections: tool class, operation collection

(1)public static boolean addAll(Collection<? super T> c, T... elements)

Add several objects of elements to the c Collection. T is the type of elements object. It is required that the element type of Collection collection must be t or the parent class of T

(2)public static int binarySearch(List<? extends Comparable<? super T>> list,T key)

In the list set, use bisection to find the subscript of key. If there is a reasonable subscript, if there is no subscript, it returns a negative subscript

T is the type of element,

<? extends Comparable<? Super T > >, it is required that the elements of the collection must implement the comparable interface <? Super T >, when implementing the comparable interface, you can specify the comparable < type argument > as the parent class of T or t. (3)public static boolean disjoint(Collection<?> c1, Collection<?> c2)

It is true if c1 and c2 do not intersect

(4)public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)

Find the largest element in the coll set

<T extends Object & Comparable<? Super T > >: the parent class of T or T is required to implement the compatible interface

Because you need to compare the size to find the maximum value

(5)public static <T extends Comparable<? Super T > > void sort (list) sorts the list set

<T extends Comparable<? Super T > >: the parent class of T or T is required to implement the compatible interface

(6)public static Collection synchronizedCollection(Collection c)

The method starting with synchronizedXX indicates that a non thread safe collection is transformed into a thread safe collection.

(7)public static List unmodifiableList(List<? extends T> list)

Methods that begin with unmodifiableXx return a "read-only" collection.

Chapter 14 IO flow

14.1 java.io.File class

It is an abstract description of file and directory pathnames.

API:

(1) getName(): get the name of the file or directory

(2) getPath(): get the path of the file or directory

(3) getAbsolutePath(): get the absolute path of the file or directory

(4) getCanonicalPath(): get the canonical path of the file or directory

(5) long length(): gets the length of the file, in bytes

(6) long lastModified(): last modified time, in milliseconds

(7) String getParent(): get parent directory or parent directory

File getParentFile(): get parent directory or parent directory

(8) isFile(): judge whether it is a file. If and only if it is a file and exists, it will be true

(9) isDirectory(): judge whether it is a directory. If and only if it is a directory and exists, it will be true

(10) exists(): does it exist

(11) isHidden(): hide

(12) canWrite(): whether it is writable

(13) canRead(): is it readable

(14) String[] list(): get the next level

File[] listFiles(): get the next level

File[] listFiles(FileFilter f): get the next level, but filter out the files and directories

(15) createNewFile(): creates a file

​ createTempFile(String prefix, String suffix)

(16) mkdir(): create a level-1 directory. If the parent directory does not exist, it will fail, but no exception will be reported

mkdirs(): create multi-level directory

(17) delete(): deletes a file or an empty directory

(18) Rename to (file f): renames a file or directory

14.2 four abstract base classes of IO streams

1. Four super classes

(1) InputStream: byte input stream

(2) OutputStream: byte output stream

(3) Reader: character input stream

(4) Writer: character output stream

2. Classification

(1) According to the direction: input flow and output flow

(2) It is handled differently: byte stream and character stream

Character streams can only handle plain text data (very narrow range of use)

(3) By role: node flow and processing flow

Processing flow is based on node flow. Processing flow needs to wrap an object of node flow.

A process flow can also wrap another process flow.

In fact, the IO system in JDK uses a decorator design pattern

3,API

(1)InputStream:

int read(): reads one byte at a time and returns the value of the byte read this time. If - 1 is returned at the end of the stream

int read(byte[] data): multiple bytes are read at a time. The read data is stored in the data byte array. data.length bytes are read at most. The number of bytes actually read this time is returned. If - 1 is returned at the end of the stream. Start storage from data[0].

int read(byte[] data,int offset, int len): read multiple bytes at a time. The read data is stored in the data byte array. The maximum number of bytes read is len. The number of bytes actually read this time is returned. If - 1 is returned at the end of the stream. Start storage from data[offset].

void close(): close

(2)OutputStream:

void write(int data): write one byte at a time

void write(byte[] data): write the entire byte array at a time

void write(byte[] data, int offset, int len): part of a byte array at a time, starting from [offset], a total of len

void close(): close

void flush(): refresh

(3)Reader:

int read(): read one character at a time and return the Unicode value of the character read this time. If - 1 is returned at the end of the stream

int read(char[] data): multiple characters are read at a time. The read data is stored in the data character array. The maximum number of characters read is data.length. It returns the number of characters actually read this time. If - 1 is returned at the end of the stream. Start storage from data[0].

int read(char[] data,int offset, int len): multiple characters are read at a time. The read data is stored in the data character array. The maximum number of characters read is len. The number of characters actually read this time is returned. If - 1 is returned at the end of the stream. Start storage from data[offset].

void close(): close

(4)Writer

void write(int data): write one character at a time

void write(char[] data): write the entire character array at one time

void write(char[] data, int offset, int len): part of a character array at a time, starting from [offset], with a total of len characters

void write(String str): write the entire string at a time

void write(String str, int offset, int count): write a part of a string at a time, starting from [offset], with a total of count

void close(): close

void flush(): refresh

14.3 file IO stream

1. Type

FileInputStream: File byte input stream, which can read any type of file

FileOutputStream: File byte output stream, which can output byte data to any type of file

FileReader: file character input stream. Only plain text files can be read. Decode according to the default character encoding of the platform.

FileWriter: file character output stream, which can only output character data to plain text files. Code according to the default character code of the platform.

2. Code for reading and writing files

Example code:

public void copy(File src, File dest)throws IOException{
    //Select IO stream
    FileInputStream fis = new FileInputStream(src);
    FileOutputStream fos = new FileOutputStream(dest);
    
    //Reading and writing
    byte[] data = new byte[1024];
    while(true){
        int len = fis.read(data);
        if(len==-1){
            break;
        }
        fos.write(data,0,len);
    }
    
    //close
     fis.close();
    fos.close();
}

14.4 buffered IO stream

1. Divided into

BufferedInputStream: byte input buffer stream, which adds buffer effect to InputStream series IO streams
BufferedOutputStream: byte output buffer stream, which adds buffer effect to OutputStream series IO streams
BufferedReader: character input buffer stream, adding buffer effect to Reader series IO stream

String readLine(): read by line

BufferedWriter: character output buffer stream, which adds buffer effect to the Writer series IO stream

void newLine(): output newline character

2. The default buffer size is 8192 = 1024 * 8 (bytes / character)

3. It can improve the efficiency of the reading and writing process

The buffer effect can be added not only to the file IO stream, but also to any IO stream conforming to the corresponding type.

Example code:

	public void copyBuffer(File src, File dest)throws IOException{
	    //Select IO stream
	    FileInputStream fis = new FileInputStream(src);
	    FileOutputStream fos = new FileOutputStream(dest);
	    
	    //BufferedInputStream can only add buffering effect to FileInputStream, and the reading process is accelerated
	    BufferedInputStream bis = new BufferedInputStream(fis);//fis is inside, bis is outside, fis is compared to underwear and bis is compared to coat
	    
	    //BufferedOutputStream can only increase the buffering effect of FileOutputStream, and the writing process is accelerated
	    BufferedOutputStream bos = new BufferedOutputStream(fos);
	    
	    //Data flow direction: SRC -- > fis -- > bis (buffering from fis to BIS) - > data -- > bos (buffering from data to bos) - > FOS -- > dest
	    
	    //Reading and writing
	    byte[] data = new byte[1024];
	    while(true){
	        int len = bis.read(data);
	        if(len==-1){
	            break;
	        }
	        bos.write(data,0,len);
	    }
	    
	    //close
	    //Closing is likened to taking off your clothes
	    bos.close();
        fos.close();
        
	    bis.close();//Take off your coat first, then your underwear
	    fis.close();	    
	}

14.5 encoded and decoded IO stream (converted stream)

1. Encoding: OutputStreamWriter

Characters can be transferred to byte stream output, and character encoding can be specified in the process of conversion.

2. Decoding: InputStreamReader

Byte input can be transferred to character input stream, and character encoding can be specified during conversion.

3. Example code: decoding (the file is GBK and the current platform is UTF-8)

	@Test
	public void test4()throws IOException{
		//This is because you want to use the "specified" encoding method for decoding in the program, rather than the "default" encoding method of the platform
		//Therefore, I still use FileInputStream byte stream to read the encoded data of the file as it is
		//During the process of transferring files to FileInputStream fis memory, no decoding is performed first
		//Because if FileReader is selected, the process from file to FileReader has been decoded according to the "default" encoding method of the platform, which is beyond our control
		
		FileInputStream fis = new FileInputStream("d:/File Class overview.txt");
		//I want to use InputStreamReader to convert FileInputStream to character stream
//		InputStreamReader isr = new InputStreamReader(fis);// If it is not specified, the default encoding method is used
		InputStreamReader isr = new InputStreamReader(fis,"GBK");//If specified, it is decoded according to the specified encoding method
		
		//File -- > FIS (byte stream) - > decoding -- > ISR (character stream) - > Br - > reading characters
		//The character stream can be read either by char [] or by line wrapped in BufferedReader
		BufferedReader br = new BufferedReader(isr);
		String line;
		while((line = br.readLine()) !=null){
			System.out.println(line);
		}
		
		br.close();
		isr.close();
		fis.close();
	}

4. Example code: encoding (the file is GBK and the current platform is UTF-8)

	@Test
	public void test3()throws IOException{
		String hua = "File Class can be created using a file path string File example";
		
		//Because you want to encode in the program, you choose FileOutputStream here
		FileOutputStream fos = new FileOutputStream("d:/File Class overview.txt",true);
		
		//Here xx, if you want to directly manipulate a string, it must be a character stream, while fos is a byte stream. You cannot directly manipulate a string
//		xx.write("\r\n");
//		xx.write(hua);
		
		//Data flow: memory -- > OSW (character stream) - > encoding during writing to fos -- > fos (byte stream) - > file
		
		OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");
		osw.write("\r\n");
		osw.write(hua);
		
		osw.close();
		fos.close();
	}

14.6 data IO flow

1. Type

DataInputStream: allows applications to read basic Java data types from the underlying input stream in a machine independent manner.
DataOutputStream: allows applications to write basic Java data types to the output stream in an appropriate manner.

They must be paired

Read in the same order as write

2,API

DataOutputStreamDataInputStream
writeInt(xx): output int type integerint readInt()
writeDouble(xx): output double typedouble readDouble()
writeBoolean(xx)boolean readBoolean()
writeLong(xx)long readLong()
writeChar(xx)char readChar()
writeByte(xx)byte readByte()
writeShort(xx)short readShort()
writeFloat(xx)float readFloat()
writeUTF(String str): the of the output stringString readUTF()

14.7 object IO flow

1. Type

ObjectOutputStream: serialize objects, output objects, and convert objects into byte sequences for output

ObjectInputStream: deserialize objects, read objects, and reconstruct byte sequences into Java objects

2,API

ObjectOutputStream: writeobject

ObjectInputStream: Object readObject()

3. What should I pay attention to in serialization?

(1) The types of all objects to be serialized must implement the java.io.Serializable interface

If the attribute type of an object is also a reference data type, the java.io.Serializable interface should also be implemented

(2) We hope that the modified object deserialization of the class will not have an impact, so we can finally add a serialized version ID

private static final long serialVersionUID = 1L;

(3) If some attributes do not want to be serialized, you can add transient

(4) If a property is preceded by a static modifier, it does not participate in serialization

4. In addition to the Serializable interface, you can also implement the java.io.Externalizable interface, but you need to rewrite:

void readExternal(ObjectInput in)
void writeExternal(ObjectOutput out)

It is up to the programmer to decide which attributes to serialize and deserialize.

14.8 other IO flow related contents

1. If you want to read by row, what type can you choose?

BufferedReader: String readLine()

Scanner: String nextLine()

2. If you want to output by line, what type can you choose?

(1) Handle it yourself \ r\n

(2)BufferedWriter: newLine()

(3) PrintStream and PrintWriter: println()

14.9 new try... catch introduced after jdk1.7

Syntax format:

try(Declaration of the resource object that needs to be closed){
    Business logic code
}catch(Exception type e){
    Handling exception codes
}catch(Exception type e){
    Handling exception codes
}
....

It is not finally, nor does it require programmers to close the resource object. The resource object will be closed whether an exception occurs or not

Example code:

	@Test
	public void test03() {
		//Read the contents from the d:/1.txt(GBK) file and write them to the 1.txt(UTF-8) file under the project root directory
		try(
			FileInputStream fis = new FileInputStream("d:/1.txt");
			InputStreamReader isr = new InputStreamReader(fis,"GBK");
			BufferedReader br = new BufferedReader(isr);
			
			FileOutputStream fos = new FileOutputStream("1.txt");
			OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");
			BufferedWriter bw = new BufferedWriter(osw);
		){
			String str;
			while((str = br.readLine()) != null){
				bw.write(str);
				bw.newLine();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

Chapter 15 network programming (understanding)

Learn it in order to better understand the principles of web (communication between server and client), database (data transmission between server and client), etc.

15.1 host IP

In the program, it means:

(1) Representation of values

IPV4: 32-bit integer, 8-bit group, split with. For example: 192.168.11.45

Each 8-bit range [0255]

IPV6: 128 bit integer, 16 bit group, split by: for example, X:X:X:X:X:X:X:X: X

Each 16 bit is represented by a hexadecimal value

(2) Object representation: InetAddress

This class represents an Internet Protocol (IP) address. It has two subclasses Inet4Address and Inet6Address, corresponding to IPV4 and IPV6 respectively. The InetAddress class does not provide a public constructor, but provides the following static methods to obtain the InetAddress instance.

  • public static InetAddress getLocalHost()
  • public static InetAddress getByAddress(byte[] addr)
  • public static InetAddress getByName(String host)

InetAddress provides the following common methods:

  • public String getHostAddress(): returns the IP address string (expressed in text).
  • public String getHostName(): get the host name of this IP address
  • public String getCanonicalHostName(): get the fully qualified domain name of this IP address
  • public boolean isReachable(int timeout): test whether the address can be reached.

15.2 port number

Scope: [065535]

Common port numbers:

​ tomcat/JBoss: 8080

​ http: 80

​ mysql: 3306

​ oracle: 1521

​ sql server: 1433

15.3 network protocol

[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-nXLCMWXv-1631456884035)(imgs/1560731383474.png)]

  • Application layer: an interface between network services and end users. Protocols include: HTTP, FTP, SMTP, DNS, TELNET, HTTPS, POP3, etc.
  • Presentation layer: presentation, security and compression of data. Formats include JPEG, ASCll, DECOIC, encryption format, etc.
  • Session layer: establish, manage and terminate sessions. The corresponding host process refers to the ongoing session between the local host and the remote host
  • Transport layer: define the protocol port number of data transmission, as well as flow control and error verification. The protocols are TCP and UDP.
  • Network layer: logical address addressing to realize path selection between different networks. Protocols include ICMP, IGMP, IP (IPv4, IPv6), ARP and RARP.
  • Data link layer: establish logical connection, hardware address addressing, error checking and other functions. The bits are combined into bytes and then into frames, and the medium is accessed with MAC address. The error is found but cannot be corrected.
  • Physical layer: establish, maintain and disconnect physical connections.

IP protocol is a very important protocol. IP (Internet Protocol) is also called Internet protocol. The responsibility of IP is to transfer data from the source to the destination. It transmits something called data packet between the source address and the destination address. It also provides the function of reassembling the data size to meet the requirements of different networks for packet size. TCP (Transmission Control Protocol), which is a connection oriented, reliable and byte stream based transport layer communication protocol, is often put together with IP protocol. The TCP/IP protocol we usually talk about actually refers to the TCP/IP protocol family. Because the two core protocols of the protocol family: TCP (Transmission Control Protocol) and IP (Internet Protocol) are the earliest standards passed in the family, they are referred to as TCP/IP protocol for short.

TCP: Transmission Control Protocol
(1) Connection oriented: there are three handshakes before connection and four waves when disconnection
(2) Reliable
(3) Based on byte stream
(4) Capable of transmitting large amounts of data
UDP: User Datagram Protocol
(1) Non connection oriented
(2) Unreliable
(3) Datagram based
(4) 64K with limited data size

15.4 Socket programming

Socket: socket, which represents the end of network communication and is responsible for communicating with the network card driver.

[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-SJs7nwfU-1631456884041)(imgs/1560731601718.png)]

Divided into:
(1) Stream Socket: ServerSocket and Socket
(2) Datagram socket: datagram socket

Common construction methods and other methods of ServerSocket:

  • ServerSocket(int port): specifies a port number to listen for client connections and communications
  • Socket accept(): listen for and receive client connections
  • void close(): close

Common construction methods of Socket class:

  • Public socket (InetAddress, int port): create a stream socket and connect it to the specified port number of the specified IP address.
  • public Socket(String host,int port): create a stream socket and connect it to the specified port number on the specified host.

Common methods of Socket class:

  • public InputStream getInputStream(): returns the input stream of this socket, which can be used to receive messages

  • public OutputStream getOutputStream(): returns the output stream of this socket, which can be used to send messages

  • public InetAddress getInetAddress(): the remote IP address to which this socket is connected; Returns null if the socket is not connected.

  • public void close(): close this socket. After the socket is closed, it cannot be used in future network connections (that is, it cannot be reconnected or rebound). A new socket object needs to be created. Closing this socket will also close the InputStream and OutputStream of the socket.

  • public void shutdownInput(): if the contents are read from the socket input stream after calling shutdownInput() on the socket, the stream will return EOF (end of file). That is, no data can be received in the input stream from this socket.

  • public void shutdownOutput(): disables the output stream of this socket. For TCP sockets, any previously written data will be sent, followed by TCP's normal connection termination sequence. If the socket output stream is written after calling shutdown output() on the socket, the stream will throw an IOException. That is, no data can be sent through the output stream of this socket.

Note: the shutdownInput() and shutdownOutput() methods that call Socket successively, just close the input and output streams, and do not equate to the close() method of Socket. After the communication ends, you still need to call the close() method of the socket, because only this method will release the resources occupied by the socket, such as the occupied local port number.

DatagramSocket:

  • DatagramPacket(byte[] buf, int length)
  • DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)

15.5 code examples

15.5.1 TCP protocol programming example I

A client connects to the server. After the connection is successful, the server sends "welcome to login" to the client“

package com.atguigu.test10;

import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
 * TCP: Connection oriented, reliable, byte stream based
 * 		Server: waiting to be connected
 * 
 * ServerSocket: It is only responsible for accepting and establishing connections, not data transmission
 * Socket: Responsible for data transmission
 * 
 * Steps:
 * 1,Turn on the server
 * 	  Specifies the port number on which the server listens
 * 2,Wait for the client and accept the client's connection
 * 
 * 3,Receive / send data
 * Sender: output stream
 * Recipient: input stream
 * 
 * 4,Disconnect
 * 
 * 5,Shut down the server
 */
public class TestServer {
	public static void main(String[] args) throws IOException {
		//1. Turn on the server: the network card driver listens to the data of 9999 port number
		ServerSocket server = new ServerSocket(9999);
		
		//2. Wait for the client and accept the client's connection
		Socket socket = server.accept();//This code executes once and accepts a client connection
		System.out.println("A client connection succeeded!");
		//3. For example: send data
		//Send: welcome to login
		//Byte stream, output stream, OutputStream
		//(1) Get output stream
		OutputStream out = socket.getOutputStream();
		//(2) Send data
		out.write("Welcome to login".getBytes());
		
		//4. Disconnect
		socket.close();
		
		//5. Shut down the server
		server.close();
	}
}

package com.atguigu.test10;

import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;

/*
 * TCP: 
 * 	 Client, active connection to server
 * 
 * Socket(InetAddress address, int port) 
 * Socket(String host, int port)
 * 
 * Steps:
 * 1,Connect server
 * Socket socket = new Socket("192.168.30.142",9999);
 * 
 * 2,Send or receive data
 * 
 * 3,Disconnect
 */
public class TestClient {
	public static void main(String[] args) throws UnknownHostException, IOException {
//		1. Connect server
		Socket socket = new Socket("192.168.30.142",9999);
		
		//2. For example: accept data
		//Byte stream, input stream, InputStream
		InputStream in = socket.getInputStream();
		byte[] data = new byte[1024];
		int len;
		while((len = in.read(data)) != -1){
			System.out.println(new String(data,0,len));
		}
		
		//3. Disconnect
		socket.close();
	}
}

15.5.2 TCP protocol programming example II

A client connects to the server. After the connection is successful, the client sends a "hello" to the server, and the server returns "welcome to login" to the client“

package com.atguigu.test11;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TestServer {
	public static void main(String[] args) throws IOException {
		//1. Turn on the server: the network card driver listens to the data of 9999 port number
		ServerSocket server = new ServerSocket(9999);
		
		//2. Wait for the client and accept the client's connection
		Socket socket = server.accept();//This code executes once and accepts a client connection
		System.out.println("A client connection succeeded!");
		
		//3. Accept data
		InputStream in = socket.getInputStream();
		byte[] data = new byte[1024];
		int len;
		System.out.println("Server received:");
		while((len = in.read(data)) != -1){
			System.out.println(new String(data,0,len));
		}
		
		//4. For example: send data
		//Send: welcome to login
		//Byte stream, output stream, OutputStream
		//(1) Get output stream
		OutputStream out = socket.getOutputStream();
		//(2) Send data
		out.write("Welcome to login".getBytes());
		
		//4. Disconnect
		socket.close();
		
		//5. Shut down the server
		server.close();
	}
}

package com.atguigu.test11;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class TestClient {
	public static void main(String[] args) throws UnknownHostException, IOException {
//		1. Connect server
		Socket socket = new Socket("192.168.30.142",9999);
		
		//2. For example: send hello
		OutputStream out = socket.getOutputStream();
		out.write("Hello".getBytes());
//		out.close(); / / wrong. Calling out.close() will cause the socket to close()
		//If it only means that it will not send but also receive, select semi close and only close the output channel
		socket.shutdownOutput();
		
		//3. For example: accept data
		//Byte stream, input stream, InputStream
		System.out.println("Client received:");
		InputStream in = socket.getInputStream();
		byte[] data = new byte[1024];
		int len;
		while((len = in.read(data)) != -1){
			System.out.println(new String(data,0,len));
		}
		
		//3. Disconnect
		socket.close();
	}
}

15.5.3 TCP protocol programming example III

A client connects to the server. After successful connection:

(1) The client inputs words from the keyboard and sends them to the server until bye;

(2) The server manually reverses the word each time, and then returns it to the client until bye is received

package com.atguigu.test12;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
 * Server side:
 * 	(1)Receive client connections
 *  (2)Receive client words
 *  (3)Return the word "reverse" to the client
 *  (2)(3)Multiple times until the client sends "bye"
 */
public class TestServer {
	public static void main(String[] args) throws IOException {
		//1. Turn on the server
		ServerSocket server = new ServerSocket(8989);
		
		//2. Receive a client connection
		Socket socket = server.accept();
		
		//3. Get the input stream and output stream first
		InputStream in = socket.getInputStream();
		/*
		 * Because it receives a word, reverses one, and returns one
		 * If only byte stream is used, it is difficult to distinguish words
		 * Character stream required
		 * That means you need to stream bytes into character streams
		 */
		InputStreamReader isr = new InputStreamReader(in);//The encoding problem is not involved here, just to convert the type of stream
		/*
		 * Several characters in the character stream are one word
		 * Then we choose "newline" as the word segmentation
		 * This means that we can read Scanner or BufferedReader by line
		 */
		BufferedReader br = new BufferedReader(isr);
		
		OutputStream out = socket.getOutputStream();
		/*
		 * When the client receives bytes, it is also inconvenient to process. A few bytes are a word, and the byte output should still be transferred to the character stream
		 * Moreover, it is not easy to distinguish between characters, so "line feed" is also selected to distinguish words
		 * Now we need to turn the OutputStream into a character stream or other processing stream that can be written by line
		 * 
		 * You can write by line: BufferedWriter(newLine())
		 * 		   PrintStream(println())
		 */
		PrintStream ps = new PrintStream(out);
		
		//Receive words from client
		String word;
		while((word = br.readLine()) != null){
			if("bye".equals(word)){
				break;
			}
			
			//If not bye, reverse and return
			StringBuilder sb = new StringBuilder(word);
			sb.reverse();
			
			//Return to client
			ps.println(sb.toString());
		}
		
		//4. Disconnect
		socket.close();
		
		//5. Shut down the server
		server.close();
	}
}

package com.atguigu.test12;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

/*
 * client:
 * (1)Enter words from the keyboard
 * (2)Send to server
 * (3)Receive the results returned by the server
 * (1)(2)(3)Multiple times until the keyboard enters bye and sends it to the sending server
 */
public class TestClient {
	public static void main(String[] args) throws UnknownHostException, IOException {
		//1. Connect server
		Socket socket = new Socket("192.168.30.142",8989);
		
		/*
		 *  * (1)Enter words from the keyboard
		 * (2)Send to server
		 * (3)Receive the results returned by the server
		 * (1)(2)(3)Multiple times until the keyboard enters bye and sends it to the sending server
		 */
		Scanner input = new Scanner(System.in);
		/*
		 * Also considering the sending words and the segmentation between words, we choose PrintStream and BufferedReader
		 */
		PrintStream ps = new PrintStream(socket.getOutputStream());
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		while(true){
			//Enter words from the keyboard
			System.out.print("Please enter words:");
			String word = input.next();
			
			//Send to server
			ps.println(word);
			
			if("bye".equals(word)){
				break;
			}
			
			//Receive the results returned by the server
			String result = br.readLine();
			System.out.println("Inverted results returned by the server:" + result);
		}
		
		input.close();
		socket.close();
	}
}

15.5.4 TCP protocol programming example 4

Multiple clients connect to the server at the same time. After successful connection:

(1) The client inputs words from the keyboard and sends them to the server until bye;

(2) The server manually reverses the word each time, and then returns it to the client until bye is received

package com.atguigu.test13;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
 * Server side:
 * 	(1)Receive client connections
 *  (2)Receive client words
 *  (3)Return the word "reverse" to the client
 *  (2)(3)Multiple times until the client sends "bye"
 *  
 *  Add a condition that the server can receive n client connections at the same time
 *  Server side has to add multithreading
 */
public class TestServer {
	public static void main(String[] args) throws IOException {
		//1. Turn on the server
		ServerSocket server = new ServerSocket(8989);
		
		boolean flag = true;
		while(flag){
			//2. Receive a client connection
			Socket socket = server.accept();//The socket of each client is independent
			
			//Open a separate thread for each client to maintain its communication
			MessageHandler mh = new MessageHandler(socket);
			mh.start();
		}
			
		//5. Shut down the server
		server.close();
	}
}
class MessageHandler extends Thread{
	private Socket socket;
	
	public MessageHandler(Socket socket) {
		super();
		this.socket = socket;
	}

	public void run(){
		try {
			//3. Get the input stream and output stream first
			InputStream in = socket.getInputStream();
			/*
			 * Because it receives a word, reverses one, and returns one
			 * If only byte stream is used, it is difficult to distinguish words
			 * Character stream required
			 * That means you need to stream bytes into character streams
			 */
			InputStreamReader isr = new InputStreamReader(in);//The encoding problem is not involved here, just to convert the type of stream
			/*
			 * Several characters in the character stream are one word
			 * Then we choose "newline" as the word segmentation
			 * This means that we can read Scanner or BufferedReader by line
			 */
			BufferedReader br = new BufferedReader(isr);
			
			OutputStream out = socket.getOutputStream();
			/*
			 * When the client receives bytes, it is also inconvenient to process. A few bytes are a word, and the byte output should still be transferred to the character stream
			 * Moreover, it is not easy to distinguish between characters, so "line feed" is also selected to distinguish words
			 * Now we need to turn the OutputStream into a character stream or other processing stream that can be written by line
			 * 
			 * You can write by line: BufferedWriter(newLine())
			 * 		   PrintStream(println())
			 */
			PrintStream ps = new PrintStream(out);
			
			//Receive words from client
			String word;
			while((word = br.readLine()) != null){
				if("bye".equals(word)){
					break;
				}
				
				//If not bye, reverse and return
				StringBuilder sb = new StringBuilder(word);
				sb.reverse();
				
				//Return to client
				ps.println(sb.toString());
			}
			
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				//4. Disconnect
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
package com.atguigu.test13;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

/*
 * client:
 * (1)Enter words from the keyboard
 * (2)Send to server
 * (3)Receive the results returned by the server
 * (1)(2)(3)Multiple times until the keyboard enters bye and sends it to the sending server
 * 
 * Add a condition that the server can receive n client connections at the same time
 * The client code does not need to be modified
 */
public class TestClient {
	public static void main(String[] args) throws UnknownHostException, IOException {
		//1. Connect server
		Socket socket = new Socket("192.168.30.142",8989);
		
		/*
		 *  * (1)Enter words from the keyboard
		 * (2)Send to server
		 * (3)Receive the results returned by the server
		 * (1)(2)(3)Multiple times until the keyboard enters bye and sends it to the sending server
		 */
		Scanner input = new Scanner(System.in);
		/*
		 * Also considering the sending words and the segmentation between words, we choose PrintStream and BufferedReader
		 */
		PrintStream ps = new PrintStream(socket.getOutputStream());
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		while(true){
			//Enter words from the keyboard
			System.out.print("Please enter words:");
			String word = input.next();
			
			//Send to server
			ps.println(word);
			
			if("bye".equals(word)){
				break;
			}
			
			//Receive the results returned by the server
			String result = br.readLine();
			System.out.println("Inverted results returned by the server:" + result);
		}
		
		input.close();
		socket.close();
	}
}

15.5.5 TCP protocol programming example 5

A client connects to the server. After the connection is successful, it uploads a file to the server. After receiving the file, the server saves it in the upload folder.

package com.atguigu.test14;

import java.io.DataInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
 * Send files from client to server
 * (1)Receive client connections
 * (2)Receive file name. Suffix
 * reflection:
 * 	 Where to save ① find a location to store in the current project, such as the upload folder
 *  ②How to solve the problem of duplicate file names? File names need to be handled by adding time stamps or other unique encoded UUID equivalents
 *  ③.The suffix needs to be retained because it represents the type of file
 * (3)Receive file content
 * (4)Feedback results
 * 
 * reflection:
 * 		Here, you should receive not only the file name and suffix, but also the file content.
 * 		There are both text information "file name. Suffix" and other types of data "file content". Only byte stream can be selected.
 * 
 * 		How to distinguish between file name, suffix and file content
 * 		What kind of byte input stream do you want to process string and byte type data.
 * 
 * 		FileInputStream
 * 		BufferedInputStream
 * 		DataInputStream
 * 		ObjectInputStream
 * 
 * 		Among these: DataInputStream: readUTF() and read(byte [])
 * 				ObjectInputStream Yes, but please, I choose DataInputStream here
 * 
 */
public class TestServer {
	public static void main(String[] args) throws IOException {
		//1. Turn on the server
		ServerSocket server = new ServerSocket(9999);
		
		//2. Receive client connections
		Socket socket = server.accept();
		
		//3. Get input stream
		InputStream in = socket.getInputStream();
		DataInputStream dis = new DataInputStream(in);
		
		//Receive file name. Suffix
		String fileName = dis.readUTF();
		
		//Processing file name
		/*
		 * The file name I want to store on the server: the original file name + timestamp
		 */
		long timestamp = System.currentTimeMillis();
		//. subscript
		int index = fileName.lastIndexOf(".");
		//Suffix
		String ext = fileName.substring(index);
		// Original file name
		String name = fileName.substring(0, index);
		//New file name
		String newFileName = "upload/" + name + timestamp + ext;
		
		//Create a file output stream and write the received file content to a new file
		FileOutputStream fos = new FileOutputStream(newFileName);
		
		//Receive file content
		byte[] data = new byte[1024];
		int len;
		while((len = dis.read(data))!=-1){
			fos.write(data, 0, len);
		}
		
		//You can also give feedback to the client that the file has been received
		OutputStream out = socket.getOutputStream();
		PrintStream ps = new PrintStream(out);
		ps.println("File received!");
		
		//to break off
		fos.close();
		socket.close();
		server.close();
	}
}

package com.atguigu.test14;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

/*
 * Send files from client to server
 * 
 * 
 * client:
 * (1)Enter the path name of the file from the keyboard, that is, select the file to send
 * (2)Give the server the file name. Suffix first“
 * (3)Send file content
 * (4)Receive feedback from the server
 * 
 * Here, because you want to send both "file name. Suffix" and "file content", select byte stream and DataOutputStream
 * 
 */
public class TestClient {
	public static void main(String[] args) throws UnknownHostException, IOException {
		//1. Connect server
		Socket socket = new Socket("192.168.30.142",9999);
		
		//2. Enter the path name of the file from the keyboard, that is, select the file to send
		Scanner input = new Scanner(System.in);
		System.out.print("Please select the file you want to send (for example: D:/Shang Silicon Valley_190513 class_Chai Linyan_JavaSE/Information issued at the opening ceremony.rar): ");
		String fileName = input.nextLine();
		File file = new File(fileName);
		
		//3. Send the file name. Suffix to the server“
		OutputStream out = socket.getOutputStream();
		DataOutputStream dos = new DataOutputStream(out);
		
		//Send file name. Suffix“
		dos.writeUTF(file.getName());
		
		//4. Send file content
		//Read the contents from the file first
		FileInputStream fis = new FileInputStream(file);
		byte[] data = new byte[1024];
		int len;
		while((len = fis.read(data)) != -1){
			//Read and send to the server at the same time
			dos.write(data,0,len);
		}
		socket.shutdownOutput();//Indicates that the transmission is complete
		
		//5. Receive feedback
		InputStream in = socket.getInputStream();
		InputStreamReader isr = new InputStreamReader(in);
		BufferedReader br = new BufferedReader(isr);
		String result = br.readLine();
		System.out.println("result:" + result);
		
		//6. Shut down
		socket.close();
		fis.close();
	}
}

15.5.6 TCP protocol programming example 6

Multiple clients connect to the server. After the connection is successful, a file is uploaded to the server. After the server receives the file, it is saved in the upload folder.

package com.atguigu.test15;

import java.io.DataInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TestServer {
	public static void main(String[] args) throws IOException {
		//1. Turn on the server
		ServerSocket server = new ServerSocket(9999);
		
		while(true){
			//2. Receive client connections
			Socket socket = server.accept();
			
			FileUploadThread ft = new FileUploadThread(socket);
			ft.start();
		
		}
//		server.close();// Do not shut down the server
	}
}
class FileUploadThread extends Thread{
	private Socket socket;
	
	public FileUploadThread(Socket socket) {
		super();
		this.socket = socket;
	}

	public void run(){
		try {
			//3. Get input stream
			InputStream in = socket.getInputStream();
			DataInputStream dis = new DataInputStream(in);
			
			//Receive file name. Suffix
			String fileName = dis.readUTF();
			
			//Processing file name
			/*
			 * The file name I want to store on the server: the original file name + timestamp
			 */
			long timestamp = System.currentTimeMillis();
			//. subscript
			int index = fileName.lastIndexOf(".");
			//Suffix
			String ext = fileName.substring(index);
			// Original file name
			String name = fileName.substring(0, index);
			//New file name
			String newFileName = "upload/" + name + timestamp + ext;
			
			//Create a file output stream and write the received file content to a new file
			FileOutputStream fos = new FileOutputStream(newFileName);
			
			//Receive file content
			byte[] data = new byte[1024];
			int len;
			while((len = dis.read(data))!=-1){
				fos.write(data, 0, len);
			}
			
			//You can also give feedback to the client that the file has been received
			OutputStream out = socket.getOutputStream();
			PrintStream ps = new PrintStream(out);
			ps.println("File received!");
			
			//to break off
			fos.close();
			socket.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
package com.atguigu.test15;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class TestClient {
	public static void main(String[] args) throws UnknownHostException, IOException {
		//1. Connect server
		Socket socket = new Socket("192.168.30.142",9999);
		
		//2. Enter the path name of the file from the keyboard, that is, select the file to send
		Scanner input = new Scanner(System.in);
		System.out.print("Please select the file you want to send (for example: D:/Shang Silicon Valley_190513 class_Chai Linyan_JavaSE/Information issued at the opening ceremony.rar): ");
		String fileName = input.nextLine();
		File file = new File(fileName);
		
		//3. Send the file name. Suffix to the server“
		OutputStream out = socket.getOutputStream();
		DataOutputStream dos = new DataOutputStream(out);
		
		//Send file name. Suffix“
		dos.writeUTF(file.getName());
		
		//4. Send file content
		//Read the contents from the file first
		FileInputStream fis = new FileInputStream(file);
		byte[] data = new byte[1024];
		int len;
		while((len = fis.read(data)) != -1){
			//Read and send to the server at the same time
			dos.write(data,0,len);
		}
		socket.shutdownOutput();//Indicates that the transmission is complete
		
		//5. Receive feedback
		InputStream in = socket.getInputStream();
		InputStreamReader isr = new InputStreamReader(in);
		BufferedReader br = new BufferedReader(isr);
		String result = br.readLine();
		System.out.println("result:" + result);
		
		//6. Shut down
		socket.close();
		fis.close();
		input.close();
	}
}

15.5.7 TCP protocol programming example 7

Group chat

package com.atguigu.test16;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;

/*
 * 
 */
public class TestServer {
	private static ArrayList<Socket> online = new ArrayList<Socket>();
	
	public static void main(String[] args) throws IOException {
		//1. Turn on the server
		ServerSocket server = new ServerSocket(9999);
		
		while(true){
			//2. Receive client connections
			Socket socket = server.accept();
			
			//Add this client to online
			online.add(socket);
			
			//Each client has an independent thread
			MessageHandler mh = new MessageHandler(socket);
			mh.start();
		}
	}

	//Private static inner class
	//The reason for using inner classes here is to use the online collection above
	private static class MessageHandler extends Thread{
		private Socket socket;
		private String ip;
		
		public MessageHandler(Socket socket) {
			super();
			this.socket = socket;
			this.ip = socket.getInetAddress().getHostAddress();
		}

		public void run(){
			//Once the client is successfully connected, the thread can tell others that I'm online as soon as it starts
			sendToOthers(ip+"It's online");
			
			/*
			 * (1)Receive messages sent by the current client
			 * (2)Forward to other online clients
			 */
			//(1) Receive messages sent by the current client
			try {
				InputStream in = socket.getInputStream();
				InputStreamReader isr = new InputStreamReader(in);
				BufferedReader br = new BufferedReader(isr);
				
				String content;
				while((content = br.readLine()) !=null){
					if("bye".equals(content)){
						//Send yourself a bye
						OutputStream out = socket.getOutputStream();
						PrintStream ps = new PrintStream(out);
						ps.println("bye");
						
						break;
					}
					
					//Receive a sentence and forward a sentence
					sendToOthers(ip+"say:" + content);
				}
				
				sendToOthers(ip+"Offline");
			} catch (IOException e) {
				sendToOthers(ip+"The line dropped");
			}
		}
		
		//Because the forwarding code is also very long, it is an independent method
		public void sendToOthers(String str){
			//Traverse all online clients
			Iterator<Socket> iterator = online.iterator();
			while(iterator.hasNext()){
				Socket on = iterator.next();
				if(!on.equals(socket)){//Forward only to other clients
					try {
						OutputStream out = on.getOutputStream();
						PrintStream ps = new PrintStream(out);
						
						ps.println(str);
					} catch (IOException e) {
						//This means that the on client is either offline or offline
						iterator.remove();
					}
				}
			}
		}
	}
	
	
}

package com.atguigu.test16;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

/*
 * Group chat
 */
public class TestClient {
	public static void main(String[] args) throws UnknownHostException, IOException {
		//1. Connect server
		Socket socket = new Socket("192.168.30.142",9999);
		
		//2. Start two threads, one to receive messages and one to send messages
		SendThread st = new SendThread(socket);
		ReceiveThread rt = new ReceiveThread(socket);
		
		st.start();
		rt.start();
		
		//Wait until the sending thread stops
		try {
			st.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		//Stop the thread receiving data
		rt.setFlag(false);
		
		//Wait until the receiving thread stops, then go down and disconnect
		try {
			rt.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		socket.close();
	}
}
class SendThread extends Thread{
	private Socket socket;
	
	public SendThread(Socket socket) {
		super();
		this.socket = socket;
	}

	public void run(){
		try {
			//keyboard entry
			Scanner input = new Scanner(System.in);
			OutputStream out = socket.getOutputStream();
			PrintStream ps = new PrintStream(out);
			while(true){
				//Input from keyboard
				System.out.print("Please enter a message to send:");
				String content = input.nextLine();
				System.out.println("content:" + content);
				
				//Send to server
				ps.println(content);
				
				//If bye, the sending ends
				if("bye".equals(content)){
					break;
				}
			}
			input.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
class ReceiveThread extends Thread{
	private Socket socket;
	private boolean flag = true;
	
	public ReceiveThread(Socket socket) {
		super();
		this.socket = socket;
	}
	
	public void run(){
		try {
			InputStream in = socket.getInputStream();
			InputStreamReader isr = new InputStreamReader(in);
			BufferedReader br = new BufferedReader(isr);
			
			while(flag){
				String line = br.readLine();
				System.out.println(line);
				if("bye".equals(line)){
					break;
				}
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void setFlag(boolean flag) {
		this.flag = flag;
	}
	
}

15.5.8 UDP protocol programming example

package com.atguigu.test17;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class TestSend {
	public static void main(String[] args) throws IOException {
		//1. The sender creates a Socket
		//The port number and IP address of the sender are obtained automatically
		DatagramSocket ds = new DatagramSocket();
		
		//2. Prepare to package the data to be sent
		String str = "Class is over soon";
		byte[] bytes = str.getBytes();
		InetAddress ip = InetAddress.getByName("192.168.30.142");
		DatagramPacket dp = new DatagramPacket(bytes,0,bytes.length, ip, 9999);
		
		//3. Send via socket
		ds.send(dp);
		System.out.println("Send complete");
		
		//4. Shut down
		ds.close();
		
	}
}

package com.atguigu.test17;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/*
 * Receiver:
 * 	DatagramPacket(byte[] buf, int length) 
 * 	Parameter 1: byte array used to hold data
 *  Parameter 2: length of array
 */
public class TestReceive {
	public static void main(String[] args) throws IOException {
		//1. The receiver also needs a socket
		//The port number of the receiver, specified, and automatically obtained by IP
		DatagramSocket ds = new DatagramSocket(9999);
		
		//2. Prepare a datagram and receive data
		byte[] data = new byte[1024];
		DatagramPacket dp = new DatagramPacket(data,data.length);
		
		//3. Receive data
		ds.receive(dp);
		
		//4. Disassemble the data
		byte[] bs = dp.getData();//Received data
		int len = dp.getLength();//Actual length of data received
		System.out.println(new String(bs,0,len));
		
		//5. Disconnect
		ds.close();
	}
}

Chapter 16 reflection (difficulties)

16.1 class loading

1. Class life cycle in memory: load – > use – > unload

2. Class loading is divided into three stages:

(1) Loading: load

(2) Connection: link

① Verification: verify validity

② Preparation: prepare the corresponding memory (method area), create Class objects, assign default values to Class variables, and assign initial values to static constants.

③ Parsing: replace the symbol reference in bytecode with the corresponding direct address reference

(3) Initialization: initialize (class initialization). In most cases, class initialization is completed after class loading. In some cases, class initialization will be delayed.

[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-xup1fp4n-1631456884050)(imgs/1560767438339.png)]

3. What causes class initialization?

(1) The class of the main method must be initialized first

(2) The first time you use a type is when you new its object. If the class is not initialized at this time, complete class initialization first and then instance initialization

(3) Call the static members (class variables and class methods) of a class. If the class is not initialized, complete the class initialization first

(4) When initializing a subclass, if it is found that its parent class has not been initialized, initialize the parent class first

(5) When a class is operated through reflection, if the class is not initialized, it will also cause the class to initialize first

Class initialization executes () which consists of (1) the explicit assignment code of class variables and (2) the code in the static code block

class Father{
	static{
		System.out.println("main The parent class of the class in which the method is located(1)");//When a child class is initialized, the parent class is initialized
	}
}

public class TestClinit1 extends Father{
	static{
		System.out.println("main The class in which the method resides(2)");//The class of the main method is initialized
	}
	
	public static void main(String[] args) throws ClassNotFoundException {
		new A();//The first time you use a is to create its object, which initializes class A
		
		B.test();//Using static members of class B directly initializes class B
		
		Class clazz = Class.forName("com.atguigu.test02.C");//Class C is initialized by reflection operation
	}
}
class A{
	static{
		System.out.println("A Class initialization");
	}
}
class B{
	static{
		System.out.println("B Class initialization");
	}
	public static void test(){
		System.out.println("B Class");
	}
}
class C{
	static{
		System.out.println("C Class initialization");
	}
}

4. Which use classes but do not cause class initialization?

(1) Use a static constant of a class (static final)

(2) Calling static variables and methods of the parent class through a subclass will only lead to the initialization of the parent class, not the subclass, that is, only the class declaring static members will be initialized

(3) Declaring an array with a type and creating an array object does not cause this class to initialize

public class TestClinit2 {
	public static void main(String[] args) {
		System.out.println(D.NUM);//Class D is not initialized because NUM is final
		
		System.out.println(F.num);
		F.test();//Class F will not initialize, class E will initialize, because num and test() are declared in class E
		
		//Class G will not be initialized, and there is no formal class G at this time
		G[] arr = new G[5];//Instead of creating an object of G, an array object is created to hold the G object
        //G [] is a new type. It is a new type generated by dynamic compilation of array classes
        //G[].class
	}
}
class D{
	public static final int NUM = 10;
	static{
		System.out.println("D Class initialization");
	}
}
class E{
	static int num = 10;
	static{
		System.out.println("E Initialization of parent class");
	}
	public static void test(){
		System.out.println("Static method of parent class");
	}
}
class F extends E{
	static{
		System.out.println("F Initialization of subclasses");
	}
}

class G{
	static{
		System.out.println("G Class initialization");
	}
}

5. Class loader is required for class loading

(1) Boot class loader

It is responsible for loading the jre/rt.jar core library

It is not implemented in Java code, nor is it a subclass of ClassLoader. When obtaining its object, it often returns null

(2) Extended class loader

It is responsible for loading the jre/lib/ext extension library

It is a subclass of ClassLoader

(3) Application class loader

It is responsible for loading the classes under the classpath path of the project

It is a subclass of ClassLoader

(4) Custom class loader

When your program needs to load classes in the "specific" directory, you can customize the class loader;

When the bytecode file of your program needs to be encrypted, a custom class loader is often provided to decode it

The custom class loader you will see later: in tomcat

6. Parent delegation mode of class loader in Java System

Brief description:

If the Class loader at the next level receives a task, it will first search whether it has been loaded. If not, it will upload the task first. If it has not been loaded, it will go all the way to the root loader. If the root loader is not found under its responsible path, it will send it back. If it is not found all the way back to the last level, ClassNotFoundException or NoClassDefError will be reported. If it is found at a certain level, the Class object will be returned directly.

The application class loader regards the extension class loader as the parent loader,

The extension class loader treats the boot class loader as the parent loader.

It is not an inheritance relationship, but a combination.

16.2 javalang.Class class

Related API s (1) java.lang.Class (2) java.lang.reflect. *;

1. The Class object is the source of reflection.

2. Which types can get Class objects, you can use code examples

//(1) Basic data type and void
 For example: int.class
	 void.class
//(2) Classes and interfaces
 For example: String.class
	Comparable.class
//(3) Enumeration
 For example: ElementType.class
//(4) Annotation
 For example: Override.class
//(5) Array
 For example: int[].class

3. Four ways to get Class objects
(1) Type name.class

Requires a type known during compilation

(2) Object. getClass()

Only runtime types of objects that already exist can be obtained

(3) Class. Forname (full name of type)

Can get types unknown during compilation

(4) ClassLoader's ClassLoader object. Loadclass (type full name)

You can use a custom loader object to load types under a specified path

public class TestClass {
	@Test
	public void test05() throws ClassNotFoundException{
		Class c = TestClass.class;
		ClassLoader loader = c.getClassLoader();
		
		Class c2 = loader.loadClass("com.atguigu.test05.Employee");
		Class c3 = Employee.class;
		System.out.println(c2 == c3);
	}
	
	@Test
	public void test03() throws ClassNotFoundException{
		Class c2 = String.class;
		Class c1 = "".getClass();
		Class c3 = Class.forName("java.lang.String");
		
		System.out.println(c1 == c2);
		System.out.println(c1 == c3);
	}
}

16.3 application of reflection

16.3.1 get type details

You can obtain: package, modifier, type name, parent class (including generic parent class), parent interface (including generic parent interface), member (property, constructor, method), annotation (on class, method, property)

Sample code for general information:

public class TestClassInfo {
	public static void main(String[] args) throws NoSuchFieldException, SecurityException {
		//1. Get a Class object of a certain type first
		Class clazz = String.class;
		//A metaphor clazz is like a shadow in a mirror
		
		//2. Get class information
		//(1) Get the Package object, that is, all java packages are Package objects
		Package pkg = clazz.getPackage();
		System.out.println("Package name:" + pkg.getName());
		
		//(2) Get modifier
		//In fact, the Modifier is Modifier, which has many constant values
		/*
		 * 0x It's hexadecimal
		 * PUBLIC           = 0x00000001;  1    1
		 * PRIVATE          = 0x00000002;  2	10
		 * PROTECTED        = 0x00000004;  4	100
		 * STATIC           = 0x00000008;  8	1000
		 * FINAL            = 0x00000010;  16	10000
		 * ...
		 * 
		 * The design idea is to use a bit of binary as 1 to represent a modifier. Only one bit of the whole binary is 1 and the rest are 0
		 * 
		 * mod = 17          0x00000011
		 * if ((mod & PUBLIC) != 0)  Description modifier has public
		 * if ((mod & FINAL) != 0)   Description modifier has final
		 */
		int mod = clazz.getModifiers();
		System.out.println(Modifier.toString(mod));
		
		//(3) Type name
		String name = clazz.getName();
		System.out.println(name);
		
		//(4) The parent Class also has the Class object corresponding to the parent Class
		Class superclass = clazz.getSuperclass();
		System.out.println(superclass);
		
		//(5) Parent interfaces
		Class[] interfaces = clazz.getInterfaces();
		for (Class class1 : interfaces) {
			System.out.println(class1);
		}
		
		//(6) Class, a property you declare, which is the object of Field
/*		Field clazz.getField(name)  Get a property object according to the property name, but you can only get public
		Field[] clazz.getFields();  Get all public properties
		Field clazz.getDeclaredField(name)  Get a property object according to the property name to get the declared
		Field[] clazz.getDeclaredFields()	Get all declared properties
		*/
		Field valueField = clazz.getDeclaredField("value");
//		System.out.println("valueField = " +valueField);
		
		Field[] declaredFields = clazz.getDeclaredFields();
		for (Field field : declaredFields) {
			//Modifier, data type, property name    
			int modifiers = field.getModifiers();
			System.out.println("Modifier for property:" + Modifier.toString(modifiers));
			
			String name2 = field.getName();
			System.out.println("Property name:" + name2);
			
			Class<?> type = field.getType();
			System.out.println("Data type of property:" + type);
		}
		System.out.println("-------------------------");
		//(7) Constructors
		Constructor[] constructors = clazz.getDeclaredConstructors();
		for (Constructor constructor : constructors) {
			//Modifier, constructor name, constructor parameter list, thrown exception list
			int modifiers = constructor.getModifiers();
			System.out.println("Modifier for constructor:" + Modifier.toString(modifiers));
			
			String name2 = constructor.getName();
			System.out.println("Constructor Name:" + name2);
			
			//parameter list 
			System.out.println("Formal parameter list:");
			Class[] parameterTypes = constructor.getParameterTypes();
			for (Class class1 : parameterTypes) {
				System.out.println(class1);
			}
		}
		System.out.println("=--------------------------------");
		//(8) Methods
		Method[] declaredMethods = clazz.getDeclaredMethods();
		for (Method method : declaredMethods) {
			//Modifier, return value type, method name, parameter list, exception list 
			int modifiers = method.getModifiers();
			System.out.println("Modifier for method:" + Modifier.toString(modifiers));
			
			Class<?> returnType = method.getReturnType();
			System.out.println("return type:" + returnType);
			
			String name2 = method.getName();
			System.out.println("Method name:" + name2);
			
			//parameter list 
			System.out.println("Formal parameter list:");
			Class[] parameterTypes = method.getParameterTypes();
			for (Class class1 : parameterTypes) {
				System.out.println(class1);
			}
			
			//Exception list
			System.out.println("Exception list:");
			Class<?>[] exceptionTypes = method.getExceptionTypes();
			for (Class<?> class1 : exceptionTypes) {
				System.out.println(class1);
			}
		}
		
	}
}

16.3.2 create objects of any reference type

There are two ways:

1. Instantiate directly through Class object (parameter free construction is required)

2. Instantiate by getting the constructor object

Steps of mode 1:

(1) Get the Class object of this type (2) and create the object

Steps of mode 2:

(1) Get Class object of this type (2) get constructor object (3) create object

setAccessible(true) can also be called if the scope modified by the constructor's permission modifier is not visible

Example code:

public class TestNewInstance {
	@Test
	public void test3()throws Exception{
		//(1) Get Class object
		Class<?> clazz = Class.forName("com.atguigu.test.Student");
		/*
		 * Gets the parameterized construct in the Student type
		 * If there are multiple constructors, we usually obtain the specified constructor according to the formal parameter [type] list
		 * For example: public Student(int id, String name) 
		 */
		//(2) Get constructor object
		Constructor<?> constructor = clazz.getDeclaredConstructor(int.class,String.class);
		
		//(3) Create instance object
		// T newInstance(Object... initargs) this Object... Is a list of arguments constructed with parameters when creating an Object
		Object obj = constructor.newInstance(2,"Zhang San");
		System.out.println(obj);
	}
	
	@Test
	public void test2()throws Exception{
		Class<?> clazz = Class.forName("com.atguigu.test.Student");
		//Caused by: java.lang.NoSuchMethodException: com.atguigu.test.Student.<init>()
		//That is, if the Student does not have a parameterless structure, there is no parameterless instance initialization method < init >
		Object stu = clazz.newInstance();
		System.out.println(stu);
	}
	
	@Test
	public void test1() throws ClassNotFoundException, InstantiationException, IllegalAccessException{
//		AtGuigu obj = new AtGuigu();// Cannot be created during compilation
		
		Class<?> clazz = Class.forName("com.atguigu.test.AtGuigu");
		//clazz stands for com.atguigu.test.AtGuigu type
		//clazz.newInstance() creates the object of AtGuigu
		Object obj = clazz.newInstance();
		System.out.println(obj);
	}
}

16.3.3 operation of any type of attribute

(1) Gets the Class object of this type
Class clazz = Class.forName("com.atguigu.bean.User");
(2) Get property object
Field field = clazz.getDeclaredField("username");
(3) Create instance object
Object obj = clazz.newInstance();

(4) Set properties accessible

field.setAccessible(true);

(4) Set properties

field.set(obj,"chai");
(5) Get property value
Object value = field.get(obj);

If you operate on static variables, the instance object can be omitted and represented by null

Example code:

public class TestField {
	public static void main(String[] args)throws Exception {
		//1. Gets the Class object of the Student
		Class clazz = Class.forName("com.atguigu.test.Student");
		
		//2. Get the attribute object, for example: id attribute
		Field idField = clazz.getDeclaredField("id");
		
		//3. Create an instance object, that is, create a Student object
		Object stu = clazz.newInstance();
		
		//If the id is private and access is not accessible in the current class, we need to do the following
		idField.setAccessible(true);
		
		//4. Get property value
		/*
		 * Previously: int variable = Student object. getId()
		 * Now: Object id attribute object. Get (Student object)
		 */
		Object value = idField.get(stu);
		System.out.println("id = "+ value);
		
		//5. Set attribute value
		/*
		 * Previous: Student object. Setid (value)
		 * Now: id attribute object. Set (Student object, value)
		 */
		idField.set(stu, 2);
		
		value = idField.get(stu);
		System.out.println("id = "+ value);
	}
}

16.3.4 calling any type of method

(1) Gets the Class object of this type
Class clazz = Class.forName("com.atguigu.service.UserService");
(2) Get method object
Method method = clazz.getDeclaredMethod("login",String.class,String.class);
(3) Create instance object
Object obj = clazz.newInstance();
(4) Call method
Object result = method.invoke(obj,"chai","123);

If the scope modified by the permission modifier of the method is not visible, setAccessible(true) can also be called

If the method is static, the instance object can also be omitted and replaced with null

Example code:

public class TestMethod {
	@Test
	public void test()throws Exception {
		// 1. Gets the Class object of the Student
		Class<?> clazz = Class.forName("com.atguigu.test.Student");
		
		//2. Get method object
		/*
		 * To uniquely locate a method in a class, you need: (1) method name (2) formal parameter list, because the method may be overloaded
		 * 
		 * For example: void setName(String name)
		 */
		Method method = clazz.getDeclaredMethod("setName", String.class);
		
		//3. Create instance object
		Object stu = clazz.newInstance();
		
		//4. Call method
		/*
		 * Previous: Student object. Setname (value)
		 * Now: method object. Invoke (Student object, value)
		 */
		method.invoke(stu, "Zhang San");
		
		System.out.println(stu);
	}
}

16.3.5 get generic parent class information

Sample code to get generic parent class information:

/* Type: 
 * (1)Class
 * (2)ParameterizedType   
 * 		For example: father < string, integer >
 * 			ArrayList<String>
 * (3)TypeVariable
 * 		For example: T, U,E,K,V
 * (4)WildcardType
 * 		For example:
 * 		ArrayList<?>
 * 		ArrayList<? super Lower limit >
 * 		ArrayList<? extends Upper limit >
 * (5)GenericArrayType
 * 		For example: T []
 * 	
 */
public class TestGeneric {
	public static void main(String[] args) {
		//Requirement: at runtime, get the generic argument < string, integer > of the generic parent class of Son type
		
		//(1) Or get the Class object first
		Class clazz = Son.class;//Any of the four forms is OK
		
		//(2) Get generic parent class
//		Class sc = clazz.getSuperclass();
//		System.out.println(sc);
		/*
		 * getSuperclass()Only the parent class name can be obtained, and the generic argument list of the parent class cannot be obtained
		 */
		Type type = clazz.getGenericSuperclass();
		
		// Father < string, integer > belongs to ParameterizedType
		ParameterizedType pt = (ParameterizedType) type;
		
		//(3) Gets the list of generic arguments for the generic parent class
		Type[] typeArray = pt.getActualTypeArguments();
		for (Type type2 : typeArray) {
			System.out.println(type2);
		}
	}
}
//Generic parameter: < T, u >
class Father<T,U>{
	
}
//Generic argument: < string, integer >
class Son extends Father<String,Integer>{
	
}

16.3.6 reading annotation information

Example code reads annotation information:

public class TestAnnotation {
	public static void main(String[] args) {
		//Requirement: you can obtain the value of @ MyAnnotation configured above MyClass type
		
		//Read annotation
//		(1) Get Class object
		Class<MyClass> clazz = MyClass.class;
		
		//(2) Get annotation object
		//Gets the specified annotation object
		MyAnnotation my = clazz.getAnnotation(MyAnnotation.class);
		
		//(3) Get configuration parameter value
		String value = my.value();
		System.out.println(value);
	}
}
//statement
@Retention(RetentionPolicy.RUNTIME)  //Note that this annotation can be retained until runtime
@Target(ElementType.TYPE) //Note: this annotation can only be used on types, including classes, interfaces, enumerations, etc
@interface MyAnnotation{
	//Configuration parameter. If there is only one configuration parameter and the name is value, value can be omitted during assignment=
	String value();
}

//Using annotations
@MyAnnotation("/login")
class MyClass{
	
}

Chapter 17 Java 8

17.1 Lambda expressions and functional interfaces

Lambda's good writing can greatly reduce code redundancy, and its readability is better than lengthy anonymous inner classes.

17.1.1 functional interface

lambda expression is actually the syntax sugar to implement SAM interface. The so-called SAM interface is Single Abstract Method, that is, there is only one abstract method to be implemented in the interface. Of course, the interface can contain other non abstract methods.

In fact, any interface that meets the "SAM" characteristics can be called a functional interface, but if you want to be more specific, you'd better add @ functional interface when declaring the interface.

Among the previously learned interfaces, functional interfaces include Runnable, Comparator and FileFilter

1. Consumer interface

The abstract method features of this kind of interface: it has formal parameters, but the return value type is void

Interface nameAbstract methoddescribe
Consumervoid accept(T t)Receive an object to complete the function
BiConsumer<T,U>void accept(T t, U u)Receive two objects to complete the function
DoubleConsumervoid accept(double value)Receive a double value
IntConsumervoid accept(int value)Receive an int value
LongConsumervoid accept(long value)Receive a long value
ObjDoubleConsumervoid accept(T t, double value)Receive an object and a double value
ObjIntConsumervoid accept(T t, int value)Receive an object and an int value
ObjLongConsumervoid accept(T t, long value)Receive an object and a long value

2. Supply type interface

Abstract method characteristics of this kind of interface: no parameters, but no return value

Interface nameAbstract methoddescribe
SupplierT get()Returns an object
BooleanSupplierboolean getAsBoolean()Returns a boolean value
DoubleSupplierdouble getAsDouble()Returns a double value
IntSupplierint getAsInt()Returns an int value
LongSupplierlong getAsLong()Returns a long value

3. Judgment interface

The abstract method feature of the interface here is that it has parameters, but the return value type is boolean result.

Interface nameAbstract methoddescribe
Predicateboolean test(T t)Receive an object
BiPredicate<T,U>boolean test(T t, U u)Receive two objects
DoublePredicateboolean test(double value)Receive a double value
IntPredicateboolean test(int value)Receive an int value
LongPredicateboolean test(long value)Receive a long value

4. Functional interface

Abstract method features of this kind of interface: both parameters and return values

Interface nameAbstract methoddescribe
Function<T,R>R apply(T t)Receive a T-type object and return an R-type object result
UnaryOperatorT apply(T t)Receive a T-type object and return a T-type object result
DoubleFunctionR apply(double value)Receive a double value and return an R-type object
IntFunctionR apply(int value)Receive an int value and return an R-type object
LongFunctionR apply(long value)Receive a long value and return an R-type object
ToDoubleFunctiondouble applyAsDouble(T value)Receive a T-type object and return a double
ToIntFunctionint applyAsInt(T value)Receive a T-type object and return an int
ToLongFunctionlong applyAsLong(T value)Receive a T-type object and return a long
DoubleToIntFunctionint applyAsInt(double value)Receive a double value and return an int result
DoubleToLongFunctionlong applyAsLong(double value)Receive a double value and return a long result
IntToDoubleFunctiondouble applyAsDouble(int value)Receive an int value and return a double result
IntToLongFunctionlong applyAsLong(int value)Receive an int value and return a long result
LongToDoubleFunctiondouble applyAsDouble(long value)Receive a long value and return a double result
LongToIntFunctionint applyAsInt(long value)Receive a long value and return an int result
DoubleUnaryOperatordouble applyAsDouble(double operand)Receive a double value and return a double
IntUnaryOperatorint applyAsInt(int operand)Receive an int value and return an int result
LongUnaryOperatorlong applyAsLong(long operand)Receive a long value and return a long result
BiFunction<T,U,R>R apply(T t, U u)Receive a T-type and a U-type object and return an R-type object result
BinaryOperatorT apply(T t, T u)Receive two T-type objects and return a T-type object result
ToDoubleBiFunction<T,U>double applyAsDouble(T t, U u)Receive a T-type and a U-type object and return a double
ToIntBiFunction<T,U>int applyAsInt(T t, U u)Receives a T-type and a U-type object and returns an int
ToLongBiFunction<T,U>long applyAsLong(T t, U u)Receive a T-type and a U-type object and return a long
DoubleBinaryOperatordouble applyAsDouble(double left, double right)Receive two double values and return a double result
IntBinaryOperatorint applyAsInt(int left, int right)Receive two int values and return an int result
LongBinaryOperatorlong applyAsLong(long left, long right)Receive two long values and return a long result

17.1.2 Lambda expression syntax

Lambda expression is used to assign values to variables or formal parameters of [functional interface].

In fact, Lambda expressions are essentially "abstract methods" used to implement [functional interfaces]

Lambda expression syntax format

(parameter list ) -> {Lambda body}

explain:

  • (formal parameter list) it is the abstract method (formal parameter list) of the functional interface you want to assign value. Copy it
  • {Lambda} is the method body that implements this abstract method
  • ->It is called Lambda operator (there can be no space between minus sign and greater than sign, and it must be half angle input in English)

Optimization: Lambda expressions can be streamlined

  • When there is only one sentence in {Lambda body}, {} and {;} can be omitted
  • When there is only one sentence in {Lambda body} and the sentence is still a return statement, return can also be omitted, but if {;} is not omitted, return cannot be omitted
  • When the type of (formal parameter list) is known, the type of formal parameter can be omitted
  • When the type of (formal parameter list) is known and the number of formal parameters is only one, the data type and () can be omitted, but the formal parameter name cannot be omitted
  • () cannot be omitted when (formal parameter list) is an empty parameter

Example code:

public class TestLambdaGrammer {
	@Test
	public void test1(){
		//Assign a value to the formal parameter or variable of the Runnable interface with a Lambda expression
		/*
		 * To write a lambda expression, you need to determine two things
		 * (1)What does the abstract method of this interface look like
		 * 		public void run()
		 * (2)What does the implementation of this abstract method do
		 * 		For example: I want to print "hello lambda"“
		 */
		Runnable r = () -> {System.out.println("hello lambda");};
	}
	
	@Test
	public void test2(){
		//lambda body omits {;}
		Runnable r = () -> System.out.println("hello lambda");
	}
	
	@Test
	public void test3(){
		String[] arr = {"hello","Hello","java","chai"};
		
		//Sort the arr array, but you want to be case insensitive
		/*
		 * public static <T> void sort(T[] a,Comparator<? super T> c)
		 * Here, you use a Lambda expression to assign a value to a formal parameter of type Comparator
		 * 
		 * Two things:
		 * (1)Abstract method of this interface: int compare(T o1, T o2)
		 * (2)What does this abstract method do?
		 * 		For example, for elements of String type, case insensitive comparison is required
		 */
//		Arrays.sort(arr, (String o1, String o2) -> {return o1.compareToIgnoreCase(o2);});
		
		//{return;} is omitted
//		Arrays.sort(arr, (String o1, String o2) ->  o1.compareToIgnoreCase(o2));
		
		//Two strings are omitted
		Arrays.sort(arr, (o1, o2) ->  o1.compareToIgnoreCase(o2));
		
		for (String string : arr) {
			System.out.println(string);
		}
	}
	
	@Test
	public void test4(){
		ArrayList<String> list = new ArrayList<>();
		list.add("hello");
		list.add("java");
		list.add("world");
		
		/*
		 * JDK1.8 For collections of Collection series, to be exact, a default method is added to the Iterable interface
		 * 		default void forEach(Consumer<? super T> action) 
		 * This method is used to traverse the set, etc. instead of the original foreach loop.
		 * 
		 * The formal parameter of this method is the Consumer interface type, which is the representative of the Consumer interface in the functional interface
		 * I now call this method to assign a value to the type parameter of the Consumer interface with a Lambda expression
		 * 
		 * Two things:
		 * (1)Its abstract method: void accept (T)
		 * (2)What does the implementation of abstract methods accomplish
		 * 		For example, here you want to print this t
		 */
//		list.forEach((String t) -> {System.out.println(t);});
		
		//Omit {;}
//		list.forEach((String t) -> System.out.println(t));
		
		//Omit String
//		list.forEach((t) -> System.out.println(t));
		
		//The formal parameter () can be omitted
		list.forEach(t -> System.out.println(t));
	}
}

17.1.3 method reference and constructor reference

Lambda expressions are syntax that can simplify the assignment of variables and formal parameters of functional interfaces, while method references and constructor references are used to simplify lambda expressions.

1. When the Lambda expression satisfies some special conditions, it can also be simplified:

(1) The Lambda body has only one sentence and is completed by calling an existing method of an object / class

For example, the System.out object calls the println() method to complete the Lambda body

Math class, call the random() static method to complete the Lambda body

(2) And the formal parameter of Lambda expression is exactly the argument given to the method

For example: T - > system. Out. Println (T)

() - > math. Random() are all parameterless

2. Syntax format of method reference:

(1) Instance object name:: instance method

(2) Class name:: static method

(3) Class name:: instance method

explain:

  • :: it is called a method reference operator (there must be no space between the two, and it must be entered in English)

  • The formal parameter list of a Lambda expression is used in the Lambda body, either as an object calling a method or as an argument to a method.

  • There is no additional data in the whole Lambda body.

3. Constructor reference

(1) When the Lambda expression creates an object and satisfies the formal parameters of the Lambda expression, it is exactly the argument list of the constructor that creates the object.

(2) When the Lambda expression creates an array object and satisfies the Lambda expression parameters, the length of the array object is exactly given

4. Syntax format of constructor reference:

  • Class name:: new

  • Array type name:: new

Example code:

public class TestMethodReference {
	
	//This method is to imitate the code in HashMap to correct the length of the array you specify to the nth power of 2
	//createArray() creates an array with a length of 2 to the nth power
	public <R> R[] createArray(Function<Integer,R[]> fun,int length){
		int n = length - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        length = n < 0 ? 1 : n + 1;
		return fun.apply(length);
	}
	
	@Test
	public void test6(){
		/*
		 * Function Is a functional interface that can be assigned with Lambda expressions
		 * Function<T,R>Abstract method r apply (T)
		 * 
		 * createArray Function < Integer, R [] > fun is used in this method. Description T type has been specified as Integer
		 * explain
		 */
//		Function<Integer,String[]> f = (Integer len) -> new String[len];
		
		//Because the Lambda body is completed by creating an array object, and the formal parameters of the Lambda expression are exactly the length used to create the array
		//Omitted by constructor reference
		Function<Integer,String[]> f = String[]::new;
		String[] array = createArray(f, 10);
		
		System.out.println(array.length);//16
	}
	
	@Test
	public void test5(){
//		Supplier<String> s = () -> new String();// Provide an empty string object through the supply interface
		
		//Constructor reference
		Supplier<String> s = String::new;//Provide an empty string object through the supply interface
	}
	
	@Test
	public void test4(){
//		Runnable r = () -> System.out.println("hello lambda");
		Runnable r = System.out::println;//Print blank lines
		
		//The method reference cannot be simplified because the "hello lambda" cannot be omitted
	}
	
	@Test
	public void test3(){
		String[] arr = {"Hello","java","chai"};
//		Arrays.sort(arr, (s1,s2) -> s1.compareToIgnoreCase(s2));
		
		//Simplify with method reference
		/*
		 * Lambda The first formal parameter of the expression (for example, s1) is exactly the object calling the method, and the remaining formal parameters (for example, s2) are exactly the arguments given to the method
		 */
		Arrays.sort(arr, String::compareToIgnoreCase);
	}
	
	@Test
	public void test2(){
//		Stream<Double> stream = Stream.generate(() -> Math.random());
		
		//Simplify with method reference
		Stream<Double> stream = Stream.generate(Math::random);
	}
	
	@Test
	public void test1(){
		List<Integer> list = Arrays.asList(1,3,4,8,9);
		
		//list.forEach(t -> System.out.println(t));
		
		//Simplify again with method
		list.forEach(System.out::println);
	}
}

17.2 StreamAPI

There are two of the most important changes in Java 8. The first is a Lambda expression; The other is the Stream API.

The Stream API (Java. Util. Stream) introduces a true functional programming style into Java. This is the best supplement to the Java class library so far, because the Stream API can greatly improve the productivity of Java programmers and enable programmers to write efficient, clean and concise code.

Stream is a key abstract concept for processing collections in Java 8. It can specify the operations you want to perform on collections, and can perform very complex operations such as finding, filtering and mapping data. Using the Stream API to operate on the collection data is similar to a database query executed using SQL. You can also use the Stream API to perform operations in parallel. In short, the Stream API provides an efficient and easy-to-use way to process data.

Stream is a data channel used to manipulate the sequence of elements generated by data sources (sets, arrays, etc.). "Set is about data and is responsible for storing data. Stream is about calculation and is responsible for processing data!"

be careful:

① Stream itself does not store elements.

② Stream does not change the source object. Each process returns a new stream that holds the result.

③ Stream operations are deferred. This means that they wait until the results are needed.

There are three steps for Stream operation:

1 - create a Stream: obtain a Stream from a data source (such as a collection or array)

2 - intermediate operation: the intermediate operation is an operation chain that processes the data of the data source n times, but it will not be really executed before the operation is terminated.

3 - termination operation: once the termination operation is executed, the intermediate operation chain will be executed, the final result will be generated and the Stream will be ended.

[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-rltz2O7z-1631456884059)(imgs/1560769396655.png)]

17.2.1 creating a Stream

1. Method 1 of creating Stream: through collection

The Collection interface in Java 8 is extended to provide two methods to obtain streams:

  • Public default stream(): returns a sequential stream

  • public default Stream parallelStream(): returns a parallel stream

2. Method 2 of creating Stream: through array

The static method stream() of Arrays in Java 8 can obtain the array stream:

  • Public static stream (t [] array): returns a stream

Overloaded form, which can handle arrays of corresponding basic types:

  • Public static intstream (int [] array): returns an integer data stream

  • public static LongStream stream(long[] array): returns a long integer data stream

  • Public static double stream (double [] array): returns a floating-point data stream

3. Method 3 of creating a Stream: through of()

You can call the static method of() of the Stream class to create a Stream by displaying the value. It can receive any number of parameters.

  • public static Stream of(T... values): returns a sequential stream

4. Create Stream mode 4: create infinite Stream

You can create an infinite stream using the static methods Stream.iterate() and Stream.generate().

  • public static Stream iterate(final T seed, final UnaryOperator f): returns an infinite stream

  • Public static stream generate (suppliers): returns an infinite stream

17.2.2 intermediate operation

Multiple intermediate operations can be connected to form a pipeline. Unless the termination operation is triggered on the pipeline, the intermediate operation will not perform any processing! When the operation is terminated, it is processed all at once, which is called "lazy evaluation".

methodDescription
filter(Predicate p)Receive Lambda and exclude some elements from the stream
distinct()Filter to remove duplicate elements through equals() of the elements generated by the flow
limit(long maxSize)Truncate the stream so that its elements do not exceed the given number
skip(long n)Skip elements and return a stream that throws away the first n elements. If there are less than n elements in the stream, an empty stream is returned. Complementary to limit(n)
peek(Consumer action)Receive Lambda and perform Lambda volume operation for each data in the stream
sorted()Generate a new stream, which is sorted in natural order
sorted(Comparator com)Generates a new stream, sorted in comparator order
map(Function f)Receive a function as an argument, which is applied to each element and mapped to a new element.
mapToDouble(ToDoubleFunction f)Receive a function as an argument, which will be applied to each element to generate a new DoubleStream.
mapToInt(ToIntFunction f)Receive a function as a parameter, which will be applied to each element to generate a new IntStream.
mapToLong(ToLongFunction f)Receive a function as an argument, which will be applied to each element to generate a new LongStream.
flatMap(Function f)Take a function as a parameter, replace each value in the stream with another stream, and then connect all streams into one stream

17.2.3 termination operation

The terminal operation generates results from the pipeline of the stream. The result can be any value that is not a stream, such as List, Integer, or even void. The stream cannot be used again after it has been terminated.

methoddescribe
boolean allMatch(Predicate p)Check that all elements match
boolean anyMatch(Predicate p)Check to see if at least one element matches
boolean noneMatch(Predicate p)Check that no elements match
Optional findFirst()Returns the first element
Optional findAny()Returns any element in the current stream
long count()Returns the total number of elements in the stream
Optional max(Comparator c)Returns the maximum value in the stream
Optional min(Comparator c)Returns the minimum value in the stream
void forEach(Consumer c)iteration
T reduce(T iden, BinaryOperator b)You can combine the elements in the flow repeatedly to get a value. Return T
U reduce(BinaryOperator b)You can combine the elements in the flow repeatedly to get a value. Return to Optional
R collect(Collector c)Convert the Stream to another form. Receive the implementation of a Collector interface, which is used to summarize the elements in the Stream

The implementation of the method in the Collector interface determines how to perform collection operations (such as collecting List, Set and Map). In addition, the Collectors utility class provides many static methods to easily create common Collector instances.

17.3 Optional class

By far, the notorious null pointer exception is the most common cause of failure in Java applications. Previously, in order to solve the null pointer exception, Google's famous guava project introduced the Optional class. Guava prevents code pollution by checking null values, which encourages programmers to write cleaner code. Inspired by Google Guava, the Optional class has become part of the Java 8 class library.

Optional is actually a container: it can hold the value of type T, or just null. Optional provides many useful methods so that we don't need to explicitly detect null values.

Its API:

1. How do I create an Optional object? Or how to use Optional to load value objects or null values

(1) static Optional empty(): used to create an empty Optional

(2) Static option of (t value): used to create a non empty option

(3) static Optional ofNullable(T value): used to create an Optional that may or may not be empty

2. How to remove the wrapped object from the Optional container?

(1) T get(): Optional container must be non empty

It is safe to use T get() and of(T value)

(2)T orElse(T other) :

orElse(T other) is used with ofNullable(T value),

If the Optional container is not empty, the wrapped value is returned. If it is empty, the default value (spare tire) specified by orElse(T other)other is used instead

(3)T orElseGet(Supplier<? extends T> other) :

If the Optional container is not empty, the wrapped value is returned. If it is empty, the value provided by the Lambda expression of the Supplier interface is used instead

(4) T orElseThrow(Supplier<? extends X> exceptionSupplier)

If the Optional container is not empty, the wrapped value will be returned. If it is empty, the exception type you specified will be thrown instead of the original NoSuchElementException

3. Other methods

(1) boolean isPresent(): judge whether the value in the Optional container exists

(2)void ifPresent(Consumer<? super T> consumer) :

Judge whether the value in the Optional container exists. If it exists, perform the operation specified by the Consumer. If it does not exist, do not perform the operation

(3) Optional map(Function<? super T,? extends U> mapper)

Judge whether the value in the Optional container exists. If it exists, perform the operation specified by the Function interface. If it does not exist, do not perform the operation

Chapter 18 design mode

18.1 formwork design mode (understand)

1. When solving a problem or completing a function, the algorithm structure (steps) of the main body is determined, but one or several small steps are uncertain. When users (subclasses) need to determine, the template design pattern can be used

2. Example code: calculate the running time of any section of code

//template class
public abstract class CalTime{
    public long getTime(){
        //1. Get start time
        long start =  System.currentTimeMills();
        
        //2. Run xx Code: This is uncertain
        doWork();
        
        //3. Get end time
        long end =  System.currentTimeMills();
        
        //4. Calculate time difference
        return end - start;
    }
    
    protected abstract void doWork();
}

Use template class:

public class MyCalTime extends CalTime{
    protected void doWork(){
        //... code that needs to calculate run time
    }
}

Test class

public class Test{
    public static void main(String[] args){
        MyCalTime my = new MyCalTime();
        System.out.println("Run time:" + my.getTime());
    }
}

18.2 single case design mode

Single example: there is only one object of a certain type in the whole system.

1. Hungry Han style

(1) Enumerative

public enum Single{
    INSTANCE
}

(2) Form II

public class Single{
    public static final Single INSTANCE = new Single();
    private Single(){
        
    }
}

(3) Form III

public class Single{
    private static final Single INSTANCE = new Single();
    private Single(){
        
    }
    public static Single getInstance(){
        return INSTANCE;
    }
}

2. Lazy style

(1) Internal class form

public class Single{
    private Single(){}
    
    private static class Inner{
        static final Single INSTANCE = new Single();
    }
    
    public static Single getInstance(){
        return Inner.INSTANCE;
    }
    
}

(2) Form II

public class Single{
    private static Single instance;
    private Single(){}
    
    public static Single getInstance(){
        if(instance == null){
            synchronized(Single.class){
                if(instance == null){
                    instance = new Single();
                }
            }
        }
        return instance;
    }
}

18.3 factory design mode

Problem to be solved: separate the creator of the object from the user of the object, and unify the creation of the object into one place (factory)

18.3.1 simple factory mode

Example code:

interface Car{
	void run();
}

class BMW implements Car{

	@Override
	public void run() {
		System.out.println("Make you cry in a BMW");
	}
	
}
class Benz implements Car{
	@Override
	public void run() {
		System.out.println("Mercedes makes you sit on the hood and cry");
	}
}

class SimpleFactory{
	public static Car getCar(String type){
		switch(type){
		case "bmw":
			return new BMW();
		case "Benz":
			return new Benz();
		}
		return null;
	}
}

If there is a factory class with reflection: simple factory mode, it can be optimized:

class SimpleFactoryPlus{
	/*
	 * type: Full name of the type
	 */
	public static Car getCar(String type) throws Exception{
		//Gets the Class object of the implementation Class of the Car
		Class clazz = Class.forName(type);
		//Create an instance object of the Car's implementation class
		Object obj = clazz.newInstance();
		//Forcibly convert the class and return the instance object of the car
		return (Car)obj;
	}
}

18.3.2 factory method mode

Example code:

interface Car{
	void run();
}

class BMW implements Car{

	@Override
	public void run() {
		System.out.println("Make you cry in a BMW");
	}
	
}
class Benz implements Car{
	@Override
	public void run() {
		System.out.println("Mercedes makes you sit on the hood and cry");
	}
}

//Plant common interface
interface Factory{
	Car getCar();
}
class BMWFactory implements Factory{

	@Override
	public BMW getCar() {
		return new BMW();
	}
	
}
class BenzFactory implements Factory{

	@Override
	public Benz getCar() {
		return new Benz();
	}
	
}

18.4 static proxy mode

A static proxy class can only proxy for one topic interface.

If the topic interface is different and the proxy works the same, you also need to write two proxy classes.

Example code:

public class TestProxy {
	@Test
	public void test1(){
		TimeProxy tp = new TimeProxy(new GoodsDAO());
		tp.add();
	}
	@Test
	public void test2(){
		TimeProxy tp = new TimeProxy(new UserDAO());
		tp.add();
	}
}
//Topic interface
interface DAO{
	void add();
}
//Proxy class
class GoodsDAO implements DAO{
	public void add(){
		System.out.println("Addition of goods");
	}
}
class UserDAO implements DAO{
	public void add(){
		System.out.println("Addition of users");
	}
}
//proxy class
class TimeProxy implements DAO{
	private DAO target;//target represents the surrogate object

	public TimeProxy(DAO target) {
		super();
		this.target = target;
	}

	@Override
	public void add() {
		long start = System.currentTimeMillis();
		target.add();//Return the core business logic to the agent
		long end = System.currentTimeMillis();
		System.out.println("Time difference:" +(end-start));
	}
	
}

18.5 dynamic agent

Steps:

(1) Topic interface

(2) Proxy class

(3) Agent work processor for dynamic agent

It is required that the java.lang.reflect.InvocationHandler interface must be implemented, which is overridden

Object invoke(Object proxy, Method method,Object[] args)

(4) Create proxy class object

Static method of type java.lang.reflect.Proxy

newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h )

(5) Call the method to use

Example code:

 /* Steps:
 * 1,Write a topic interface (like a static proxy)
 * 2,Write the proxy class (same as static proxy)
 * 3,Write an agent work processor: that is, what does the agent class do for the proxy class
 * Requirement: InvocationHandler must be implemented. Override
 *   Object invoke(Object proxy, Method method, Object[] args)
 *   First parameter: proxy class object
 *   The second parameter: the method to be executed by the proxy class and the proxy class
 *   The third parameter: the list of arguments to execute the method
 *   
 *   This invoke method is not called by the programmer. It is called automatically when the corresponding proxy method is executed by the class object
 *   
 * 4,Create proxy classes and their objects
 *   Need: Proxy: provides static methods for creating dynamic Proxy classes and instances. It is also a superclass of all dynamic Proxy classes created by these methods.
 *   
 *    static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 
 *    The first parameter: the class loader of the proxy class. We want the proxy class and the proxy class to use the same class loader
 *    The second parameter: the interfaces implemented by the proxy class
 *    Third parameter: proxy worker object
 *    
 * 5,Call the proxied method   
 */
public class TestProxy2 {
	@Test
	public void test2(){
		//Proxied object
		YongHuDAO sd = new YongHuDAO();
		
		ClassLoader loader = sd.getClass().getClassLoader();//Class loader object of the delegate
		Class<?>[] interfaces = sd.getClass().getInterfaces();//Interfaces implemented by the agent
		TimeInvocationHandler h = new TimeInvocationHandler(sd);//Proxy work processor object
		
		//Create proxy classes and their objects
		//Proxy is the object of proxy class, which is automatically compiled by the compiler
		Object proxy = Proxy.newProxyInstance(loader, interfaces, h);
		
		//The purpose of forced conversion here is to call the methods of adding, deleting, modifying and querying
		//Why is the forced conversion successful here? Because the proxy class and the proxy class implement the same topic interface
		DBDAO d = (DBDAO) proxy;
		d.add();
		d.update();
		d.delete();
		d.select();
	}
	
	@Test
	public void test1(){
		//Proxied object
		ShangPinDAO sd = new ShangPinDAO();
		
		ClassLoader loader = sd.getClass().getClassLoader();
		Class<?>[] interfaces = sd.getClass().getInterfaces();
		TimeInvocationHandler h = new TimeInvocationHandler(sd);
		
		//Create proxy classes and their objects
		//Proxy is the object of proxy class, which is automatically compiled by the compiler
		Object proxy = Proxy.newProxyInstance(loader, interfaces, h);
		
		//The purpose of forced conversion here is to call the methods of adding, deleting, modifying and querying
		//Why is the forced conversion successful here? Because the proxy class and the proxy class implement the same topic interface
		DBDAO d = (DBDAO) proxy;
		d.add();
		d.update();
		d.delete();
		d.select();
	}
}
//Agent work processor
class TimeInvocationHandler implements InvocationHandler{
	private Object target;//Proxied object

	public TimeInvocationHandler(Object target) {
		super();
		this.target = target;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		long start = System.currentTimeMillis();
		
		//The xx method of the proxied object is called
		/*
		 * No reflection: proxied object. xx method (args argument list)
		 * With reflection: method object. Invoke (proxied object, args argument list)
		 */
		Object returnValue = method.invoke(target, args);
		
		long end = System.currentTimeMillis();
		System.out.println(method.getName() + "Method run time:" + (end-start));
		
		return returnValue;
	}
	
}


//Topic interface
interface DBDAO{
	void add();
	void update();
	void delete();
	void select();
}
//Proxied class 1
class ShangPinDAO implements DBDAO{
	public void add(){
		System.out.println("Add item");
	}

	@Override
	public void update() {
		System.out.println("Modify product");
	}

	@Override
	public void delete() {
		System.out.println("Delete item");
	}

	@Override
	public void select() {
		System.out.println("Query commodity");
	}
}
//Proxied class 2
class YongHuDAO implements DBDAO{
	public void add(){
		System.out.println("Add user");
	}

	@Override
	public void update() {
		System.out.println("Modify user");
	}

	@Override
	public void delete() {
		System.out.println("delete user");
	}

	@Override
	public void select() {
		System.out.println("Query user");
	}
}

Posted by webhead on Sun, 12 Sep 2021 16:53:38 -0700