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 category | This package | Subclasses of other packages | Any 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 number | Basic data type | Packaging |
---|---|---|
1 | byte | Byte |
2 | short | Short |
3 | int | Integer |
4 | long | Long |
5 | float | Float |
6 | double | Double |
7 | char | Character |
8 | boolean | Boolean |
9 | void | Void |
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
Packaging | Cache object |
---|---|
Byte | -128~127 |
Short | -128~127 |
Integer | -128~127 |
Long | -128~127 |
Float | No, |
Double | No, |
Character | 0~127 |
Boolean | true 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
method | describe |
---|---|
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
DataOutputStream | DataInputStream |
---|---|
writeInt(xx): output int type integer | int readInt() |
writeDouble(xx): output double type | double 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 string | String 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 name | Abstract method | describe |
---|---|---|
Consumer | void 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 |
DoubleConsumer | void accept(double value) | Receive a double value |
IntConsumer | void accept(int value) | Receive an int value |
LongConsumer | void accept(long value) | Receive a long value |
ObjDoubleConsumer | void accept(T t, double value) | Receive an object and a double value |
ObjIntConsumer | void accept(T t, int value) | Receive an object and an int value |
ObjLongConsumer | void 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 name | Abstract method | describe |
---|---|---|
Supplier | T get() | Returns an object |
BooleanSupplier | boolean getAsBoolean() | Returns a boolean value |
DoubleSupplier | double getAsDouble() | Returns a double value |
IntSupplier | int getAsInt() | Returns an int value |
LongSupplier | long 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 name | Abstract method | describe |
---|---|---|
Predicate | boolean test(T t) | Receive an object |
BiPredicate<T,U> | boolean test(T t, U u) | Receive two objects |
DoublePredicate | boolean test(double value) | Receive a double value |
IntPredicate | boolean test(int value) | Receive an int value |
LongPredicate | boolean test(long value) | Receive a long value |
4. Functional interface
Abstract method features of this kind of interface: both parameters and return values
Interface name | Abstract method | describe |
---|---|---|
Function<T,R> | R apply(T t) | Receive a T-type object and return an R-type object result |
UnaryOperator | T apply(T t) | Receive a T-type object and return a T-type object result |
DoubleFunction | R apply(double value) | Receive a double value and return an R-type object |
IntFunction | R apply(int value) | Receive an int value and return an R-type object |
LongFunction | R apply(long value) | Receive a long value and return an R-type object |
ToDoubleFunction | double applyAsDouble(T value) | Receive a T-type object and return a double |
ToIntFunction | int applyAsInt(T value) | Receive a T-type object and return an int |
ToLongFunction | long applyAsLong(T value) | Receive a T-type object and return a long |
DoubleToIntFunction | int applyAsInt(double value) | Receive a double value and return an int result |
DoubleToLongFunction | long applyAsLong(double value) | Receive a double value and return a long result |
IntToDoubleFunction | double applyAsDouble(int value) | Receive an int value and return a double result |
IntToLongFunction | long applyAsLong(int value) | Receive an int value and return a long result |
LongToDoubleFunction | double applyAsDouble(long value) | Receive a long value and return a double result |
LongToIntFunction | int applyAsInt(long value) | Receive a long value and return an int result |
DoubleUnaryOperator | double applyAsDouble(double operand) | Receive a double value and return a double |
IntUnaryOperator | int applyAsInt(int operand) | Receive an int value and return an int result |
LongUnaryOperator | long 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 |
BinaryOperator | T 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 |
DoubleBinaryOperator | double applyAsDouble(double left, double right) | Receive two double values and return a double result |
IntBinaryOperator | int applyAsInt(int left, int right) | Receive two int values and return an int result |
LongBinaryOperator | long 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".
method | Description |
---|---|
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.
method | describe |
---|---|
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"); } }