Java
Fundamentals of Java language
Java Language Overview
Basic knowledge
Software: a set of computer data and instructions organized in a specific order. It is divided into system software and application software
- System software: Windows Linux macOS Unix Android iOS
- Application software: Word PowerPoint drawing board
Human computer interaction mode: graphical interface vs command line mode
Application = algorithm + data structure
Common DOS commands:
dir: List the files and folders under the money directory md: Create directory rd: Delete directory cd: Enter the specified directory cd..: Return to the previous directory cd/: Back to root del: Delete file exit: sign out DOS command line
Development history of computer language
- First generation: machine language
- Second generation: assembly language
- Third generation: high level language
- Process oriented: C, Pascal, Fortran
- Object oriented: Java, JS, Python, Scala
Java language version iteration
- In 1991, the development language of the Green project was originally named Oak
- In 1994, the development team realized that Oak was very suitable for the Internet
- In 1996, JDK 1.0 was released, and about 83000 web pages were made using Java technology
- In 1997, JDK 1.1 was released and the JavaOne conference was held, which was the largest conference of its kind in the world at that time
- In 1998, JDK 1.2 was released, and the enterprise platform J2EE was released in the same year
- In 1999, Java was divided into J2SE, J2EE and J2ME, and JSP/Servlet Technology was born
- In 2004, the milestone version JDK 1.5 was released. In order to highlight the importance of this version, it was renamed JDK 5.0
- In 2005, J2SE - > javase, J2EE - > JavaEE, J2ME - > javame
- In 2009, Oracle acquired SUN at a transaction price of $7.4 billion
- In 2011, JDK 7.0 was released
- In 2014, JDK 8.0 was released, which is the most changed version since JDK 5.0
- In 2017, JDK 9.0 was released to maximize modularity
- In March 2018, JDK 10.0 was released, also known as 18.3
- In September 2018, JDK 11.0 was released, also known as 18.9
Application fields of Java language
- Java Web Development: background development
- Big data development
- Android Application Development: client development
Characteristics of Java language
-
object-oriented
- Two features: class and object
- Three characteristics: encapsulation, inheritance and polymorphism
-
Robustness
-
Removed the pointer in C language
-
Automatic garbage collection -- > memory overflow and memory leak will still occur
-
Cross platform: write once, run anywhere
Credit: JVM
-
Relationship between JDK, JRE and JVM
JDK download, installation and configuration of path environment variables
Why configure the path environment variable?
Path environment variable: the path to be searched when the Windows reinstall system executes the command
Why to configure path: I hope Java development tools can execute successfully under the file path of any file
How to configure
https://blog.csdn.net/weixin_43344151/article/details/118917382
Visit the official website and download the corresponding version
https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html
install
Note: the path to install the software cannot contain Chinese or spaces
Configure environment variables
This computer -- > right click "properties" -- > click "advanced system settings" -- > click "environment variables"
Double click PATH in the system variable
Click OK in turn
Open cmd window
Run java, javac and java -version, and the following screen appears, indicating that the installation and configuration are successful
Development experience - HelloWorld
to write
Create a java source file: HelloWorld.java
public class HelloWorld{ public static void main(String[] args){ System.out.println("Hello, World!"); } }
compile
javac HelloWorld.java
function
java HelloWorld
Common problem solving
Summarize the first procedure
-
The process of writing, compiling and running Java programs
Write: save the written java code in a source file ending in. Java
Compilation: use javac.exe command to compile our java source file. Format: javac source file name. Java
Run: use the java.exe command to explain and run our bytecode file. Format: Java class name -
Multiple classes can be declared in a Java source file, but at most one class can be declared public, and the class name of the class declared public must be the same as the source file name
-
The entry of the program is the main() method, and the format is fixed
-
Output statement:
System.out.println(): output data first, and then wrap
System.out.print(): output data only -
Each line of execution statement is executed in; end
-
Compilation process: after compilation, one or more bytecode files will be generated. The file name of the bytecode file is the same as the class name in the Java source file
Note: Comment
- Classification:
- Single line note://
- Single line comment: / **/
- Document comments: / * **/
- effect:
- Explain the written program, enhance readability, facilitate yourself and others
- Debug the written code
- characteristic:
- Single line comments and multi line comments. The annotated content does not participate in the compilation. In other words, the bytecode file at the end of. class generated after compilation does not contain the annotated content
- The content annotated by the document comments can be parsed by the tool javadoc provided by JDK to generate a set of description documents of the program in the form of web files
- Multiline comments cannot be nested
Java API documentation
API: application programming interface
Habit: the class libraries provided by the language are called API s
API document: a description of how to use the provided class library
Good programming style
-
Correct annotation and annotation style
- Use document annotations to annotate the entire class or method.
- If a step in the annotation method, use a single or multiple line annotation.
-
Correct indents and blanks
- Use a tab operation to indent
- Operator is habitually added with a space on both sides. For example: 2 + 4 * 5.
-
Block style
-
The Java API source code selects the end of line style
-
development tool
- Text editing tools
- Notepad
- UltraEdit
- EditPlus
- Notepad
- TextPad
- Java IDE
- JBuilder
- NetBeans
- Eclipse
- MyEclipse
- IDEA
Basic grammar
Keywords and identifiers
keyword
Definition: a string (word) with special meaning given by the Java language for special purposes
Features: all the letters written in the keyword are lowercase
Specific keywords:
Reserved word
Definition: the existing Java version has not been used, but later versions may be used as keywords.
What are the reserved words: goto and const
Note: avoid using these reserved words when naming your own identifiers
identifier
Definition: any place where you can name yourself is called an identifier
Structures involved: package name, class name, method name, variable name, interface name and constant name
Rule: (must be followed, otherwise, the compilation fails)
- It consists of 26 English letters in case, 0-9_ Or $composition
- A number cannot begin.
- Keywords and reserved words cannot be used, but they can be included.
- Java is strictly case sensitive and has unlimited length.
- The identifier cannot contain spaces.
Specification: (it may not be complied with, which will not affect the compilation and operation, but it is required to be complied with
- Package name: all letters are lowercase when composed of multiple words: xxxyyyzzz z
- Class name and interface name: when composed of multiple words, the first letter of all words is capitalized: xxxyyyzz
- Variable name and method name: when composed of multiple words, the first word is lowercase, and the first letter of each word is capitalized at the beginning of the second word: xxxyyyzz
- Constant name: all letters are capitalized. When there are multiple words, each word is underlined: XXX_YYY_ZZZ
Note:
- When naming, in order to improve the reading ability, try to be meaningful, "see the name and know the meaning".
Clean Code
-
introduce
- Naming can be seen everywhere in software. We name variables, functions, parameters, classes, and packages. We name the source code and the directory where the source code is located.
- With so much naming to do, you might as well do it well. Here are some simple rules for choosing a good name.
-
The name is worthy of the name
- Variable names are too arbitrary. haha, list1, ok, theList are meaningless
-
Avoid misleading
- Including List, import, java and other class names, keywords or special words;
- Letter o and number 0, letter l and number 1, etc
- Beware of using names that differ less. For example, XYZControllerForEfficientHandlingOfStrings and XYZControllerForEfficientStorageOfStrings
-
Make meaningful distinctions
- Negative textbook, variable names: a1, a2, a3
- Avoid redundancy. Avoid variables, tables and strings in table fields. Avoid nameString. Just name to know the string type
- Another example: two classes are defined: Customer class and CustomerObject class. How to distinguish them?
- Three methods are defined: getActiveAccount(), getActiveAccounts(), getActiveAccountInfo(). How to distinguish them?
-
Use a readable name
- Don't use the words you put together, such as xsxm (student's name); Genymdhms (generation date, year, month, day, hour, minute, second)
- The so-called hump naming method, try to use complete words
-
Use a searchable name
- For some constants, it is better not to use numbers directly, but to specify a variable name, which can be easily searched
- For example: find MAX_CLASSES_PER_STUDENT is easy, but it's troublesome to find the number 7.
-
Avoid coding
- Hungarian Markedness
- That is, the variable name indicates that the variable data type starts with a lowercase letter. For example, the prefix sz of szCmdLine means "zero terminated string".
- Member prefix
- Avoid using prefixes, but a better one in Android likes to use m to represent private and so on. I feel better
- Interface and Implementation
- The author doesn't like to start the interface with I, and the implementation wants to just add Impl later
- Hungarian Markedness
-
Avoid thinking mapping
- For example, single letter names are traditionally used as loop counters. So don't name some non counter variables i, j, k, etc
-
Class name
-
Class and object names should be nouns and noun phrases. Such as Customer, WikiPage, Account and AddressParser. Avoid using class names such as Data or Info.
-
Can't make verbs. For example: Manage, Process
-
-
Method name
- The method name should be a verb or verb phrase. Such as postPayment, deletePage or save
-
Don't be cute
-
Some variables are called haha and banana
-
Don't use eatMyShorts() for abort()
-
-
Each concept corresponds to a word
-
There are controllers and managers in the project at the same time. Why not use one of them uniformly?
-
For programmers who will use your code, a consistent nomenclature is a blessing in heaven.
-
-
Don't pun
Sometimes add may not be appropriate, such as insert and append. Add means the complete newly added meaning. -
Use solution domain name
-
Programmers look at the code, so try to use those computer science terms, algorithm names, pattern names and mathematical terms,
-
Naming according to the area covered by the problem is not smart.
-
-
Use names derived from the problem area
-
If you can't name the task at hand in terms familiar to programmers, use a name from the problem area.
-
At least, programmers responsible for maintaining code can consult domain experts.
-
-
Add meaningful context
- You can put related variables into a class and use this class to indicate the context.
-
Don't add useless context
- There is no need to have the abbreviation of the item in the name. For example, there is a project called "Gas Station Deluxe",
- Adding a GSD prefix to each class is not a good strategy.
-
Last words
- The most difficult part of choosing a good name is that it requires good description skills and common cultural background
Use of variables
Classification of variables
Classification by data type
detailed description:
- Integer: byte (1 byte) short (2 bytes) int (4 bytes) long (8 bytes)
- byte range - 128 ~ 127
- Declare a long variable, which must end with "L" or "L"
- In general, int is used when defining integer variables
- The default type of an integer constant is int
- Floating point type: float (4 bytes) double (8 bytes)
- A floating point type represents a numeric value with a decimal point
- float indicates that the range of values is larger than long
- When defining a float type variable, the variable should end with "F" or "F"
- In general, double is used when defining floating-point variables
- Floating point constant. The default type is double
- Character type: char (2 bytes)
- A pair of '' is usually used to define char type variables, and only one character can be written inside
- Representation
- Declare a character
- Escape character
- Use Unicode values directly to represent character constants
- boolean: boolean
- You can only take one of two values: true or false
- It is usually used in condition judgment and loop structure
Classification by declared location
Defines the format of the variable
Data type variable name = variable value;
perhaps
Data type variable name;
Variable name = variable value;
Notes on variable use
-
Variables must be declared before use
-
Variables are defined within their scope. It is valid within the scope. In other words, out of scope, it fails
-
Two variables with the same name cannot be described in the same scope
Operation rules between variables of basic data type
Basic data types involved
7 types except boolean type
Automatic type conversion (involving only 7 basic data types)
When a variable of a data type with a small capacity is calculated with a variable of a data type with a large capacity, the result is automatically promoted to a data type with a large capacity
byte ,short ,char –> int –> long –> float –> double
In particular, when byte, short and char variables are operated, the result is int
Note: the capacity at this time refers to the size of the range of numbers. For example, the capacity of float should be greater than that of long
Cast type conversion (only involving 7 basic data types)
Inverse procedure of automatic type promotion operation
- Mandatory character required: ()
- Note: cast may result in loss of precision
Operation between String and 8 basic data types
- String is a reference data type, which is translated into: string
- Use a pair of '' when declaring a variable of type String
- String can operate with 8 basic data types, and the operation can only be connection operation:+
- The result of the operation is still of type String
Avoid:
// Compilation error String s = 123; // Compilation error int i = (int)"123";
Base system
Hexadecimal and representation involved in programming
- Binary: 0,1, full 2 into 1. Start with 0b or 0b.
- Decimal: 0-9, full 10 into 1.
- Octal: 0-7, full 8 into 1. It starts with the number 0.
- **Hexadecimal (hex): * * 0-9 and A-F, full 16 into 1. It starts with 0x or 0x. A-F here is not case sensitive. For example: 0x21AF +1= 0X21B0
Instructions for binary
- Computer bottom storage mode: all numbers exist in binary form at the bottom of the computer
- Storage mode of binary data: all values, whether positive or negative, are stored in the form of complement at the bottom
- Description of original code, inverse code and complement code
- Positive number
- Three in one
- negative
- Original code: directly change a value into binary, and the highest bit is the sign bit
- Inverse code: inverse the original code by bit, but the highest bit (symbol bit) is determined as 1
- Complement: its inverse code plus 1
- Positive number
Conversion between hexadecimals
operator
Arithmetic operator
code
/* One of the operators: arithmetic operator + - + - * / % (Front) + + + + + (rear) (front) --- (rear)+ */ public class AriTest { public static void main(String[] args) { // Division:/ int num1 = 12; int num2 = 5; int result1 = num1 / num2; // 2 System.out.println(result1); int result2 = num1 / num2 * num2; // 10 System.out.println(result1); double result3 = num1 / num2; // 2.0 System.out.println(result3); // 2.0 double result4 = num1 / num2 + 0.0; // 2.4 double result5 = num1 / (num2 + 0.0); // 2.4 double result6 = (double) num1 + num2; System.out.println(result5); System.out.println(result6); // Remainder:% // The sign of the result number is the same as the modulus // In development, we often use% to judge whether it can be eliminated int m1 = 12; int n1 = 5; System.out.println("m1 % n1 = " + m1 % n1); int m2 = -12; int n2 = 5; System.out.println("m1 % n1 = " + m2 % n2); int m3 = 12; int n3 = -5; System.out.println("m1 % n1 = " + m3 % n3); int m4 = -12; int n4 = -5; System.out.println("m1 % n1 = " + m4 % n4); // (front) + +: increase by 1 before operation // ++(later): operation first, and then increase by 1 int a1 = 10; int b1 = ++a1; int a2 = 10; int b2 = a2++; System.out.println("a1 = " + a1 + ", b1 = " + b1); System.out.println("a2 = " + a2 + ", b2 = " + b2); int a3 = 10; a3++; int b3 = a3; // Note: self incrementing 1 does not change the data type of its own variable short s1 = 10; s1++; System.out.println(s1); byte b = 127; b++; System.out.println("b = " + b); // (front) --: subtract 1 first and then operate // --(later): first operation, then self subtraction 1 int a4 = 10; int b4 = --a4; System.out.println("a4 = " + a4 + ", b4 = " + b4); int a5 = 10; int b5 = --a5; System.out.println("a5 = " + a5 + ", b5 = " + b5); } }
Special note
-
(before) + +: Auto increment before operation
(later) + +: operation first, and then auto increment**
-
(front) –: self subtraction before operation
(later) –: operation first, then self subtraction
-
Connector: + can only be used between String and other data type variables.
Assignment Operators
code
/* * Operator 2: assignment operator * = += -= *= /= %= */ public class SetValueTest { public static void main(String[] args) { // =: assignment symbol int i1 = 10; int j1 = 10; int i2, j2; // continuous assignment i2 = j2 = 10; int i3 = 10, j3 =10; int num1 = 10; num1 += 2; // num1 = num1 + 2; System.out.println(num1); int num2 = 10; num2 %= 5; // num2 = num2 % 5; System.out.println(num2); short s1 = 10; // Does not change the data type of the variable itself s1 += 2; System.out.println(s1); // In development, if you want the variable to realize the operation of + 2, how many methods are there? (premise: int num = 10) // Mode 1: num = num + 2; // Mode 2: num += 2; (recommended) // In development, if you want the variable to realize the operation of + 1, how many methods are there? (premise: int num = 10) // Mode 1: num = num + 1; // Mode 2: num += 1; // Mode 3: num + +; (recommended) // Exercise 1 int i = 1; i *= 0.1; // 0 System.out.println(i); i++; // 1 System.out.println(i); // Exercise 2 int m = 2; int n = 3; n *= m++; // 3 System.out.println("m = " + m); // 6 System.out.println("n = " + n); // Exercise 3 int n1 = 10; n1 += (n1++) + (++n1); // 32 System.out.println( n1); } }
Special note
- The result of the operation does not change the data type of the variable itself
Assignment Operators
code
/* * Operator 3: comparison operator * == != > < >= <= instanceof * Conclusion: * 1.The result of the comparison operator is a boolean type * 2.Distinguish between = = and= */ public class CompareTest { public static void main(String[] args) { int i = 10; int j = 20; System.out.println(i == j); // false System.out.println(i = j); // 20 boolean b1 = true; boolean b2 = false; System.out.println(b2 == b1); // false System.out.println(b2 = b1); // true } }
Special note
-
The results of comparison operators are of boolean type
-
>< > = < =: can only be used between numeric data types
-
== != : It can be used not only between numeric type data, but also between reference type variables
Account acct1 = new Account(1000); Account acct2 = new Account(2000); boolean b1 = acct1 == acct2; // Compare whether two accounts are the same Account boolean b2 = acct1 != acct2;
Logical operator
code
/** * Filename : LogicTest.java * Author : keke * Creation time : 8:06:50 PM October 30, 2021 * Description : Operator 4: logical operator * && & || | ! ^ * explain: * 1.Logical operators operate on variables of boolean type */ public class LogicTest { public static void main(String[] args) { // Distinguish & and&& // Similarities: // 1. The operation results of & and & & are the same // 2. When the left side of the symbol is true, both will perform the operation on the right side of the symbol // difference: // When the left side of the symbol is false, & will perform the operation on the right side of the symbol, & & will not perform the operation on the right side of the symbol // In development, recommended&& boolean b1 = true; b1 = false; int num1 = 10; if (b1 & (num1++ > 0)) { System.out.println("I'm in Beijing now"); }else { System.out.println("I'm in Nanjing now"); } System.out.println("num1 = " + num1); boolean b2 = true; b2 = false; int num2 = 10; if (b2 && (num2++ > 0)) { System.out.println("I'm in Beijing now"); }else { System.out.println("I'm in Nanjing now"); } System.out.println("num2 = " + num2); // Distinction: | and|| // Similarities: // 1. The operation results of | and | are the same // 2. When the left side of the symbol is false, both will perform the operation on the right side of the symbol // difference: // When the left side of the symbol is true, | will perform the operation on the right side of the symbol, | will not perform the operation on the right side of the symbol // In development, recommended|| boolean b3 = false; b3 = true; int num3 = 10; if (b3 | (num3++ > 0)) { System.out.println("I'm in Beijing now"); }else { System.out.println("I'm in Nanjing now"); } System.out.println("num3 = " + num3); boolean b4 = false; b4 = true; int num4 = 10; if (b4 || (num4++ > 0)) { System.out.println("I'm in Beijing now"); }else { System.out.println("I'm in Nanjing now"); } System.out.println("num4 = " + num4); } }
Special note
- Logical operators operate on variables of boolean type, and the operation result is boolean type
Bitwise Operators
code
/** * Filename : BitTest.java * Author : keke * Creation time : 8:42:10 PM October 30, 2021 * Description : Operator 5: bitwise operator (understanding) & | ~ ^ < > > > * Conclusion: * 1.Bitwise operators operate on integer data * 2.<<: Within a certain range, move 1 bit to the left, which is equivalent to multiplying by 2 * >>: Within a certain range, shifting 1 bit to the right is equivalent to dividing by 2 * * Interview question: the most efficient calculation 2 * 8? 2 < < 3 or 8 < < 1 */ public class BitTest { public static void main(String[] args) { int i = 21; i = -21; System.out.println("i << 2 = " + (i << 2)); System.out.println("i << 3 = " + (i << 3)); System.out.println("i << 26 = " + (i << 26)); System.out.println("i << 27 = " + (i << 27)); System.out.println("i >> 2 = " + (i >> 2)); int m = 12; int n = 5; System.out.println("m & n = " + (m & n)); System.out.println("m | n = " + (m | n)); System.out.println("m ^ n = " + (m ^ n)); // Exercise: exchanging the values of two variables int num1 = 10; int num2 = 20; System.out.println("num1 = " + num1 + ", num2 =" + num2); // Method 1: define temporary variables (recommended) int temp = num1; num1 = num2; num2 = temp; System.out.println("num1 = " + num1 + ", num2 =" + num2); // Mode 2: // Benefit: no need to define temporary variables // Disadvantages: // 1. The addition operation may be out of storage // 2. Limitations: it can only be applied to numerical types num1 = num1 + num2; num2 = num1 - num2; num1 = num1 - num2; System.out.println("num1 = " + num1 + ", num2 =" + num2); // Method 3: use bitwise operators num1 = num1 ^ num2; num2 = num1 ^ num2; num1 = num1 ^ num2; System.out.println("num1 = " + num1 + ", num2 =" + num2); } }
Interview question: the most efficient calculation 2 * 8?
Answer: 2 < < 3 or 8 < < 1
Special note
1. Bitwise operators operate on integer data
2. < <: within a certain range, every 1 bit to the left is equivalent to multiplying by 2
>>: within a certain range, each shift to the right by 1 bit is equivalent to dividing by 2
Ternary operator
code
/** * Filename : SanYuanTest.java * Author : keke * Creation time : 9:16:12 PM October 30, 2021 * Description : Operator 6: ternary operator * 1.Structure: (conditional expression)? Expression 1: expression 2 * 2.explain * 1.The result of the conditional expression is of type boolean * 2.Whether to execute expression 1 or expression 2 depends on whether the conditional expression is true or false * If the expression is true, expression 1 is executed * If the expression is false, expression 2 is executed * 3.Expression 1 and expression 2 are required to be consistent * 4.Ternary operators can be nested * 3.Where ternary operators can be used, they can be rewritten as if else * 4.If the program can use either ternary operator or if else, the ternary operator is preferred * Reason: simplicity and high execution efficiency */ public class SanYuanTest { public static void main(String[] args) { // Gets the larger value of two integers int m = 12; int n = 5; int max = m > n ? m : n; System.out.println(max); double num = m > n ? 2 : 1.0; // m > n ? 2: "n big"// Compilation error // Not recommended String maxStr = m > n ? "m large" : m == n ? "m and n equal" : "n large"; System.out.println(maxStr); // Gets the maximum of three numbers int n1 = 12; int n2 = 30; int n3 = -43; max = n1 > n2 ? n1 > n3 ? n1 : n3 : n2; System.out.println(max); if (m > n) { System.out.println(m); }else { System.out.println(n); } } }
Special note
-
The result of the conditional expression is of type boolean
-
Whether to execute expression 1 or expression 2 depends on whether the conditional expression is true or false
If the expression is true, expression 1 is executed
If the expression is false, expression 2 is executed
-
Expression 1 and expression 2 are required to be consistent
-
Ternary operators can be nested
Process control
Branching structure
if-else
Format:
-
Structure I
if(Conditional expression){ Execute expression }
-
Structure II
if(Conditional expression){ Execute expression 1 } else{ Execute expression 2 }
-
Structure III
if(Conditional expression){ Execute expression 1 }else if(Conditional expression){ Execute expression 2 } ... else{ Execute expression n }
explain:
- else structure is optional
- For conditional expressions:
- If multiple conditional expressions are mutually exclusive (or have no intersection), it doesn't matter which judgment and execution statement is declared under the above function
- If there is an intersection relationship between multiple conditional expressions, you need to consider which structure should be declared above according to the actual situation
- If there is an inclusive relationship between multiple conditional expressions. Usually, the declaration with small scope needs to be placed on the declaration with large scope. Otherwise, the declaration with small scope will not be executed
- If else structures can be nested with each other
- If the execution statement in the if else structure has only one line, this pair of braces can be omitted, but it is not recommended to omit
switch-case
Format:
switch(expression){ case Constant 1: Execute statement 1; // break; case Constant 2: Execute statement 2; // break; ... default: Execute statement n; // break; }
explain:
-
According to the values in the switch expression, the constants in each case are sequentially matched. Once the match is successful, it enters the corresponding case structure and calls its execution statement. After the execution statement is called, the execution statements in other case structures will continue to be executed downward until the break keyword or the end of this switch case structure is encountered
-
The break keyword can be used in the switch case structure, which means that once the keyword is executed, it will jump out of the switch case structure
-
The expression in the switch structure can only be one of the following six data types:
byte, short, char, int, enumeration type (new in JDK5.0), String (new in JDK7.0)
-
Only constants can be declared after case, and ranges cannot be declared
-
The break keyword is optional
-
Default is equivalent to else in the if else structure. The default structure is optional and the location is flexible
Cyclic structure
Four elements of circular structure
- Initialization condition
- The loop condition -- > is of type boolean
- Circulatory body
- Iterative condition
Note: usually, the end of the loop is because the loop condition returns false
for
Structure:
for(1;2;4){ 3 }
Execution procedure: 1 -- > 2 -- > 3 -- > 4 -- > 2 -- > 3 -- > 4 -- >... -- > 2
while
Structure:
1 while(2){ 3; 4; }
Execution procedure: 1 -- > 2 -- > 3 -- > 4 -- > 2 -- > 3 -- > 4 -- >... -- > 2
explain
- When writing a while loop, be careful not to lose the iteration condition. Once lost, it may lead to an endless loop
Summary of for and while loops:
-
During development, you will basically select from for and while to realize the loop structure
-
The for loop and the while loop are interchangeable
Difference: the scope of the initialization condition part of the for loop and the while loop is different
-
Avoid dead cycles
do-while
Structure:
1 do{ 3 4; }while(2);
Execution procedure: 1 -- > 3 -- > 4 -- > 2 -- > 3 -- > 4 -- > 2 -- >... -- > 2
explain:
- The do while loop executes the loop body at least once
- In development, use for and while more and do while less
"Infinite loop" structure
for(;;){ } while(true){ }
Summary: how to end a loop structure?
- When the loop condition is false
- In the loop body, execute break
Nested loop
-
Nested loop: declaring one loop structure A in the loop body of another loop structure B constitutes A nested loop
Outer circulation: circulation structure B
Inner circulation: circulation structure A
2. Description
- The inner loop structure is traversed once, which is only equivalent to the execution of the outer loop body once
- Suppose that the outer loop needs to be executed m times and the inner loop needs to be executed n times. At this time, the loop body of the inner loop has been executed m * n times
- The outer loop controls the number of rows and the inner loop controls the number of columns
Typical exercises
package day05; /** * Filename : ForForTest.java * Author : keke * Creation time : 1:47:24 PM, November 1, 2021 * Description : * Use of nested loops * 1.Nested loop: declaring one loop structure A in the loop body of another loop structure B constitutes A nested loop * 2.Outer circulation: circulation structure B * Inner circulation: circulation structure A * 3.explain * 1.The inner loop structure is traversed once, which is only equivalent to the execution of the outer loop body once * 2.Suppose that the outer loop needs to be executed m times and the inner loop needs to be executed n times. At this time, the loop body of the inner loop has been executed m * n times * 3.The outer loop controls the number of rows and the inner loop controls the number of columns */ public class ForForTest { public static void main(String[] args) { for(int i = 1; i <= 4; i++) { for(int j = 1; j <= 6; j++) { System.out.print('*'); } System.out.println(); } for(int i = 0; i < 5; i++) { for(int j = 0; j <= i; j++) { System.out.print('*'); } System.out.println(); } for(int i = 0; i < 5; i++) { for(int j = 1; j <= 5 - i; j++) { System.out.print('*'); } System.out.println(); } System.out.println("=============================================="); for(int i = 0; i < 5; i++) { for(int j = 0; j <= i; j++) { System.out.print('*'); } System.out.println(); } for(int i = 0; i < 5; i++) { for(int j = 2; j <= 5 - i; j++) { System.out.print('*'); } System.out.println(); } } }
package day05; /** * Filename : NineNineTable.java * Author : keke * Creation time : 2:31:29 PM November 1, 2021 * Description : * multiplication table */ public class NineNineTable { public static void main(String[] args) { for (int i = 1; i < 10; i++) { for(int j = 1; j <= i; j++) { System.out.print(j + " * " + i + " = " + i * j + "\t"); } System.out.println(); } } }
package day05; /** * Filename : PrimeNumberTest2.java * Author : keke * Creation time : 2:41:08 PM November 1, 2021 * Description : * 100 All prime numbers within * Prime number: a natural number that can only be divided by 1 and itself, also known as prime number -- > from 2 to the end of the number - 1, it cannot be divided by the number itself * Minimum prime number: 2 */ public class PrimeNumberTest2 { public static void main(String[] args) { // Gets the number of milliseconds of the current time long start = System.currentTimeMillis(); label: for(int i = 2; i <= 1000; i++) { for(int j = 2; j <= Math.sqrt(i); j++) { // i is divided by j if (i % j == 0) { continue label; } } // All that can perform this step are prime numbers System.out.print(i + " "); } System.out.println(); long end = System.currentTimeMillis(); System.out.println(end - start); } }
Supplement: measure the advantages and disadvantages of a function code:
- Correctness
- Readability
- Robustness
- High efficiency and low storage: time complexity and space complexity (measuring the quality of the algorithm)
Use of break and continue keywords
keyword | Scope of use | Functions used in circulation | Same point |
---|---|---|---|
break | switch-case | ||
Cyclic structure | End current cycle | Cannot declare an execution statement after a keyword | |
continue | Cyclic structure | End the current cycle | Cannot declare an execution statement after a keyword |
Use of tagged break and continue keywords
Use of Scanner class
package day04; import java.util.Scanner; /** * Filename : ScannerTest.java * Author : keke * Creation time : 3:23:13 PM October 31, 2021 * Description : * How to get different types of variables from the keyboard: you need to use the Scanner class * Specific implementation steps: * 1.Guide Package: import java.util.Scanner; * 2.Scanner Instantiation: Scanner scanner = new Scanner(System.in); * 3.Call the relevant methods of the Scanner class (next() and nextXxx()) to obtain variables of the specified type * be careful: * You need to input the value of the specified type according to the corresponding method. If the data type does not match the required type, an exception inputmismatch exception will be reported * Cause program termination */ public class ScannerTest { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Please enter your name:"); String name = scanner.next(); System.out.println(name); System.out.print("Please enter your age:"); int age = scanner.nextInt(); System.out.println(age); System.out.print("Please enter your weight:"); double weight = scanner.nextDouble(); System.out.println(weight); System.out.print("Single or not:"); boolean isLove = scanner.nextBoolean(); System.out.println(isLove); // For the acquisition of char type, Scanner does not provide relevant methods. Only one string can be obtained System.out.print("Please enter your gender:"); // Gets the character at position with index 0 char genderChar = scanner.next().charAt(0); System.out.println(genderChar); } }
array
Overview of arrays
- Array: an array is a collection of multiple data of the same type arranged in a certain order, named with a name, and managed uniformly by numbering.
- Array related concepts
- Array name
- element
- Corner mark, subscript, index
- Length of array: number of elements
-
Array features:
- Arrays are ordered
- Array is a variable of reference data type. The element of an array can be either a basic data type or a reference data type
- Creating an array object opens up a whole contiguous space in memory
- Once the length of the array is determined, it cannot be modified
-
Classification of arrays
- According to dimension: one-dimensional array, two-dimensional array
- According to the type of array elements: array of basic data type elements and array of reference data type elements
Data structure:
- Logical relationship between data: set, one-to-one, one to many, many to many
- Data storage structure
- Linear table: sequential table (such as array), linked list, stack and queue
- Tree structure: binary tree
- Graphic structure
Algorithm:
- Sorting algorithm
- search algorithm
One dimensional array
Declaration and initialization of one-dimensional array
// 1. Declaration and initialization of one-dimensional array int[] ids; // 1.1 static initialization: array initialization and array element assignment are performed simultaneously ids = new int[]{1001, 1002, 1003, 1004}; int dids = {1001, 1002, 1003, 1004}; // Type inference // 1.2 dynamic initialization: array initialization and array element assignment are performed separately String[] names = new String[5]; // Wrong writing // int[] arr1 = new int[]; // int[5] arr1 = new int[]; // int[] arr1 = new int[3]{1, 2, 3};
One dimensional array reference
Called by means of corner markers
// The subscript (or index) of the array starts from 0 and ends with the length of the array - 1 names[0] = "Wang Ming"; names[1] = "Wang He"; names[2] = "placed under house arrest"; names[3] = "Ju Long Zhang"; names[4] = "Wang Hongzhi";
Array properties
length
System.out.println(names.length); System.out.println(ids.length);
be careful:
- Once the array is initialized, its length is determined
- Once the array length is determined, it cannot be modified
Traversing a one-dimensional array
for(int i = 0; i < names.length; i++){ System.out.print(names[i] + " "); }
Default initialization value for one-dimensional array elements
- Array element is an integer: 0
- Array elements are floating point: 0.0
- Array elements are of character type: 0 '\ u0000'
- Array elements are Boolean: false
- Array element is a reference type: null
Memory parsing of arrays
Two dimensional array
How to understand 2D arrays
The array belongs to the reference data type, and the elements of the array can also be the reference data type. If the elements of a one-dimensional array are also of one-dimensional array type, the array is called a two-dimensional array
Declaration and initialization of two-dimensional array
// initiate static int[][] arr1 = new int[][] {{1, 2, 3}, {4, 5}, {6, 7, 8}}; // dynamic initialization String[][] arr2 = new String[3][2]; String[][] arr3 = new String[3][]; // Wrong situation // String[][] arr4 = new String[][3]; // correct int arr4[][] = new int[3][]; int[] arr5[] = new int[3][]; // Type inference int[] arr6[] = {{1, 2, 3}, {4, 5}, {6, 7, 8}};
Call of two-dimensional array
System.out.println(arr1[0][1]); System.out.println(arr2[1][1]); arr3[1] = new String[4]; System.out.println(arr3[1][0]);
Properties of a two-dimensional array
System.out.println(arr4.length); System.out.println(arr4[1].length);
Traversing a two-dimensional array
for (int i = 0; i < arr6.length; i++) { for (int j = 0; j < arr6[i].length; j++) { System.out.print(arr6[i][j] + " "); } System.out.println(); }
Default initialization value for array elements
Regulation: the two-dimensional array is divided into the elements of the outer array and the elements of the inner array
- For initialization method 1: for example: int[][] arr = new int[4][3];
-
The initialization value of the outer element is: address value
-
The initialization value of the inner element is: the same as that of the one-dimensional array
-
- For initialization mode 2: for example: int[][] arr = new int[4] [];
-
The initialization value of the outer element is: null
-
The initialization value of the inner element is: it cannot be defined, otherwise an error will be reported
-
Memory parsing of arrays
Common algorithms for arrays
Array creation and element assignment
Yang Hui triangle (two-dimensional array), loop number (two-dimensional array), 6 numbers, randomly generated between 1-30 and not repeated
For numeric arrays
Maximum, minimum, sum, average, etc
Assignment and copy of array
int[] array1, array2; array1 = new int[]{1, 2, 3, 4};
assignment
array1 = array2;
Understanding: assign the address value of the array saved by array1 to array2, so that array1 and array2 point to the same array entity in the heap space
copy
array2 = new int[array1.length]; for (int i = 0; i < array2.length; i++) { array2[i] = array1[i]; }
Understanding: through the new method, the array space is newly opened up for array2 in the heap space, and the element values in array1 array are assigned to array2 array one by one
Inversion of array elements
// Mode 1: for (int i = 0; i < arr1.length / 2; i++) { String temp = arr1[i]; arr1[i] = arr1[arr1.length - i - 1]; arr1[arr1.length - i - 1] = temp; } // Mode 2: for(int i = 0, j = arr1.length - 1; i < j; i++, j--) { String temp = arr1[i]; arr1[i] = arr1[j]; arr1[j] = temp; }
The lookup of the specified element in the array
Linear search
Implementation idea: compare and find data one by one through traversal
Applicability: it has universal applicability
binary search
Implementation idea: compare the intermediate value every time and search in half
Applicability: (premise: the array must be ordered)
/** * Half search method * @param arr Ordered array * @param dest Number to find */ public void binarySearch(int[] arr, int dest) { // Initial first index int head = 0; // Initial end index int end = arr.length - 1; boolean isFlag1 = true; while (head <= end) { int middle = (head + end) / 2; if (dest == arr[middle]) { System.out.println("The specified element was found at:" + middle); isFlag1 = false; break; }else if (arr[middle] > dest) { end = middle - 1; }else { head = middle + 1; } } if (isFlag1) { System.err.println("Unfortunately, I didn't find it"); } }
Array sorting algorithm
- Select sort
- Direct selection sort
- Heap sort
- Exchange sort
- Bubble sorting
- Quick sort
- Insert sort
- Direct insert sort
- Binary Insertion Sort
- Shell Sort
- Merge sort
- Bucket sort
- Cardinality sort
understand:
-
Measure the advantages and disadvantages of sorting algorithm
- Time complexity
- Spatial complexity
- stability
-
Sorted classification
- Internal sorting
- External sorting (requires disk)
-
Time complexity of different sorting algorithms
Sorting method Time complexity (average) Time complexity (worst case) Time complexity (best) Spatial complexity stability Insert sort O(n2) O(n2) O(n) O(1) stable Shell Sort O(n1.3) O(n2) O(n) O(1) instable Select sort O(n2) O(n2) O(n2) O(1) instable Heap sort O(nlog2n) O(nlog2n) O(nlog2n) O(1) instable Bubble sorting O(n2) O(n2) O(n) O(1) stable Quick sort O(nlog2n) O(n2) O(nlog2n) O(nlog2n) instable Merge sort O(nlog2n) O(nlog2n) O(nlog2n) O(n) stable Count sort O(n+k) O(n+k) O(n+k) O(n+k) stable Bucket sort O(n+k) O(n2) O(n) O(n+k) stable Cardinality sort O(n*k) O(n*k) O(n*k) O(n+k) stable -
Handwritten bubble sorting
public void bubbleSort(int[] arr){ for (int i = 0; i < arr.length - 1; i++) { for (int j = 0; j < arr.length - i - 1; j++) { if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } }
Use of Arrays tool class
understand
- It is defined under the java.util package
- Arrays: provides many ways to manipulate arrays
use
package com.atguigu.java; import java.util.Arrays; /** * Filename : ArraysTest.java * Author : keke * Creation time : 9:52:42 PM November 2, 2021 * Description : * java.util.Arrays: The tool class for operating arrays defines many methods for operating arrays */ public class ArraysTest { public static void main(String[] args) { // 1.boolean equals(int[] a,int[] b): judge whether two arrays are equal. int[] arr1 = {1, 2, 3, 4}; int[] arr2 = {1, 3, 2, 4}; System.out.println(Arrays.equals(arr1, arr2)); // 2.String toString(int[] a): output array information. System.out.println(Arrays.toString(arr1)); // 3.void fill(int[] a,int val): fill the specified value into the array. Arrays.fill(arr1, 10); System.out.println(Arrays.toString(arr1)); // 4.void sort(int[] a): sort the array. Arrays.sort(arr2); System.out.println(Arrays.toString(arr2)); // 5.int binarySearch(int[] a,int key): binary the sorted array to retrieve the specified value. int[] arr3 = {-98, -34, 2, 34, 54, 66, 79, 105, 210, 333}; System.out.println(Arrays.binarySearch(arr3, 211)); } }
Common exceptions to arrays
Array subscript out of bounds exception: ArrayIndexOutOfBoundsException
int[] arr = {1, 2, 3, 4, 5}; for (int i = 0; i <= arr.length; i++) { System.out.println(arr[i]); } System.out.println(arr[-2]);
Null pointer exception: NullPointerException
// Case 1: int[] arr1 = {1, 2, 3}; arr1 = null; System.out.println(arr1[1]); // Case 2: int[][] arr2 = new int[4][]; System.out.println(arr2[0][0]); // Case 3: String[] arr3 = new String[] {null, "BB", "CC"}; System.out.println(arr3[0].toString());
Little knowledge: once the program has an exception and is not handled, the execution will be terminated
object-oriented
Classes and objects
Three main lines of object-oriented learning
- Java classes and class members: properties, methods, constructors, code blocks, and internal classes
- Three characteristics of object-oriented: encapsulation, inheritance, polymorphism and abstraction
- Other keywords: this, super, static, final, abstract, interface, package, import, etc
"Focus on the big, start with the small"
Process oriented and object oriented
- Process oriented, emphasizing the functional behavior, taking the function as the minimum unit, consider how to do it.
- Object oriented, which emphasizes the objects with functions, takes the class / object as the minimum unit, and considers who will do it.
The idea of completing a project (or function)
- According to the needs of the problem, select the real-world entity targeted by the problem.
- Find the attributes and functions related to solving problems from entities, and these attributes and functions form classes in the conceptual world.
- Abstract entities are described in computer language to form the definition of classes in the computer world. That is, with the help of a program language, the class is constructed into a data structure that can be recognized and processed by the computer.
- Instantiate a class into an object in the computer world. Object is the ultimate tool to solve problems in the computer world.
Two important concepts in object oriented
- Class: the description of a class of things, which is an abstract and conceptual definition
- Object: it is each individual of this kind of thing that actually exists, so it is also called instance.
- Object oriented programming focuses on class design
- A design class is a member of a design class
The relationship between the two: the object is derived from the class new
Rule 1 for the implementation of object-oriented thought
- Create a class and design the members of the class
- Create an object of class
- Call the structure of an object through object. Property or object. Method
Supplement: instructions for the use of several concepts
- Attribute = member variable = field = field
- Behavior = member method = method = function
- Object to create class = instantiation of class = instantiation of class
Object creation and object memory parsing
Typical code:
Person p1 = new Person(); Person p2 = new Person(); Person p3 = p1; // There is no newly created object entity sharing a heap space
explain:
- If you create multiple objects of a class, each object has a set of class properties (non static)
- This means that if property a of one object is modified, the value of another property a will not be affected
Memory resolution:
Anonymous object
Concept: the created object is not explicitly assigned to a variable name, that is, it is an anonymous object
Features: anonymous objects can only be called once
give an example:
new Phone().sendEmail(); new Phone().playGame(); new Phone().price = 1999; new Phone().showPrice();
Application scenario:
PhoneMall mall = new PhoneMall(); // Use of anonymous objects mall.show(new Phone()); class PhoneMall{ public void show(Phone phone) { phone.sendEmail(); phone.playGame(); } }
Understand "everything is an object"
- In the category of Java language, functions and structures are encapsulated into classes, and the specific function structure of classes is called through class instantiation
-
Scanner,String etc.
-
File: File
-
Network resources: URL
-
- When it comes to the interaction between Java language and front-end Html and back-end database, the structure of front and back-end is embodied as classes and objects at the Java level
JVM memory structure
After compiling the source program, one or more bytecode files are generated. Using the class loader and interpreter in the JVM to interpret and run the generated bytecode file means that the class corresponding to the bytecode file needs to be loaded into memory, which involves memory parsing
-
Virtual machine stack, which is the stack structure mentioned at ordinary times, stores local variables in the stack structure
-
Heap, load the new structure into the heap space. Add: objects are attributes (non static) loaded into the heap space
-
Method area: class loading information, constant pool and static field
One of the structures of the class: properties
Class design, one of the two important structures: attributes
Compare attribute VS local variable
-
Same point
- Define the format of variables: data type, variable name = variable value;
- Declaration before use
- Variables have their corresponding scopes
-
difference:
-
Different positions declared in the class
- Attribute: directly defined in a pair of {} of the class
- Local variables: variables declared within methods, method parameters, code blocks, constructor parameters, and constructors
-
Differences about permission modifiers
-
Attribute: when declaring an attribute, you can specify its permission and use the permission modifier
Common permission modifiers: private, public, default, protected -- > encapsulation
At present, when declaring attributes, you can use the default
-
Local variable: permission modifier cannot be used
-
-
Default initialization value
- Property: the properties of a class have default initialization values according to their types
- Integer (byte, short, int, long): 0
- Floating point (float, double): 0.0
- char: 0 (or '\ u0000')
- boolean: false
- Reference data type (class, array, interface): null
- Local variable: there is no default initialization value, which means that the assignment must be displayed before calling the local variable, especially when the thread is calling
- Property: the properties of a class have default initialization values according to their types
-
Location loaded in memory
- Properties: load into heap space (non static)
- Local variables: loading into stack space
-
Supplement: review the classification of variables
-
Method 1: by data type
-
Method 2: according to the position declared in the class
Class structure 2: method
Class design, the second of two important structures: methods
-
Declaration of method:
Permission modifier return value type method name(parameter list ){ Method body }
Note: the methods modified by static, final and abstract will be described later
-
explain
-
Permission modifier: the permission modifiers of the default method use public first
Four kinds of permission modifiers specified by Java: private, protected, default, public -- > encapsulation
-
Return value type: with return value vs without return value
- If a method has a return value, the type of the return value must be specified when the method is declared. At the same time, the return keyword needs to be used in the method to return variables or constants of the specified type: "return data“
- If a method does not have a return value, it is declared with void. Generally, return cannot be used in methods without a return value. However, if it is used, only "return;" means to end the method
- Define whether the method should have a return value?
- Title Requirements
- Based on experience: specific analysis of specific problems
-
Method name: it belongs to an identifier and follows the naming rules and specifications of the identifier, "see the meaning of the name"
-
Parameter list: a method can declare zero, one, or more parameters
- Format: data type 1, parameter 1, data type 2, parameter 2
- When defining methods, should formal parameters be defined?
- Title Requirements
- Based on experience: specific analysis of specific problems
-
Method body: the embodiment of method function
-
-
Method, you can call the properties or methods of the current class
- Special: recursive method of method A is called in method A
- Method cannot be defined
Use of the return keyword
- Scope of use: used in the method body
- effect
- End method
- For methods with return value types, use the "return data;" method to return the required data
- Note: you cannot declare an execution statement after the return keyword
Method overloading
concept
Definition: more than one method with the same name is allowed in the same class, as long as their parameter number or parameter type are different.
Summary: "two are the same and different"
-
Same class, same method name
-
Different parameter lists: different parameter numbers and different parameter types
give an example
Overloaded sort() binarySearch() in Arrays class, println() in PrintStream
// The following four methods can constitute overloads public void getSum(int i, int j) { System.out.println(1); } public void getSum(double d1, double d2) { System.out.println(2); } public void getSum(String s, int i) { System.out.println(3); } public void getSum(int i, String s) { System.out.println(4); } // The following three methods cannot constitute overloads public int getSum(int i, int j){ return 0; } public void getSum(int m, int n){ } private void getSum(int i, int j){ }
Determine whether it constitutes an overload of the method
Judge strictly according to the definition: two are the same and different
It has nothing to do with the permission modifier, return value type, formal parameter variable name and method body of the method
How to determine the call of a method in a class
Method name -- > parameter list
Interview question: what is the difference between method overloading and rewriting?
throws / throw String / StringBuilder / StringBuffer Collection / Collections final / finally / finalize sleep() / wait() Interface / abstract class ...
Method of variable number formal parameters
instructions
- New content in jdk5.0
- Specific use
- Variable number parameter format: type... Variable name
- When calling variable number formal parameters, the parameters passed in can be 0, 1 or more
- Methods with variable number formal parameters have the same name as those in this class, and methods with different formal parameters constitute overloads
- Methods with variable number of formal parameters have the same name as those in this class, and arrays with the same parameter type do not constitute overloads. In other words, they cannot coexist
- The variable number parameter is in the parameter of the method and must be declared at the end
- A variable number parameter can declare at most one deformable parameter in a method parameter
Examples
public class MethodArgsTest { public void show(int i) { } public void show(String s) { System.out.println("MethodArgsTest.show(String s)"); } public void show(String... strs) { System.out.println("MethodArgsTest.show(String... strs)"); for (int i = 0; i < strs.length; i++) { System.out.println(strs[i]); } } // Cannot exist with the previous method /*public void show(String[] strs) { System.out.println("MethodArgsTest.show(String[] strs)"); }*/ public void show(int i, String... strs) { } }
When called:
public static void main(String[] args) { MethodArgsTest test = new MethodArgsTest(); test.show(1); test.show("Hello"); test.show("Hello", "World"); test.show(); test.show(new String[] {"Hello", "World", "!"}); }
Java Value Passing Mechanism
Examples of assignment of variables in methods
public class ValueTransferTest { public static void main(String[] args) { int m = 10; int n = m; System.out.println("m = " + m + ", n = " + n); n = 20; System.out.println("m = " + m + ", n = " + n); Order o1 = new Order(); o1.orderId = 1001; Order o2 = o1; System.out.println("o1.orderId = " + o1.orderId + ", o2.orderId = " + o2.orderId); // After the assignment, the address values of o1 and o2 are the same, resulting in both pointing to an object entity in the heap space o2.orderId = 1002; System.out.println("o1.orderId = " + o1.orderId + ", o2.orderId = " + o2.orderId); } } class Order{ int orderId; }
Rules:
- If the basic data type of the variable, the data value saved by the variable is assigned at this time
- If the reference data type of the variable, the address value of the data saved by the variable is assigned at this time
Concept of parameters for methods
- Formal parameters: parameters in parentheses declared when a method is defined
- Argument: the data actually passed to the formal parameter when the method is called
Parameter passing mechanism in Java
- Rules:
- If the parameter is a basic data type, what the argument assigns to the formal parameter is the data value actually stored by the argument
- If the parameter is a reference data type, the address value of the stored data of the parameter is assigned to the formal parameter
- extension:
- If the basic data type of the variable, the data value saved by the variable is assigned at this time
-
If the reference data type of the variable, the address value of the data saved by the variable is assigned at this time
Typical examples and memory analysis
Recursive Method
definition
Recursive method: a method body calls itself
understand
- Method recursion contains an implicit loop that repeats a piece of code, but this repetition does not need loop control.
- recursion must be in the known direction, otherwise this recursion will become infinite recursion, similar to dead loop.
give an example
public class RecursionTest { // Example 1: calculate the sum of all natural numbers between 1-100 public int getSum(int n) { if (n == 1) { return 1; } return n + getSum(n - 1); } // Example 2: calculate the product of all natural numbers between 1-100 public int getSum1(int n) { if (n == 1) { return 1; } return n * getSum1(n - 1); } /** * Example 3: it is known that there is a sequence: f(0) = 1, f(1) = 4, f(n+2) = 2 * f(n+1) + f(n), * Where n is an integer greater than 0, find the value of f(10). */ public int f(int n) { if (n == 0) { return 1; }else if (n == 1) { return 4; } return 2 * f(n - 1) + f(n - 2); } // Example 4: Fibonacci sequence public int f1(int n) { if (n == 1 || n == 2) { return 1; } return f(n - 1) + f(n - 2); } }
One of the characteristics of object-oriented: encapsulation and hiding
Why
- Programming pursues "high cohesion and low coupling".
- High cohesion: the internal data operation details of the class are completed by themselves, and external interference is not allowed;
- Low coupling: only a small amount of methods are exposed for use.
- Hide the internal complexity of objects and only expose simple interfaces. It is convenient for external calls, so as to improve the scalability and maintainability of the system. Generally speaking, hide what should be hidden and expose what should be exposed. This is the design idea of encapsulation.
Problem introduction
After creating an object of a class, the attribute of the object can be assigned by means of "object. Attribute". Here, the assignment operation is restricted by the data type and storage range of the attribute. In addition, there are no other constraints. However, in practical problems, it is often necessary to assign an attribute and add additional constraints, This condition cannot be reflected in the attribute declaration, but can only be added through methods. At this time, it is necessary to avoid the user from assigning the attribute in the way of "object. Attribute", so the attribute needs to be declared private - > at this time, encapsulation is reflected for the attribute
Encapsulation idea and concrete code embodiment
-
Privatize the properties of the class and provide public methods to get (getXxx) and set (setXxx) values
public class Circle{ private double radius; public void setRadius(double radius){ this.radius = radius; } public double getRadius(){ return radius; } }
-
Private method without external exposure
-
Singleton mode (privatize constructor)
-
If you do not want the class to be called outside the package, you can set the class as the default
Four kinds of permission modifiers specified by Java
Order of permissions from small to large
Private < default < protected < public
Specific modification scope
Modifier | Class interior | Same package | Subclasses of different packages | Same process |
---|---|---|---|---|
private | yes | |||
default | yes | yes | ||
protected | yes | yes | yes | |
public | yes | yes | yes | yes |
A description of the structure that permission modifiers can be used to modify
Specifically, four kinds of permissions can be used to modify classes and their internal structures: attributes, methods, constructors, and internal classes
-
If you modify a class, you can only use: default public
Class structure: Constructor
effect
- create object
- Initialization object information
instructions
-
If there is no constructor of the definition class displayed, the system provides an empty parameter constructor by default
-
Defines the format of the constructor: permission modifier class name (formal parameter list) {}
-
Multiple constructors defined in a class constitute an overload
-
Once the class constructor is explicitly defined, the system no longer provides the default null parameter constructor
-
There will be at least one constructor in a class
give an example
class Person{ String name; int age; // constructor public Person() { System.out.println("Person().........."); } public Person(String n) { name = n; } public Person(String n, int a) { name = n; age = a; } public void eat() { System.out.println("People eat"); } public void study() { System.out.println("People can learn"); } }
Assignment order of attributes
Summary: sequence of attribute assignment
-
Default initialization
-
Display initialization
-
Initialization in constructor
-
Assignment by "object. Method" or "object. Property"
Sequence of the above operations: 1 -- > 2 -- > 3 -- > 4
Concept of JavaBean
JavaBean s refer to Java classes that meet the following standards:
- Class is public
- There is a public constructor without parameters
- There are properties and corresponding get and set methods
this keyword
Callable structure
- Properties and methods
- constructor
Calling properties and methods
this is understood as: the current object or the object currently being created
-
In the method of the class, you can call the property or method of the current object by using "this. Property" or "this. Method". However, "this." is usually omitted. In special cases, if the formal parameter of the method has the same name as the attribute of the class, the "this. Variable" must be used to indicate that the variable is an attribute rather than a formal parameter
-
In the constructor of a class, you can use "this. Property" or "this. Method" to call the property or method of the object currently being created. However, generally, you choose to omit "this." in special cases, if the formal parameter of the constructor has the same name as the property of the class, you must explicitly use "this. Variable" Indicates that this variable is an attribute, not a formal parameter
Invoking Constructors
-
In the constructor of this class, you can explicitly use the "this (formal parameter list)" method to call other constructors specified in this class
-
Constructor cannot call itself through "this (formal parameter list)"
-
If there are n constructors in a class, "this (formal parameter list)" is used in up to n - 1 constructors
-
Specifies that "this (formal parameter list)" must be declared on the first line of the current constructor
-
Inside the constructor, at most one "this (formal parameter list)" method can be declared to call other constructors
Keyword package / import
Use of package keyword
instructions
-
In order to better realize the management of classes in the project, the concept of package is provided
-
Use package to declare the package to which the class or interface belongs, which is declared in the first line of the source file
-
Package is an identifier and follows naming rules and specifications. See the meaning of name
-
Every ".." represents a layer of file directory
give an example
Example 1:
Example 2: MVC design pattern
Introduction to main packages in JDK
- java.lang ---- contains some core classes of Java language, such as String, Math, Integer, System and Thread, and provides common functions
- java.net ---- contains classes and interfaces that perform network related operations.
- java.io -- contains classes that can provide multiple input / output functions.
- java.util ---- contains some utility classes, such as defining system features, collection framework classes of interfaces, and using functions related to date and calendar.
- java.text ---- contains some java formatting related classes
- java.sql ---- contains the relevant classes / interfaces for JDBC database programming in java
- java.awt ---- contains several classes that make up the abstract window toolkits. These classes are used to build and manage the graphical user interface (GUI) of the application. B/S C/S
Use of import keyword
import: import
- Display the class and interface under the specified package imported using the import structure in the source file
- The declaration is between the declaration of the package and the declaration of the class
- If you use to import multiple structures, you can write them out side by side
- "xxx. *" can be used to indicate that all structures under xxx package can be imported
- If the class or interface used is defined under the java.lang package, the import structure can be omitted
- If the class or interface used is defined under this package, the import structure can be omitted
- If classes with the same name under different packages are used in the source file, at least one class must be displayed in the form of full class name
- Using "xxx. *" means that you can call all structures under the xxx package, but if you are using structures under the xxx sub package, you still need to display the import
- import static: imports static structures: properties or methods in the specified class or interface
Object oriented feature 2: Inheritance
Why inheritance (the benefits of inheritance)
-
It reduces code redundancy and improves code reusability
-
Convenient for function expansion
-
It provides a premise for the later use of polymorphism
Inherited format
class A extends B{ }
- A: subClass, derived class, subClass
- B: Parent class, superClass, base class, superClass
What are the differences after a subclass inherits its parent class
-
Embodiment: once subclass A inherits parent class B, subclass A obtains all the attributes and methods declared in parent class B. in particular, the attributes and methods declared as private in the parent class. After subclass inherits the parent class, it is still considered to have obtained the private structure in the parent class. Only because of the influence of encapsulation, the subclass cannot directly call the structure of the parent class
-
After a subclass inherits from the parent class, it can also declare its own unique attributes or methods: extension of functions. The relationship between subclasses and parent classes is different from that between subsets and collections
Description of inheritance in Java
-
A class can be inherited by multiple subclasses
-
Single inheritance of classes in Java: a class can only have one parent class
-
Child parent class is a relative concept
-
The parent class directly inherited by the child class is called the direct parent class, and the parent class indirectly inherited is called the indirect parent class
-
After the child class inherits the parent class, it obtains the properties and methods declared in the direct parent class and all indirect parent classes
Understanding of java.lang.Object class
- If the parent class declaring a class is not displayed, this class inherits from java.lang.Object
- All Java classes (except the java.lang.Object class) inherit directly or indirectly from java.lang.Object
- All Java classes have the functions declared by the java.lang.Object class
Method override
What is a method override (override or overwrite)?
After the subclass inherits from the parent class, it can override the methods with the same name and parameters in the parent class
application
After rewriting, when a subclass object is created and a method with the same name and parameter in the child parent class is called through the subclass object, the actual execution is that the subclass rewrites the method of the parent class
give an example
class Circle{ /** * Find area */ public double findArea(){} } class Cylinder extends Circle{ /** * Surface area */ public double findArea(){} } class Account{ public boolean withdraw(double amt){} } class CheckAccount extends Account{ public boolean withdraw(double amt){} }
Overridden rules
Declaration of method:
Permission modifier return value type method name (parameter list ) throws Type of exception { Method body }
The Convention is commonly known as: the method in the subclass is called the overridden method, and the method in the parent class is called the overridden method
-
The method name and parameter list of the method overridden by the subclass are the same as those of the method overridden by the parent class
-
The permission modifier of the method overridden by the subclass is not less than that of the method overridden by the parent class. Special case: a subclass cannot override a method declared private in the parent class
-
The return value type of the method overridden by the subclass
-
If the return value type of the method overridden by the parent class is void, the return value type of the method overridden by the child class can only be void
-
If the return value type of the method overridden by the parent class is a, the return value type of the method overridden by the child class can be class A and its subclasses
-
If the return value type of the method overridden by the parent class is the basic data type, the return value type of the method overridden by the child class must be the same basic data type
-
-
The exception type thrown by the method overridden by the subclass is not greater than the exception type thrown by the method overridden by the parent class
Methods with the same name and parameters in the subclass and parent class are either declared non static (consider overriding), or both declared non static (not overriding)
Interview questions
How to distinguish between method rewriting and overloading?
-
The concept of both
-
Specific rules for overloading and overriding
-
Overloading is not polymorphic, rewriting is polymorphic
Overloading means that multiple methods with the same name are allowed, and the parameters of these methods are different. The compiler modifies the name of the method with the same name according to different parameter tables of the method. For the compiler, these methods with the same name become different methods. Their call addresses are bound at compile time. Java overloading can include parent classes and subclasses, that is, subclasses can overload methods with different parameters of the same name of the parent class. Therefore: for overloads, the compiler has determined the method to be called before the method call, which is called "early binding" or "static binding";
For polymorphism, the interpreter will not determine the specific method to be called until the moment of method call, which is called "late binding" or "dynamic binding".
Quote Bruce Eckel: "don't be silly. If it's not late binding, it's not polymorphic."
Use of super keyword
super understanding
Parent class
Structure of super call
- attribute
- method
- constructor
super calls properties and methods
- You can call the properties or methods declared in the parent class by using "super. Attribute" or "super. Method" in the method or constructor of the subclass. However, in general, you can omit "super."
- In special cases, when an attribute with the same name is defined in the subclass and parent class, if you want to define the attribute declared in the parent class in the subclass, you must explicitly use the "super. Attribute" method to indicate that the attribute declared in the parent class is called
- In special cases, when a subclass overrides the method of the parent class and wants to define the overridden method in the parent class in the method of the subclass, it must explicitly use the "super. Method" method to indicate that the overridden method in the parent class is called
super call constructor
- You can call the specified constructor declared in the parent class in the way of "super (formal parameter list)" displayed in the constructor of the child class
- The use of "super (formal parameter list)" must be declared in the first line of the subclass constructor
- In the constructor of a class, only one of "this" or "super" can be selected, not both
- In the first line of the constructor, if the Declaration "this" or "super" is not displayed, the null parameter constructor in the parent class is called by default
- Among multiple constructors of the class, at least one constructor uses "super (formal parameter list)" to call the constructor in the parent class
The whole process of subclass object instantiation
From the result: (inheritance)
After the subclass inherits from the parent class, it obtains the properties and methods declared in the parent class
If you create an object of a subclass, the properties declared in all the parent classes will be loaded in heap space
From the process point of view
When you create a subclass object through the subclass constructor, you must directly and indirectly call the constructor of its parent class, and then call the constructor of the parent class of the parent class until you call the empty parameter constructor in the java.lang.Object class. Just because all the structures of the parent class are loaded, you can see that there is a specified structure of the parent class in memory, Subclass objects can be considered for calling
Emphasize description
Although the parent class constructor is called when creating a subclass object, an object has been created from beginning to end, that is, the subclass object from new
The third feature of object-oriented: polymorphism
Understanding polymorphism
It can be understood as multiple forms of a thing
What is polymorphism
Object polymorphism: the reference of the parent class points to the object of the subclass (or the subclass object is assigned to the parent class reference)
give an example:
Person p = new Man(); Object obj = new Date();
Use of polymorphism: virtual method calls
With the polymorphism of objects, only the methods declared in the parent class can be called at compile time. However, at run time, the actual implementation is the method summary of subclass overriding the parent class: see the left for compilation and the right for operation
Premise of polymorphism
- Class inheritance
- Method override
Application examples of polymorphism
// Example 1: public class AnimalTest { public static void main(String[] args) { AnimalTest test = new AnimalTest(); test.func(new Dog()); test.func(new Cat()); } public void func(Animal animal) { animal.eat(); animal.shout(); } } class Animal{ public void eat() { System.out.println("Animal feeding"); } public void shout() { System.out.println("Animal call"); } } class Dog extends Animal{ @Override public void eat() { System.out.println("Dogs eat bones"); } @Override public void shout() { System.out.println("Woof, woof"); } } class Cat extends Animal{ @Override public void eat() { System.out.println("Cats eat fish"); } @Override public void shout() { System.out.println("cat "); } } //Example 2: class Order{ public void method(Object obj) { } } // Example 3: class Driver{ public void doData(Connection conn) { // Standardized steps to manipulate data } }
Points for attention in the use of polymorphism
The polymorphism of objects is only applicable to methods, not attributes (see the left for compilation and operation)
Upward and downward transformation
Upward transformation
polymorphic
Downward transformation
Why downward transformation is used: after object polymorphism, subclass specific properties and methods are actually loaded in memory. However, since variables are declared as parent types, only the properties and methods declared in the parent class can be called during compilation. Subclass specific properties and methods cannot be called. How can subclass specific properties and methods be called? Use downward transformation
How to achieve a downward Transformation: using a cast type converter
Note:
- ClassCastException exception may occur when strong rotation is used
- In order to avoid the exception of ClassCastException during downward transformation, judge instanceof before downward transformation. Once true is returned, downward transformation will be carried out, false will be returned, and downward transformation will not be carried out
Use of instanceof keyword
- a instanceof A determines whether a is an instance of class A. if yes, it returns true. If not, it returns false
- If a instanceof A returns true, a instanceof B returns true, where class B is the parent of class A
- a instanceof A requires that the class to which a belongs and class a must be the relationship between subclass and parent class, otherwise compilation error occurs
Interview questions
Talk about your understanding of polymorphism?
-
Realize the universality of the code
-
public boolean equals(Object obj) {}
JDBC: use Java programs to operate (get database connection, CRUD) databases (MySQL, Oracle, DB2, SQL Server)
-
The use of abstract classes and interfaces must reflect polymorphism (abstract classes and interfaces cannot be instantiated)
Is polymorphism a compile time behavior or a run-time behavior?
Runtime behavior
prove:
package com.atguigu.test; import java.util.Random; //Interview question: is polymorphism a compile time behavior or a runtime behavior? //The certificate is as follows: class Animal { protected void eat() { System.out.println("animal eat food"); } } class Cat extends Animal { protected void eat() { System.out.println("cat eat fish"); } } class Dog extends Animal { public void eat() { System.out.println("Dog eat bone"); } } class Sheep extends Animal { public void eat() { System.out.println("Sheep eat grass"); } } public class InterviewTest { public static Animal getInstance(int key) { switch (key) { case 0: return new Cat (); case 1: return new Dog (); default: return new Sheep (); } } public static void main(String[] args) { int key = new Random().nextInt(3); System.out.println(key); Animal animal = getInstance(key); animal.eat(); } }
Use of Object class
Description of java.lang.Object class
-
The Object class is the root parent of all Java classes
-
If the extension keyword is not used in the class declaration to indicate its parent class, the default parent class is java.lang.Object
-
The functions (properties and methods) in the Object class are universal
-
Properties: None
-
Methods: equals() toString() getClass() hashCode() clone() finalize() wait() notify() notifyAll()
-
-
The Object class declares only one null parameter constructor
equals() method
use
-
Is a method, not an operator
-
Applies only to reference data types
-
Definition of equals() in Object class
public boolean equals(Object obj) { return (this == obj); }
Note: the equals() method and = = method defined in the Object class have the same function to compare whether the two address values are the same, that is, whether the two references point to the same Object entity
-
For example, String, Date, File and wrapper classes all override the equals() method in the Object class. After rewriting, the comparison indicates whether the addresses of the two references are the same, but whether the "entity contents" of the two objects are the same
-
In general, if a custom class uses equals(), it is also necessary to override the equals() of the Object to compare whether the entity contents of the two objects are the same. The rewriting rule is to compare whether the entity contents of the two objects are the same
How to override equals()
Examples of manual Rewriting:
public class Customer { String name; int age; /** * Rewrite rule: compare whether the entity contents of two objects are the same */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof Customer) { Customer cust = (Customer) obj; // Compare whether the properties of two objects are the same if (this.age == cust.getAge() && this.name.equals(cust.getName())) { return true; } return this.age == cust.getAge() && this.name.equals(cust.getName()); } return false; } }
How to implement in development: automatically generated
public class Customer { String name; int age; @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Customer other = (Customer) obj; return age == other.age && Objects.equals(name, other.name); } }
Review the use of the = = operator
==: operator
-
Can be used in basic data type variables and reference data type variables
-
If you are comparing variables of basic data type, you are comparing whether the data saved by the two variables are the same, not necessarily of the same type
If the reference data type variable is compared, the comparison is whether the two address values are the same, that is, whether the two references point to the same object entity
Supplement: = = when the symbol is used, the variable types on the left and right sides of the symbol must be consistent
toString() method
use
-
When you output a reference to an object, you actually call the toString() of the current object
-
Definition of toString() in Object class
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
-
String, Date, File, wrapper class, etc. all override the toString() method in the Object class to return the "entity content" information of the Object when calling the toString() method of the Object
-
A custom class can also override the toString() method, which returns the "entity content" of the object when called
How to override toString()
give an example:
@Override public String toString() { return "Customer [name=" + name + ", age=" + age + "]"; }
Interview questions
- The difference between final, finally and finalize
- ==And equals()
Unit test method
-
step
-
Select the current process - right click to select: build path - add libraries - Junit 5 - next
-
Create Java classes for unit testing
Java class requirements at this time
- This class is public
- This class provides a public parameterless constructor
-
Unit test methods are declared in this class
The unit test method at this time: the permission of the method is public, there is no return value and no formal parameters
-
The annotation @ Test needs to be declared on this unit Test method and imported into the unit Test class: import org.junit.jupiter.api.Test;
-
After declaring the unit test method, you can write relevant code in the method body
-
After writing the code, right-click the unit test method name and right-click run as - JUnit Test
-
explain:
- If there are no exceptions in the execution structure, the green bar
- If an exception occurs in the execution structure, a red bar is displayed
Use of packaging
Why is there a wrapper class (or wrapper)
In order to make the variables of basic data type have the characteristics of class, packaging class is introduced
Basic data type and corresponding packing class
Basic data type | Packaging |
---|---|
int | Integer |
byte | Byte |
short | Short |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
Need to master the conversion between types
Basic data type, wrapper class and String type
Simple version
-
Basic data type < - > packaging class: new features of JDK 5.0: automatic packing and automatic unpacking
-
Basic data type, wrapper class -- > String: call valueof (XXX, XXX) overloaded by String
-
String -- > basic data type, wrapper class: call parseXxx(String s) of wrapper class
Note: NumberFormatException may be reported during conversion
Application scenario example
-
In the Vector class, only methods with formal parameters of Object type are defined for adding elements
v.addElement(Object obj); // Basic data type -- > wrapper class -- > use polymorphism
Use of static keyword
Static: static
Can be used to modify
It is mainly used to modify the internal structure of a class
- attribute
- method
- Code block
- Inner class
static modifier attribute
Static variable (class variable)
-
Attribute: static attribute VS non static attribute (instance variable) according to whether static modification is used
Instance variable: multiple objects of the class are created, and each object independently has a set of non static attributes in the class. When modifying the non static attributes in one object, the same attribute values in other objects will not be modified
Static variable: multiple objects of the class are created, and each object shares the same static variable. When a static variable is modified through an object, it will cause other objects to call the static variable. It is modified
-
Other instructions
-
Static variables are loaded with the loading of classes, and can be called by "class. Static variables"
-
Static variables are loaded before objects are created
-
Since the class will only be loaded once, only one copy of the static variable will exist in memory and in the static field of the method area
Static method Non static method class yes no object yes yes
-
-
Examples of static attributes: System.out, Math.PI
Static variable memory parsing
static modification method
Static method, class method
-
It is loaded as the class is loaded, and can be called through "class. Static method"
Static method Non static method class yes no object yes yes -
In static methods, only static methods or properties can be called
In non static methods, either static methods or properties can be called, or non static methods or properties can be called
static note
- this and super keywords cannot be used in static methods
- The use of static attributes and static methods is understood from the perspective of life cycle
How to determine whether attributes and methods should use the static keyword
-
About properties
- Attributes can be shared by multiple objects and will not vary with different objects
- Constants in classes are often declared as static
-
About methods
- The method for operating static properties is usually set to static
- Methods in tool classes are traditionally declared static, such as Arrays, Collections, and Math
Use examples
-
Example 1: Arrays, Collections, Math and other tool classes
-
Example 2: Singleton mode
-
Example 3:
class Circle{ private double radius; /** * automatic recode */ private int id; /** * Record the number of circles created */ private static int total; /** * static Declared properties are shared by all objects */ private static int init = 1001; public Circle() { id = init++; total++; } public Circle(double radius) { this(); this.radius = radius; } public static int getTotal() { return total; } public double getRadius() { return radius; } public void setRadius(double radius) { this.radius = radius; } public int getId() { return id; } public double findArea() { return Math.PI * radius * radius; } }
Singleton mode
Description of design pattern
understand
Design pattern is the code structure, programming style and thinking way to solve problems after summarizing and theorizing in a large number of practice.
Common design patterns
23 classic design patterns GoF
- Creator mode
- Factory method model
- Abstract factory pattern
- Singleton mode
- Builder pattern
- Prototype mode
- Structural model
- Adapter mode
- Decorator mode
- proxy pattern
- Bridging mode
- Combination mode
- Sharing element mode
- Behavioral model
- Strategy mode
- Template method pattern
- Observer mode
- Iterator mode
- Responsibility chain model
- Command mode
- State mode
- Visitor mode
- Intermediary model
- Interpreter mode
Singleton mode
Problems to be solved
The so-called class singleton design pattern is to take certain methods to ensure that there can only be one object instance of a class in the whole software system
Implementation of specific code
Hungry Han style 1:
class Bank{ // 1. Constructor of privatization class private Bank() { } // 2. Create class objects internally // 4. This object must also be declared static private static Bank instance = new Bank(); // 3. Provide public static methods to return class objects public static Bank getInstance() { return instance; } }
Hungry Han style 2:
class Bank{ // 1. Constructor of privatization class private Bank() { } // 2. Create class objects internally // 4. This object must also be declared static private static Bank instance; static{ instance = new Bank(); } // 3. Provide public static methods to return class objects public static Bank getInstance() { return instance; } }
Lazy:
class Order{ // 1. Constructor of privatization class private Order() { } // 2. Declare the current class object without instantiation // 4. This object must be declared static private static Order instance = null; // 3. Declare the method of public static to return the current class object public static Order getInstance() { if (instance == null) { instance = new Order(); } return instance; } }
Comparison of the two methods
-
Hungry Han style
-
Disadvantage: the object takes too long to load
-
Benefit: hungry Chinese style is thread safe
-
-
Lazy style * Benefit: delay object creation * The disadvantage of the current writing method: thread is not safe --> When the multithreaded content is, modify it again
Instructions for main()
-
The main() method serves as an entry to the program
-
The main() method is a normal static method
-
The main() method can be used as a way for us to interact with the console (previously, using Scanner)
How to transfer the data obtained by the console to the formal parameter: String[] args?
Runtime: java class name "Tom" "123" "true" "Jerry"
sysout(args[0]); // "Tom" sysout(args[2]); // "true" sysout(args[4]); // Report exception
Summary:
public static void main(String[] args){ // Method body }
- Permission modifier: private default protected public - > encapsulation
- Modifier: static final abstract native can be used to modify methods
- Return value type: no return value, return value -- > return
- Method name: it needs to meet the rules and specifications of identifier naming. See the meaning of name
- Formal parameter list: overload VS override; Parameter value transfer mechanism; Reflect the polymorphism of objects
- Method body: reflects the function of the method
Class structure 4: code block
Also called initialization block
Role of code blocks
Information used to initialize classes and objects
classification
If the code block is decorated, only static can be used
Static code block VS non static code block
- Static code block
- There can be output statements inside
- Executes as the class loads, and only once
- Function: initialize class information
- If multiple static code blocks are defined in a class, they are executed in the order of declaration
- The execution of static code blocks takes precedence over the execution of non static code blocks
- Static code blocks can only call static attributes and static methods, not non static structures
- Non static code block
- There can be output statements inside
- Executes as the object is created
- Each time an object is created, a non static block of code is executed
- Function: you can initialize the properties of an object when creating an object
- If multiple non static code blocks are defined in a class, they are executed in the order of declaration
- Static attributes, static methods, or non static attributes and non static methods can be called in non static code blocks
Load order of instantiated subclass objects
Involving the loading sequence of static code block and non static code block constructors in parent and child classes: from parent and child, static first
LeafTest.java
package cn.tedu.java3; class Root{ static{ System.out.println("Root Static initialization block for"); } { System.out.println("Root Normal initialization block"); } public Root(){ System.out.println("Root Parameterless constructor for"); } } class Mid extends Root{ static{ System.out.println("Mid Static initialization block for"); } { System.out.println("Mid Normal initialization block"); } public Mid(){ System.out.println("Mid Parameterless constructor for"); } public Mid(String msg){ // Call overloaded constructors in the same class through this this(); System.out.println("Mid A constructor with parameters, whose parameter values are:" + msg); } } class Leaf extends Mid{ static{ System.out.println("Leaf Static initialization block for"); } { System.out.println("Leaf Normal initialization block"); } public Leaf(){ // Call the constructor with a string parameter in the parent class through super super("Shang Silicon Valley"); System.out.println("Leaf Constructor for"); } } public class LeafTest{ public static void main(String[] args){ new Leaf(); new Leaf(); } }
Son.java
package cn.tedu.java3; class Father { static { System.out.println("11111111111"); } { System.out.println("22222222222"); } public Father() { System.out.println("33333333333"); } } public class Son extends Father { static { System.out.println("44444444444"); } { System.out.println("55555555555"); } public Son() { System.out.println("66666666666"); } public static void main(String[] args) { // Statically preceded by parent and child System.out.println("77777777777"); System.out.println("************************"); new Son(); System.out.println("************************"); new Son(); System.out.println("************************"); new Father(); } }
Assignment order of attributes
-
Default initialization
-
Display initialization
-
Object initialization
-
After you have an object, you can assign values through "object. Attribute" or "object. Method"
-
Code block assignment
Order of execution: 1 - 2 / 5 - 3 - 4
Use of final keyword
A structure that can be modified
Class, method, variable
usage
-
final is used to modify a class: this class cannot be inherited by other classes, such as String class, System class and StringBuffer class
-
final is used to modify a method: it indicates that this method cannot be overridden, such as getClass() of Object class;
-
final is used to modify variables: at this time, the "variable" is called a constant
- final modifies an attribute. The positions where assignment can be considered are: display initialization, initialization in code block and assignment in constructor
- When final modifies a local variable, especially when final modifies a formal parameter, it indicates that this formal parameter is a constant. When calling this method, assign an argument to the constant formal parameter. Once assigned, this formal parameter can only be used in the method body, but it cannot be re assigned
-
static final is used to modify attributes and global constants
Use of abstract keyword
abstract: abstract
A structure that can be modified
Class and method
concrete
-
Abstract modifier class: abstract class
- This class cannot be instantiated
- Abstract classes must have constructors to be called when subclasses are instantiated (involving the whole process of subclass object instantiation)
- During development, subclasses of abstract classes will be provided to complete relevant functions
-
abstract modification method:
-
Abstract method abstract method has only method declaration and no method body
-
A class containing abstract methods must be an abstract class. On the contrary, there can be no abstract methods in an abstract class
-
If a subclass overrides all abstract methods in the parent class, the subclass can be instantiated
If the subclass does not override all the abstract methods in the parent class, the subclass is also an abstract class and needs to be modified with abstract
-
Precautions in use
- abstract cannot be used to modify structures such as attributes and constructors
- abstract cannot be used to modify private methods, static methods, final methods, and final classes
Application examples of abstract
-
Example 1
public abstract class Vehicle{ public abstract double calcFuelEfficiency(); // Abstract method for calculating fuel efficiency public abstract double calcTripDistance(); // Abstract method for calculating driving distance } public class Truck extends Vehicle{ public double calcFuelEfficiency(){ //Write a specific method for calculating the fuel efficiency of trucks } public double calcTripDistance(){ //Write down the specific method of calculating the distance traveled by the truck } } public class RiverBarge extends Vehicle{ public double calcFuelEfficiency() { //Write a specific method for calculating the fuel efficiency of the barge } public double calcTripDistance() { //Write down the specific method for calculating the distance traveled by the barge } }
-
Example 2:
public class Circle extends GeometricObject{ private double radius; @Override public double findArea() { return Math.PI * radius * radius; } } abstract class GeometricObject { public abstract double findArea(); }
-
Example 3
The abstract class involved in the IO stream: InputStream / OutputStream / Reader / Writer, which defines read() / write()
Template method design pattern
Problems solved
When implementing an algorithm in software development, the overall steps are very fixed and common. These steps have been written in the parent class. However, some parts are changeable, and the changeable parts can be abstracted for different subclasses to implement. This is a template pattern.
give an example
package cn.tedu.java; public class TemplateTest { public static void main(String[] args) { Template template = new SubTemplate(); template.spendTime(); } } abstract class Template{ /** * Calculate the time taken for a piece of code */ public void spendTime() { long start = System.currentTimeMillis(); // Changeable part code(); long end = System.currentTimeMillis(); System.out.println("The time spent is:" + (end - start)); } public abstract void code(); } class SubTemplate extends Template{ @Override public void code() { for(int i = 2; i < 10000000; i++) { boolean isFlag = true; for(int j = 2; j <= Math.sqrt(i); j++) { if (i % j == 0) { isFlag = false; break; } } if (isFlag) { System.out.println(i); } } } }
Application scenario
- Encapsulation of database access
- Junit unit test
- On doGet / doPost method call in Java Web Servlet
- Template program in Hibernate
- JDBC te mlate, hibernate template, etc. in Spring
Use of interface keyword
instructions
-
Interfaces are defined using interface s
-
In Java, interface and class are two parallel structures
-
How to define an interface: define an interface as a member
-
JDK7 and before: only global constants and abstract methods can be defined
Global constant: public static final, but it can be omitted when writing
Abstract method: public abstract, but it can be omitted when writing
-
JDK8: in addition to defining global constants and abstract methods, you can also define static methods and default methods
-
-
A constructor cannot be defined in an interface, which means that the interface cannot be instantiated
-
In Java development, interfaces are used through class implementations
If the implementation class covers all the abstract methods in the interface, the implementation class can be instantiated
If the implementation class does not cover all the abstract methods in the interface, the implementation class is still an abstract class
-
Java classes can implement multiple interfaces -- > making up for the limitations of Java single inheritance
Format: Class AA extensions BB implementations CC, DD, EE {}
-
Interfaces can inherit from one interface to another, and multiple interfaces can inherit
-
The specific use of the interface reflects polymorphism
-
An interface can actually be seen as a specification
give an example
package cn.tedu.java1; public class USBTest { public static void main(String[] args) { Computer com = new Computer(); // 1. Create a non anonymous object of the non anonymous implementation of the interface Flash flash = new Flash(); com.transforData(flash); // 2. The anonymous object of the non anonymous implementation of the interface is created com.transforData(new Printer()); // 3. Create a non anonymous object of the anonymous implementation of the interface USB phone = new USB() { @Override public void stop() { System.out.println("End of mobile phone work"); } @Override public void start() { System.out.println("The phone starts working"); } }; com.transforData(phone); // 4. Create an anonymous object for the anonymous implementation of the interface com.transforData(new USB() { @Override public void stop() { System.out.println("mp3 power cut-off"); } @Override public void start() { System.out.println("mp3 start-up"); } }); } } class Computer{ public void transforData(USB usb) { usb.start(); System.out.println("Details of specific transmission data"); usb.stop(); } } interface USB{ void start(); void stop(); } class Flash implements USB{ @Override public void start() { System.out.println("U Disc opening operation"); } @Override public void stop() { System.out.println("U Disk end work"); } } class Printer implements USB{ @Override public void start() { System.out.println("Printer on"); } @Override public void stop() { System.out.println("Printer finished working"); } }
experience:
-
The interface meets polymorphism
-
The interface actually defines a specification
-
Experience interface oriented programming in development
Experience the idea of interface oriented programming
Interface oriented programming, in the application program, the structure of the invocation is the interface defined in JDBC, and does not appear the API of a specific database manufacturer.
New specification of interface in JDK8
-
Static methods defined in the interface can only be called through the interface
-
By implementing the class object, you can call the default method in the interface. If the implementation class overrides the default method in the interface, the overridden method will still be called
-
If a method with the same name and parameter is declared in the inherited parent class and the implemented interface of the subclass (or implementation class), the subclass will call the method with the same name and parameter in the parent class by default -- > class priority principle without overriding this method
-
If the implementation class implements multiple interfaces and default methods with the same name and parameters are defined in these interfaces, an error -- > interface conflict will be reported if the implementation class does not override this method, which requires us to override this method in the implementation class
-
How to call the parent class and the rewritten method in the interface in the subclass (or implementation class) method.
public void myMethod() { method3(); // Call your own defined overridden method super.method3(); // Call the declared in the parent class // Call the default method in the interface CompareA.super.method3(); CompareB.super.method3(); }
Interview questions
-
What are the similarities and differences between abstract classes and interfaces?
-
Same point
- Cannot instantiate
- Can contain abstract methods
-
difference
-
Explain the definition and internal structure of abstract classes and interfaces
-
Classes: single inheritance
Interfaces: multi inheritance
Classes and interfaces: multiple implementations
-
-
proxy pattern
Problems solved
Proxy pattern is a design pattern used more in Java development. Proxy design is to provide a proxy for other objects to control access to this object.
give an example
public class NetWorkTest { public static void main(String[] args) { Server server = new Server(); ProxyServer proxyServer = new ProxyServer(server); proxyServer.browse(); } } interface NetWork{ void browse(); } // Proxy class class Server implements NetWork{ @Override public void browse() { System.out.println("Real server access network"); } } // proxy class class ProxyServer implements NetWork{ private NetWork work; public ProxyServer(NetWork work) { this.work = work; } @Override public void browse() { check(); work.browse(); } public void check() { System.out.println("Inspection before networking"); } }
Application scenario
- Application scenario:
- Security proxy: block direct access to real roles.
- Remote proxy: Handling remote method calls (RMI) through proxy classes
- Delayed loading: load the lightweight proxy object first, and then load the real object if necessary
For example, if you want to develop a large document viewing software, there are large pictures in a large document. Maybe a picture has 100MB. When you open a file, it is impossible to display all the pictures. In this way, you can use the proxy mode. When you need to view the pictures, you can use the proxy to open the large pictures.
- classification
- Static proxy (statically defined proxy class)
- Dynamic proxy (dynamically generate proxy classes)
- JDK's own dynamic agent requires reflection and other knowledge
Design mode of factory
Problems solved
It realizes the separation of creator and caller, that is, the specific process of creating objects is shielded and isolated, so as to improve flexibility.
Specific mode
- **Simple factory mode: * * used to produce any product in the same hierarchical structure. (for adding new products, the existing code needs to be modified)
- **Factory method mode: * * used to produce fixed products in the same hierarchical structure. (any product can be added)
- **Abstract factory pattern: * * used to produce all products of different product families. (there is nothing you can do to add new products; support adding product families)
Class structure 5: inner class
definition
In Java, it is allowed to declare one class A in another class B, then class A is the inner class and class B is the outer class
classification
- Member inner class (static, non static)
- Local internal classes (within methods, code blocks, constructors)
Understanding of inner classes of members
- On the one hand, as a member of an external class
- Calling the structure of an external class
- Can be modified by static
- It can be modified by four different permissions
- On the other hand, as a class
- Properties, methods, constructors, etc. can be defined within a class
- It can be modified by final, indicating that this class cannot be inherited. By implication, it can be inherited without using final
- Can be modified by abstract
Local inner class
-
How to instantiate an object of a member's inner class
public static void main(String[] args) { // Create a Dog instance (static member inner class) Dog dog = new Person.Dog(); // Create Bird instance (non static member inner class) Person p = new Person(); Bird bird = p.new Bird(); }
-
How to distinguish the structure of calling external classes in member internal classes
class Person{ String name = "Xiao Ming"; public void eat(){ } // Non static member inner class class Bird{ String name = "cuckoo"; public void display(String name) { System.out.println(name); // Method parameters System.out.println(this.name); // Internal class properties System.out.println(Person.this.name); // External class properties // Person.this.eat(); } } }
Use of local inner classes
public class InnerClassTest1 { // Rare in development public void method() { class AA{ } } /** * Returns a class object that implements the Comparable interface */ public Comparable getComparable() { // Create a class that implements the Comparable interface: a local inner class /*class MyComparable implements Comparable{ @Override public int compareTo(Object o) { // TODO Auto-generated method stub return 0; } } return new MyComparable();*/ return new Comparable() { @Override public int compareTo(Object o) { // TODO Auto-generated method stub return 0; } }; } }
Note:
In the method of the local inner class, if the local variable in the method declared by the local inner class is called, it is required to declare this local variable as final
- JDK7 and earlier: this local variable is required to be declared final
- JDK8 and later versions: the final declaration can be omitted
public class InnerClassTest { public void method() { // local variable int num = 10; class AA{ public void show() { // num = 10; System.out.println(num); } } } }
summary
Member internal classes and local internal classes will generate bytecode files after compilation
format
- Member inner class: outer class $inner class name. Class
- Local internal class: external class $numeric internal class name. Class
Debug debugging
operation | effect |
---|---|
step into (F5) | Enter the method called by the current line |
step over (F6) | After executing the statement of the current line, proceed to the next line |
step return (F7) | After executing the method of the current line, enter the next line |
drop to frame | Returns to the first line of the method where the current line is located |
Resume resume | After executing all the code of the breakpoint where the current line is located, enter the next breakpoint. If not, it will end |
Terminate stop | Stop the JVM and the subsequent programs will not be executed |
abnormal
abnormal
Abnormal architecture
java.lang.Throwable |--- java.lang.Error: Generally, targeted code is not written for processing |--- java.lang.Exception: You can handle exceptions |--- Compile time exception( checked) |--- IOException |--- FileNotFoundException |--- ClassNotFoundException |--- Runtime exception( unchecked) |--- NullPointerException |--- ArrayIndexOutOfBoundsException |--- ClassCastException |--- NumberFormatException |--- InputMismatchException |--- ArithmeticException
From the execution process of the program, look at compile time exceptions and run-time exceptions
Compile time exception: possible exception when executing javac.exe command
Runtime exception: an exception that occurs when executing the java.exe command
Common exception types, please give examples
public class ExceptionTest { // NullPointerException @Test public void test1() { int[] arr = null; System.out.println(arr); String str = null; System.out.println(str.charAt(0)); } // IndexOutOfBoundsException @Test public void test2() { // ArrayIndexOutOfBoundsException int[] a = new int[10]; System.out.println(a[10]); // StringIndexOutOfBoundsException String str = "abc"; System.out.println(str.charAt(3)); } // ClassCastException @Test public void test3() { Object obj = new Date(); String str = (String) obj; } // NumberFormatException @Test public void test4() { String str = "abc"; int parseInt = Integer.parseInt(str); } // InputMismatchException @Test public void test5() { int score = new Scanner(System.in).nextInt(); System.out.println(score); } // ArithmeticException @Test public void test6(){ int a = 1 / 0; } // // @Test // public void test7() { // File file = new File("hello.txt"); // FileInputStream fileInputStream = new FileInputStream(file); // int read = fileInputStream.read(); // while (read != -1) { // System.out.print((char)read); // read = fileInputStream.read(); // } // fileInputStream.close(); // } }
Exception handling
Grasping and throwing model of Java exception handling
-
"Throw", once an exception occurs during the normal execution of the program, an object corresponding to the exception class will be generated at the exception code and thrown. Once an exception is thrown, the subsequent code will not be executed
Generation of exception objects:
- Exception object automatically generated by the system
- Manually generate an exception object and throw it
-
"Grasping" can be understood as the exception handling method:
- try-catch-finally
- throws
Exception handling method 1: try catch finally
try{ // Possible exception codes } catch(Exception type 1 variable name 1){ // How to handle exceptions 1 } catch(Exception type 2 variable name 2){ // How to handle exceptions 2 } catch(Exception type 3 variable name 3){ // How to handle exceptions 3 } ... finally{ // Code that must execute }
instructions
-
finally is optional
-
try is used to wrap the possible exception code. During execution, once an exception occurs, an object corresponding to the exception class will be generated. According to the type of this object, it will be matched in the cache
-
Once the exception object in the try matches a catch, it will enter the catch for exception processing. Once the processing is completed, it will jump out of the current try catch structure (without writing finally) and continue to execute the subsequent code
-
If the exception type in catch has no child parent relationship, it doesn't matter who declares it on and who declares it under
If the exception type in catch satisfies the child parent relationship, the child class must be declared on the parent class, otherwise an error will be reported
-
Common exception object handling methods
- String getMessage()
- printStackTrace()
-
Variables declared in the try structure cannot be called after the try structure
-
Try catc finally structures can be nested with each other
Summary: how do you view compile time and run-time exceptions in your code?
-
Using try catch finally to handle compile time exceptions means that the program will no longer report errors at compile time, but may still report errors at run time. It is equivalent to using try catch finally to delay an exception that may occur at compile time until it occurs at run time
-
Since runtime exceptions are common in development, try catch finally is usually not written for runtime exceptions. For compile time exceptions, we must consider exception handling
finally, re description
- finally is optional
- finally, the code declared is bound to be executed. Even if an exception occurs in catch, there is a return statement in try and a return statement in catch
- For database connection, input / output stream, network programming Socket and other resources, the JVM cannot recycle them automatically. It needs to release the resources manually. At this time, the resource release needs to be declared in finally
Interview questions
- The difference between final, finally and finalize
similar:
- throw and throws
- Collection s and Collections
- String, StringBuilder and StringBuffer
- ArrayList and LinkedList
- HashMap and LinkedHashMap
- Override and reload
Different structure:
- Abstract classes and interfaces
- ==And equals()
- sleep() and wait()
Exception handling method 2: throws
"Throws + exception type" is written in the method declaration, indicating the exception type that may be thrown when the method is executed. Once an exception occurs when the method body is executed, an object of exception class will still be generated at the exception code. After the object satisfies the throws exception type, it will be thrown, and the exception code and subsequent code will not be executed
Compare the two treatment methods
- Try catch finally: the exception is really handled
- The throws method annotation throws the exception to the caller of the method, and does not really handle the exception
Experience how to choose two processing methods in development
-
If the overridden method in the parent class does not handle exceptions in the throw mode, the overridden method of the child class cannot use throws, which means that if the overridden method of the child class has exceptions, it must be handled in the try catch finally mode
-
Several other methods are called successively in the execution method. These methods are executed in a progressive relationship. It is recommended that these methods be processed in the way of throws, and the execution method a can be processed in the way of try catch finally
Supplement:
One of the rules of method Rewriting: the exception type thrown by the method overridden by the subclass shall not be greater than the exception type thrown by the method overridden by the parent class
Manually throw exception object
instructions
During program execution, in addition to automatically throwing exception objects, you can also manually throw objects of an exception class
Interview questions
- The difference between throw and throws
- throw: refers to the object throwing an exception class and the process of generating an exception object, which is declared in the method body
- throws: a method of exception handling, which is declared at the declaration of the method
Typical examples
class Student{ private int id; public void regist(int id) { if (id > 0) { this.id = id; }else { // System.out.println("the data you entered is illegal"); // Manually throw exception object // throw new RuntimeException("the input data is illegal"); // throw new Exception("the input data is illegal"); throw new MyException("You cannot enter a negative number"); } } @Override public String toString() { return "Student [id=" + id + "]"; } }
Custom exception class
- How to customize an exception class
- Inherits from the existing exception structure: RuntimeException Exception
- Provide the global constant serialVersionUID
- Provides overloaded constructors
public class MyException extends RuntimeException{ static final long serialVersionUID = 12345678921234L; public MyException() { } public MyException(String msg) { super(msg); } }
Multithreading
Understanding of programs, processes and threads
program
concept
It is a set of instructions written in a certain language to complete a specific task. That is, a piece of static code.
process
concept
Is an execution process of a program, or a running program.
explain
Process is the unit of resource allocation. The system will allocate different memory areas for each process at run time
thread
concept
The process can be further refined into threads, which is an execution path within a program.
explain
As a unit of scheduling and execution, each thread has an independent running stack and program counter (pc), and the overhead of thread switching is small
Memory structure:
A process can be subdivided into multiple threads
Each thread has its own independent: stack, program counter
Multiple threads share structures in the same process: method area and heap
Parallelism and concurrency
Understanding of single core CPU and multi-core CPU
-
Single core CPU is actually a fake multithreading, because only one thread can be executed in a time unit. For example: Although there are multiple lanes, there is only one staff member in the toll station charging, and the CPU can pass only after charging, so the CPU is like a toll collector. If someone doesn't want to pay, the toll collector can "hang" him (hang him until he has figured it out and has the money ready). But because the CPU time unit is very short, I can't feel it.
-
If it is multi-core, it can give better play to the efficiency of multithreading. (today's servers are multi-core)
-
A Java application, java.exe, actually has at least three threads: main() main thread, gc() garbage collection thread, and exception handling thread. Of course, if an exception occurs, it will affect the main thread.
Understanding of parallelism and concurrency
- **Parallel: * * multiple CPU s execute multiple tasks at the same time. For example, many people do different things at the same time.
- **Concurrency: * * one CPU (using time slice) executes multiple tasks at the same time. For example: second kill, multiple people do the same thing.
There are two ways to create multithreading
Method 1: inherit Thread class
-
Create a subclass that inherits from the Thread class
-
Override run() -- > of the Thread class to declare this Thread in run()
-
Create an object that inherits from a subclass of the Thread class
-
Call start() from this object:
- Start the current thread
- Call the run() of the current thread
Explain two questions:
- To start a thread, you must call start(), not run()
- If you start another Thread, you must recreate an object of Thread subclass and call start() of this object
Mode 2: implementation of Runnable interface
-
Create a class that implements the Runnable interface
-
The implementation class implements the abstract method in Runnable: run()
-
Create an object that implements the class
-
Pass this object as a parameter to the constructor of the Thread class to create an object of the Thread class
-
start() is called through the object of the Thread class
Comparison of the two methods
-
During development, the method of implementing Runnable interface is preferred
reason:
- The implementation method has no limitation of single inheritance of classes
- The implementation method is more suitable to deal with the situation that multiple threads share data
- Contact: public class Tread implements Runnable
- Similarities:
- Both methods need to override run() and declare the logic to be executed by the thread in run()
- At present, the two methods to start a Thread are run() in the Thread class of the call
Common methods in Thread class
common method
-
start(): start the current thread and call run() of the current thread
-
run(): you usually need to override this method in the Thread class and declare the operation to be performed by the created Thread in this method
-
currentThread(): a static method that returns the thread executing the current code
-
getName(): get the name of the current thread
-
setName(): sets the name of the current thread
-
yeild(): release the execution authority of the current CPU
-
join(): join() that calls thread b in thread a. At this point, thread a enters the blocking state, and thread a ends the blocking state until the thread b is fully executed.
-
stop(): obsolete. When this method is executed, the current thread is forced to end
-
sleep(long millis): enables the current thread to "sleep" for the specified millisecond. Within the specified millisecond, the current thread is blocked
-
isAlive(): judge whether the current thread is alive
thread priority
-
MAX_PRIORITY: 10
MIN _PRIORITY: 1
NORM_PRIORITY: 5 -- > default priority
-
How to get and set the priority of the current thread
-
getPriority(): get the priority of the thread
-
setPriority(int newPriority): sets the priority of the thread
-
Note: high priority threads should seize the execution right of the CPU of low priority threads, but only in terms of probability, high priority threads are executed with high probability, which does not mean that low priority threads will execute only after the high priority threads are executed
-
Thread communication: wait(), notify(), notifyAll(): these three methods are defined in the Object class
Classification of threads
- Daemon thread
- User thread
Thread lifecycle
explain:
-
Life cycle focuses on two concepts: state and corresponding method
-
follow
- Status a -- > status b: which methods are executed (callback method)
- Active invocation of a method: state a -- > State b
-
Blocking: temporary state, not final state
Death: final state
Thread synchronization mechanism
background
Create three windows to buy tickets, with a total of 100 tickets. Use the method of implementing the Runnable interface
-
Problem: in the process of buying tickets, there are duplicate tickets and wrong tickets -- > there are thread safety problems
-
Causes: when a thread operates a ticket, but the operation is not completed, other threads participate and operate the ticket
-
How to solve this problem: when a thread a is operating a ticket, other threads cannot participate. Other threads cannot start operating a ticket until thread a has finished operating the ticket. This situation cannot be changed even if thread a is blocked
Java solution: synchronization mechanism
In Java, thread safety is solved through synchronization mechanism
-
Method 1: synchronize code blocks
synchronized(Synchronization monitor){ // Code to be synchronized }
-
explain:
- The code that operates shared data, that is, the code that needs to be synchronized -- > cannot contain more code or less code
-
Shared data: variables operated by multiple threads. For example, ticket is shared data
-
Synchronization monitor, commonly known as lock. The object of any class can act as a lock
Requirement: multiple threads must share the same lock
-
**Supplement**
-
In the way of implementing the Runnable interface to create multithreading, you can consider this as a synchronization monitor
-
In the way of inheriting Thread class to create multithreads, use this carefully as the synchronization monitor, and consider using the current class as the synchronization monitor
-
-
-
Mode 2: synchronization method
-
If the code that operates on shared data is completely declared in a method, you might as well declare this method synchronous
-
The synchronization method still involves the synchronization monitor, but there is no need to display the declaration
-
The synchronization monitor of non static synchronization method is this
The synchronization monitor of static synchronization method is the current class itself
-
-
Mode 3: Lock lock - JDK 5.0 added
- Interview question: similarities and differences between synchronized and Lock
- Same: both can solve thread safety problems
- Difference:
- The synchronized mechanism automatically releases the synchronization monitor after executing the corresponding synchronization code
- Lock needs to manually start synchronization (lock()) and end synchronization (unLock())
- Interview question: similarities and differences between synchronized and Lock
Priority: Lock – > synchronize code block (has entered the method body and allocated corresponding resources) – > synchronize method (outside the method body)
advantages and disadvantages
- Benefits: the way of synchronization solves the thread safety problem
- Limitations: when operating synchronous code, only one thread can participate and other threads wait, which is equivalent to a single threaded process with low efficiency
Interview questions
- How does Java solve thread safety problems in several ways? And compare the differences of several ways?
- Comparison of synchronized and Lock methods to solve thread safety problems
Thread safe singleton mode (lazy)
class Bank{ private static Bank instance = null; private Bank(){ } public static Bank getInstance() { // Mode 1: slightly poor efficiency /*synchronized (Bank.class) { if (instance == null){ instance = new Bank(); } return instance; }*/ // Mode 2: higher efficiency if (instance == null){ synchronized (Bank.class) { if (instance == null){ instance = new Bank(); } } } return instance; } }
Interview question: write a thread safe singleton mode
- Hungry Han style
- Lazy style
Deadlock problem
Deadlock understanding
Different threads occupy the synchronization resources needed by the other party and do not give up. They are waiting for the other party to give up the synchronization resources they need, forming a thread deadlock
explain
- After a deadlock occurs, there will be no exception or prompt, but all threads are blocked and cannot continue
- When using synchronization, avoid deadlocks
public class ThreadTest { public static void main(String[] args) { StringBuffer s1 = new StringBuffer(); StringBuffer s2 = new StringBuffer(); new Thread(){ @Override public void run() { synchronized (s1){ s1.append("a"); s2.append("1"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (s2){ s1.append("b"); s2.append("2"); System.out.println("s1 = " + s1); System.out.println("s2 = " + s2); } } } }.start(); new Thread(() -> { synchronized (s2){ s1.append("c"); s2.append("3"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (s1){ s1.append("d"); s2.append("4"); System.out.println("s1 = " + s1); System.out.println("s2 = " + s2); } } }).start(); } }
Thread communication
Three methods involved
- wait(): once this method is executed, the current thread enters the blocking state and releases the synchronization monitor
- notify(): once this method is executed, it will wake up one thread that is waiting. If multiple threads are waiting, it will wake up the one with higher priority
- notifyAll(): once this method is executed, all threads that are wait ing will be awakened
explain
- The three methods wait() notify() notifyAll() must be used in the synchronization code block or synchronization method
- The callers of wait() notify() notifyAll() methods must be synchronization code blocks or synchronization monitors in synchronization methods, otherwise an IllegalMonitorStateException will appear
- The three methods wait() notify() notifyAll() are defined in the java.lang.Object class
Interview questions
Similarities and differences between sleep() and wait()
-
Similarities:
- Once the method is executed, the current thread can enter the blocking state
-
difference:
-
The positions of the two method declarations are different: sleep() is declared in the Thread class and wait() is declared in the Object class
-
The requirements for calling are different: sleep() can be called in any required scenario, and wait() must be used in the synchronization code block or synchronization method
-
About whether to release the synchronization monitor: if both methods are used in the synchronization code block or synchronization method, sleep() will not release the lock, and wait() will release the lock
-
Summary
- Operation that releases the lock
- The execution of the synchronization method and synchronization code block of the current thread ends.
- The current thread encountered a break and return in the synchronization code block and synchronization method, which terminated the code block and continued execution of the method.
- The current thread has an unhandled Error or Exception in the synchronization code block and synchronization method, resulting in an abnormal end.
- The current thread executes the wait() method of the thread object in the synchronization code block and synchronization method. The current thread pauses and releases the lock.
- Operation that does not release the lock
- When a thread executes a synchronization code block or synchronization method, the program calls Thread.sleep() and Thread.yield() methods to suspend the execution of the current thread
- When a thread executes a synchronization code block, other threads call the thread's suspend() method to suspend the thread, and the thread will not release the lock (synchronization monitor).
- Try to avoid using suspend() and resume() to control threads
How to create new threads in JDK 5.0
Mode 1
Method 3 of creating thread: implement Callable interface - JDK 5.0 NEW
step
- Create an implementation class that implements Callable
- Implement the call method and declare the operation to be performed by this thread in call()
- Create an implementation class for the Callable interface
- Pass the object of this Callable interface implementation class to the FutureTask constructor as a to create the implementation class of FutureTask
- Pass the FutureTask object as a parameter to the constructor of the Thread class, create the Thread object, and call start()
- Gets the return value of the call() method in the Callable
public class ThreadNew { public static void main(String[] args) { NumTread numTread = new NumTread(); FutureTask future = new FutureTask(numTread); new Thread(future).start(); try { // The return value of get() is the return value of call() overridden by the FutureTask constructor formal parameter Callable implementation class Object sum = future.get(); System.out.println("The sum is:" + sum); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } } class NumTread implements Callable{ @Override public Object call() throws Exception { int sum = 0; for (int i = 0; i <= 100; i++) { if (i % 2 == 0){ System.out.println(i); sum += i; } } return sum; } }
explain:
- How to understand that implementing the Callable interface to create multithreading is more powerful than implementing the Runnable interface to create multithreading
- call() can have a return value
- call() can throw an exception and be caught by external operations to obtain exception information
- Callable supports generics
Mode II
Four ways to create threads: using thread pool
step
- Provides a thread pool for the specified number of threads
- To execute the operation of the specified thread, you need to provide an object that implements the Runnable interface or the Callable interface implementation class
- Close connection pool
public class ThreadPool { public static void main(String[] args) { ExecutorService service = Executors.newFixedThreadPool(10); ThreadPoolExecutor executor = (ThreadPoolExecutor) service; // Set thread pool properties // System.out.println(service.getClass()); // executor.setCorePoolSize(15); // executor.setKeepAliveTime(); // Suitable for Runnable service.execute(new NumberThread()); service.execute(new NumberThread1()); // service.submit(); Suitable for Callable service.shutdown(); } } class NumberThread implements Runnable{ @Override public void run() { for (int i = 0; i <= 100; i++) { if (i % 2 == 0){ System.out.println(Thread.currentThread().getName() + ":" + i); } } } } class NumberThread1 implements Runnable{ @Override public void run() { for (int i = 0; i <= 100; i++) { if (i % 2 != 0){ System.out.println(Thread.currentThread().getName() + ":" + i); } } } }
benefit
- Improved response time (reduced time to create new threads)
- Reduce resource consumption (reuse threads in the thread pool and do not need to be created every time)
- Easy thread management
- corePoolSize: the size of the core pool
- maximumPoolSize: maximum number of threads
- keepAliveTime: how long does the thread last when there is no task, and then it will terminate
Interview question: how many ways to create multithreading in Java? Four kinds
Common class
Use of String class
summary
String: string, represented by a pair of ""
-
String is declared as final and cannot be inherited
-
String implements the Serializable interface: it means that the string supports serialization
String implements the Comparable interface: it means that string can compare sizes
-
final char[] value is defined inside String to store String data
-
Assign a literal value to a string, and the string value is declared in the string constant pool
-
Strings with the same content (compare with equals() of String class and return true) will not be stored in the String constant pool
Immutability of String
explain
-
When the string is re assigned, the assigned memory area needs to be rewritten, and the original value cannot be used value Assign values
-
When connecting an existing string, you also need to assign a new value to the memory area, and the original value cannot be used value Assign values
-
When called String of replace() Method to modify the specified character or string, you also need to reassign the memory area assignment, and the original value cannot be used value Assign values
Code example
@Test public void test1(){ // Definition of literal quantity String s1 = "abc"; String s2 = "abc"; s1 = "hello"; // Compare the address values of s1 and s2 System.out.println("s1 == s2 = " + (s1 == s2)); System.out.println("s1 = " + s1); System.out.println("s2 = " + s2); String s3 = "abc"; s3 += "def"; System.out.println("s3 = " + s3); System.out.println("s2 = " + s2); String s4 = "abc"; String s5 = s4.replace('a', 'm'); System.out.println("s4 = " + s4); System.out.println("s5 = " + s5); }
Illustration
Different methods of String instantiation
Mode description
- Method 1: defined by literal quantity
- Mode 2: through the constructor
Code example
@Test public void test2(){ // Declared in the string constant pool in the method area String s1 = "JavaEE"; String s2 = "JavaEE"; // The saved address value is the corresponding address value after the data is opened up in the heap space String s3 = new String("JavaEE"); String s4 = new String("JavaEE"); System.out.println(s1 == s2); // true System.out.println(s1 == s3); // false System.out.println(s1 == s4); // false System.out.println(s3 == s4); // false }
Interview questions
-
String s = new String(“abc”); To create objects, several objects are created in memory
Two: one is the new structure in the heap space, and the other is the data in the constant pool corresponding to char []: "abc"
Illustration
Comparison of string splicing assignment
explain
- The splicing results of constants and constants are in the constant pool. And constants with the same content will not exist in the constant pool.
- As long as one of them is a variable, the result is in the heap
- If the result of splicing calls the intern() method, the return value is in the constant pool
Code example
@Test public void test3(){ String s1 = "javaEE"; String s2 = "hadoop"; String s3 = "javaEEhadoop"; String s4 = "javaEE" + "hadoop"; String s5 = s1 + "hadoop"; String s6 = "javaEE" + s2; String s7 = s1 + s2; System.out.println(s3 == s4); // true System.out.println(s3 == s5); // false System.out.println(s3 == s6); // false System.out.println(s3 == s7); // false System.out.println(s5 == s6); // false System.out.println(s5 == s7); // false System.out.println(s6 == s7); // false // Return the "Java EE Hadoop" that already exists in the constant value used by s8 String s8 = s5.intern(); System.out.println(s8 == s4); // true }
@Test public void test4(){ String s1 = "javaEEhadoop"; String s2 = "javaEE"; String s3 = s2 + "hadoop"; System.out.println(s1 == s3); final String s4 = "javaEE"; String s5 = s4 + "hadoop"; System.out.println(s1 == s5); }
common method
-
int length(): returns the length of the string: return value.length
-
char charAt(int index): returns the character at an index. return value[index]
-
boolean isEmpty(): judge whether it is an empty string: return value.length == 0
-
String toLowerCase(): converts all characters in a string to lowercase using the default locale
-
String toUpperCase(): converts all characters in a string to uppercase using the default locale
-
String trim(): returns a copy of a string, ignoring leading and trailing whitespace
-
boolean equals(Object obj): compare whether the contents of strings are the same
-
Boolean equalsignorecase (string otherstring): similar to the equals method, case is ignored
-
String concat(String str): concatenates the specified string to the end of this string. Equivalent to "+"
-
Int CompareTo (string otherstring): compares the size of two strings
-
String substring(int beginIndex): returns a new string, which is the last substring of the string intercepted from beginIndex.
-
String substring(int beginIndex, int endIndex): returns a new string, which is a substring intercepted from beginIndex to endIndex (excluding).
-
boolean endsWith(String suffix): tests whether the string ends with the specified suffix
-
boolean startsWith(String prefix): tests whether this string starts with the specified prefix
-
Boolean startswith (string prefix, int tofffset): test whether the substring of this string starting from the specified index starts with the specified prefix
-
Boolean contains (charsequences): returns true if and only if this string contains the specified char value sequence
-
int indexOf(String str): returns the index of the first occurrence of the specified substring in this string
-
int indexOf(String str, int fromIndex): returns the index of the first occurrence of the specified substring in this string, starting from the specified index
-
int lastIndexOf(String str): returns the index of the rightmost occurrence of the specified substring in this string
-
int lastIndexOf(String str, int fromIndex): returns the index of the last occurrence of the specified substring in this string, and reverses the search from the specified index
indexOf and lastIndexOf methods return - 1 if they are not found
-
String replace(char oldChar, char newChar): returns a new string obtained by replacing all oldchars appearing in this string with newChar.
-
String replace(CharSequence target, CharSequence replacement): replaces all substrings of this string that match the literal target sequence with the specified literal replacement sequence.
-
String replaceAll(String regex, String replacement): replace all substrings of this string that match the given regular expression with the given replacement.
-
String replaceFirst(String regex, String replacement): replace this string with the given replacement to match the first substring of the given regular expression.
-
boolean matches(String regex): tells whether the string matches the given regular expression.
-
String[] split(String regex): splits the string according to the matching of the given regular expression.
-
String[] split(String regex, int limit): split the string according to the matching given regular expression. The maximum number is no more than limit. If it exceeds the limit, all the rest will be placed in the last element.
Conversion between String and other structures
Conversion with basic data type and wrapper class
- String -- > basic data type, wrapper class: call the static method of wrapper class: parseXxx(str)
- Basic data type, wrapper class -- > String: call valueOf(xxx) overloaded by String
@Test public void test1(){ String str1 = "123"; int num = Integer.parseInt(str1); String str2 = String.valueOf(num); String str3 = num + ""; System.out.println(str1 == str3); }
Conversion between and char []
- String -- > char []: call toCharArray() of string
- Char [] -- > String: call the constructor of String
@Test public void test2(){ String str1 = "abc123"; char[] charArray = str1.toCharArray(); for (int i = 0; i < charArray.length; i++) { System.out.println(charArray[i]); } char[] arr = new char[]{'h', 'e', 'l', 'l', 'o'}; String str2 = new String(arr); System.out.println(str2); }
Conversion between and byte []
- Code: String -- > byte []: call getBytes() of string
- Decoding: byte [] -- > String: call the constructor of String
Encoding: String -- > bytes
Decoding: encoded inverse process byte -- > string
Note: during decoding, the character set used for decoding must be consistent with the character set used for encoding, otherwise garbled code will appear
@Test public void test3() throws UnsupportedEncodingException { String str1 = "abc123 China"; // Use the default character set for conversion byte[] bytes = str1.getBytes(); System.out.println(Arrays.toString(bytes)); // Encoding using gbk byte[] gbks = str1.getBytes("gbk"); System.out.println(Arrays.toString(gbks)); String str2 = new String(bytes); System.out.println(str2); String str3 = new String(gbks, "gbk"); System.out.println(str3); }
Conversion with StringBuffer and StringBuilder
- String – > StringBuffer, StringBuilder: call the constructor of StringBuffer and StringBuilder
- StringBuffer,StringBuilder -> String:
- Call the constructor of String
- StringBuffer, toString of StringBuilder
Description of storage location of string constant pool in JVM
- JDK6.0: string constant pool is stored in method area (persistent area)
- JDK 7.0: string constant pool stored in heap space
- JDK8.0: string constant pool is stored in method area (meta space)
Examination of performance algorithm questions
- Simulate a trim method to remove spaces at both ends of the string.
public String myTrim(String str) { if (str != null) { // The index used to record the position where the first index position from front to back is not a space int start = 0; // The index used to record the position where the first index position from back to front is not a space int end = str.length() - 1; while (start < end && str.charAt(start) == ' ') { start++; } while (start < end && str.charAt(end) == ' ') { end--; } if (str.charAt(start) == ' ') { return ""; } return str.substring(start, end + 1); } return null; }
- Inverts a string. Inverts the specified part of the string. For example, "abcdefg" is reversed to "abfedcg"
/** * Method 1: convert to char [] * @param str * @param startIndex * @param endIndex * @return */ public String reverseChar(String str, int startIndex, int endIndex){ if (str != null) { char[] arr = str.toCharArray(); for(int x = startIndex, y = endIndex; x < y; x++, y--){ char temp = arr[x]; arr[x] = arr[y]; arr[y] = temp; } return new String(arr); } return null; } /** * Method 2: use String splicing * @param str * @param startIndex * @param endIndex * @return */ public String reverseString(String str, int startIndex, int endIndex){ if (str != null) { String reverseStr = str.substring(0, startIndex); for(int i = endIndex; i >= startIndex; i--){ reverseStr += str.charAt(i); } reverseStr += str.substring(endIndex + 1); return reverseStr; } return null; } /** * Method 3: replace String with StringBuffer / StringBuilder * @param str * @param startIndex * @param endIndex * @return */ public String reverseStringBuilder(String str, int startIndex, int endIndex){ if (str != null) { StringBuilder builder = new StringBuilder(str.length()); builder.append(str.substring(0, startIndex)); for(int i = endIndex; i >= startIndex; i--){ builder.append(str.charAt(i)); } builder.append(str.substring(endIndex + 1)); } return null; }
- Gets the number of occurrences of one string in another string. For example, get the number of occurrences of "ab" in "abkkcadkabkebfkabkskab"
/** * Gets the number of occurrences of subStr in mainStr * @param mainStr * @param subStr * @return */ public int getCount(String mainStr, String subStr){ int mainLength = mainStr.length(); int subLength = subStr.length(); int count = 0; int index = 0; if (mainLength >= subLength){ // Mode 1 /*while ((index = mainStr.indexOf(subStr)) != -1){ count++; mainStr = mainStr.substring(index + subStr.length()); }*/ // Mode II while ((index = mainStr.indexOf(subStr, index)) != -1){ count++; index += subLength; } } return count; }
-
Gets the largest identical substring in two strings. For example, STR1 = "abcwertelloyuodef"; str2 = "cvhellobnm"
Tip: compare the short string with the substring whose length decreases in turn with the longer string.
/** * If there are multiple largest substrings of the same length * At this point, first return String [], and then replace it with ArrayList in the collection, which is more convenient * @param str1 * @param str2 * @return */ public String[] getMaxSameSubString(String str1, String str2) { if (str1 != null && str2 != null) { StringBuffer sBuffer = new StringBuffer(); String maxString = (str1.length() > str2.length()) ? str1 : str2; String minString = (str1.length() > str2.length()) ? str2 : str1; int len = minString.length(); for (int i = 0; i < len; i++) { for (int x = 0, y = len - i; y <= len; x++, y++) { String subString = minString.substring(x, y); if (maxString.contains(subString)) { sBuffer.append(subString + ","); } } // System.out.println(sBuffer); if (sBuffer.length() != 0) { break; } } String[] split = sBuffer.toString().replaceAll(",$", "").split("\\,"); return split; } return null; }
-
Sort the characters in the string in natural order.
Tips:
- The string becomes an array of characters.
- Sort the array, select, bubble, Arrays.sort();
- Turns the sorted array into a string.
StringBuffer,StringBuilder
Comparison of String, StringBuffer and StringBuilder
- String: immutable character sequence; the bottom layer uses char [] storage
- StringBuffer: variable character sequence; thread safe and inefficient; char [] storage is used at the bottom
- StringBuilder: variable character sequence; the new thread in JDK 5.0 is unsafe and efficient; char [] is used at the bottom
Memory parsing of StringBuffer and StringBuilder
Take StringBuffer as an example
String str = new String(); // char[] value = new char[0]; String str = new String("abc"); // char[] value = new char[]{'a', 'b', 'c'}; StringBuffer sb1 = new StringBuffer(); // char[] value = new char[16]; the bottom layer creates an array with a length of 16 sb1.append('a') // value[0] = 'a'; sb1.append('b') // value[1] = 'b'; StringBuffer sb2 = new StringBuffer("abc"); // char[] value = new char["abc".length() + 16];
-
Question 1: System.out.println(sb2.length()); // 3
-
Question 2: capacity expansion: if the underlying array of data to be added cannot hold up, the underlying array needs to be expanded. By default, the capacity expansion is 2 times + 2 of the original capacity, and the elements in the original array are copied to the new array
Guiding significance: it is recommended to use StringBuffer(int capacity) or StringBuilder(int capacity) in development
Compare the execution efficiency of String, StringBuffer and StringBuilder
- From high to low: StringBuilder > StringBuffer > string
Common methods in StringBuffer and StringBuilder
- StringBuffer append(xxx): provides many append() methods for string splicing
- StringBuffer delete(int start,int end): deletes the contents of the specified location
- StringBuffer replace(int start, int end, String str): replace the [start,end) position with str
- StringBuffer insert(int offset, xxx): inserts xxx at the specified position
- StringBuffer reverse(): reverses the current character sequence
- int indexOf(String str)
- String substring(int start,int end): returns a substring of the left closed right open interval from start to end
- int length()
- char charAt(int n)
- void setCharAt(int n ,char ch)
Summary:
- Add: append(xxx)
- Delete: delete(int start, int end)
- Change: setcharat (int n, char CH) / replace (int start, int end, string STR)
- Query: charAt(int n)
- Insert: insert(int offset, xxx)
- Length: length()
- Traversal: for + charAt() / toString()
Date time API before JDK8
Get the current system time
currentTimeMillis() in the System class: returns the time difference in milliseconds between the current time and 0:0:0 on January 1, 1970, which is called the timestamp
java.util.Date class and java.sql.Date class
- Use of two constructors
- Constructor 1: Date(): creates a Date object corresponding to the current time
- Constructor 2: Date(long date): creates a Date object with a specified number of milliseconds
- Use of two methods
- toString(): displays the current year, month, day, hour, minute and second
- getTime(): gets the number of milliseconds (timestamp) corresponding to the current Date object
- java.sql.Date corresponds to variables of database automatic date type
- How to instantiate
- How to convert a java.util.Date object to a java.sql.Date object
@Test public void test2(){ // Constructor 1: Date(): creates a Date object corresponding to the current time Date date1 = new Date(); System.out.println(date1); System.out.println(date1.getTime()); // Constructor 2: Date(long date): creates a Date object with a specified number of milliseconds Date date2 = new Date(1637809383273L); System.out.println(date2); java.sql.Date date3 = new java.sql.Date(99999323820232L); System.out.println(date3); Date date4 = new Date(221223445L); // java.sql.Date date5 = (java.sql.Date) date4; java.sql.Date date5 = new java.sql.Date(date3.getTime()); }
java.text.SimpleDateFormat class
SimpleDateFormat formats and parses the Date class
- Two operations
- Format: date -- > string
- Parsing: formatted inverse process string -- > date
- Instantiation of SimpleDateFormat: constructor
// Format and parse in the specified way: call the constructor with parameters // SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyy.MMMMM.dd GGG hh:mm aaa"); SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); // format System.out.println(sdf1.format(date)); // Parsing: the string must conform to the format recognized by SimpleDateFormat (reflected by constructor parameters), otherwise an exception will be thrown System.out.println(sdf1.parse(sdf1.format(date)));
practice:
/** * Exercise 1: convert the string "2020-09-08" to java.sql.Date * Exercise 2: fishing for three days and drying the net for two days 1990-01-01 XXXX XX fishing and drying the net * Total days% 5 = = 1, 2, 3: Fishing * Total days% 5 = = 4, 0: net drying * Calculation of total days * Method 1: (date2.getTime() - date1.getTime()) / (1000 * 60 * 60 * 24) * Method 2: January 1, 1990 -- > December 31, 2019 + January 1, 2020 -- > September 8, 2020 */ @Test public void testExer() throws ParseException { String birth = "2020-09-08"; SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); Date date = simpleDateFormat.parse(birth); java.sql.Date birthDate = new java.sql.Date(date.getTime()); System.out.println(birthDate); }
Calendar Class: Calendar Class and abstract class
@Test public void testCalendar(){ // 1. Instantiation // Method 1: create an object of its subclass (Gregorian calendar) // Method 2: call its static method getInstance() Calendar calendar = Calendar.getInstance(); // System.out.println(calendar.getClass()); // 2. Common methods // get() int days = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(days); System.out.println(calendar.get(Calendar.DAY_OF_YEAR)); // set() // Calender variability calendar.set(Calendar.DAY_OF_MONTH, 22); System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // add() calendar.add(Calendar.DAY_OF_MONTH, -3); System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // getTime(): Calendar Class -- > date Date date = calendar.getTime(); System.out.println(date); // setTime(): date -- > Calendar Class Date date1 = new Date(); calendar.setTime(date1); System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); }
New date time API in JDK8
Iteration of datetime API
First generation: JDK1.0 Date class
Second generation: JDK1.1 Calendar class, which replaces Date class to some extent
Third generation: JDK1.8 proposes a new API
Examples of problems in the previous two generations
-
Variability: classes like date and time should be immutable.
-
Offset: the year in Date starts from 1900, and the month starts from 0.
-
Formatting: formatting is only useful for Date, but not Calendar.
-
In addition, they are not thread safe; Cannot handle leap seconds, etc.
Packages involved in the new date time API in JDK8
- java.time: base package containing value objects
- java.time.chrono: provides access to different calendar systems
- java.time.format: format and parse time and date
- Java. Time. Temporary: including the underlying framework and extension features
- java.time.zone: contains classes that support time zones
Note: most developers only use the basic package and format package, and may also use the temporary package. Therefore, although there are 68 new public types, most developers will use only about one-third of them.
LocalDate,LocalTime,LocalDateTime
explain
- Represents the date, time, date and time using the ISO-8601 calendar system. They provide a simple local date or time and do not contain current time information or time zone related information.
- LocalDateTime is used more frequently than LocalDate and LocalTime
- Similar to the java.util.Date class
common method
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 |
getHour() / 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 |
plusDays() / plusWeeks() / plusMonth() / 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 |
Point in time: Instant
explain
- An instantaneous point on the timeline. Conceptually, it simply represents the number of milliseconds since 0:0:0 (UTC) on January 1, 1970
- Similar to the java.util.Date class
common method
method | describe |
---|---|
now() | Static method that returns the object of the Instant class of the default UTC time zone |
ofEpochMilli(long epochMilli) | Static method, which returns the object of the Instant class based on 1970-01-01 00:00:00 plus the specified number of milliseconds |
atOfSet(ZoneOfSet ofSet) | Create an OffsetDateTime with an immediate offset |
toEpochMilli() | Returns the number of milliseconds from 1970-01-01 00:00:00 to the current time, which is the timestamp |
Timestamp refers to the total number of seconds from 00:00:00 GMT on January 1, 1970 (08:00:00 GMT on January 1, 1970) to the present.
DateTimeFormatter
explain
- Format or parse date, time
- Similar to SimpleDateFormat
common method
-
Instantiation mode
- Predefined standard formats.
- ISO_LOCAL_DATE_TIME
- ISO_LOCAL_DATE
- ISO_LOCAL_TIME
- Localization related formats. For example: oflocalized datetime (formatstyle. Long)
- Custom format. For example: ofPattern("yyyy MM DD HH: mm: SS")
- Predefined standard formats.
-
common method
method describe ofPattern(String pattern) Static method that returns a DateTimeFormatter in the specified string format format(TemporalAccessor t) Format a date and time and return a string parse(CharSequence text) Parses the character sequence in the specified format into a date and time
Special: custom format. For example: ofPattern("yyyy MM DD HH: mm: SS")
// Method 3: custom format. For example: ofPattern("yyyy MM DD HH: mm: SS") DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); System.out.println(formatter3.format(localDateTime)); TemporalAccessor accessor = formatter3.parse("2021-11-25 21:53:44"); System.out.println(accessor);
Use of other API s
Datetime with time zone: ZonedDateTime / ZoneId
/** * ZoneId: Class contains all time zone information */ @Test public void test4(){ // getAvailableZoneIds(): get the corresponding ZoneId Set<String> zoneIds = ZoneId.getAvailableZoneIds(); for (String zoneId : zoneIds) { System.out.println(zoneId); } System.out.println(); // Get the time corresponding to the "Asia/Tokyo" time zone System.out.println(LocalDateTime.now(ZoneId.of("Asia/Tokyo"))); } /** * ZonedDateTime: Date time with time zone */ @Test public void test5(){ // now(): get the ZonedDateTime object of the current time zone System.out.println(ZonedDateTime.now()); // Now (zoneid): gets the ZonedDateTime object of the specified time zone ZonedDateTime.now(ZoneId.of("Asia/Tokyo")); }
Time interval: Duration
Used to calculate two "time" intervals based on seconds and nanoseconds
method | describe |
---|---|
between(Temporal start, Temporal end) | Static method, which returns the Duration object, representing the interval between two times |
getNano() / getSeconds() | Nanoseconds of return interval / seconds of return interval |
toDays() / toHours() / toMinutes() / toMillis() / toNano() | Returns the number of days, hours, minutes, milliseconds, and nanoseconds of the time interval |
@Test public void test6(){ //Duration: used to calculate two "time" intervals, based on seconds and nanoseconds LocalTime localTime = LocalTime.now(); LocalTime localTime1 = LocalTime.of(15, 23, 32); //between(): a static method that returns a Duration object that represents the interval between two times Duration duration = Duration.between(localTime1, localTime); System.out.println(duration); System.out.println(duration.getSeconds()); System.out.println(duration.getNano()); LocalDateTime localDateTime = LocalDateTime.of(2016, 6, 12, 15, 23, 32); LocalDateTime localDateTime1 = LocalDateTime.of(2017, 6, 12, 15, 23, 32); Duration duration1 = Duration.between(localDateTime1, localDateTime); System.out.println(duration1.toDays()); }
Time interval: Period
Used to calculate the interval between two "dates", measured by year, month and day
method | describe |
---|---|
between(LocalDate start, LocalDate end) | Static method, which returns the Period object, representing the interval between two local dates |
getYears() / getMonths() / getDays() | Returns the number of years, months and days in this period |
withYears(int years) / withMonths(int months) / withDays(int days) | Returns the Period object after the specified year, month and day of the setting interval |
@Test public void test7(){ LocalDate localDate = LocalDate.now(); LocalDate localDate1 = LocalDate.of(2028, 3, 18); Period period = Period.between(localDate, localDate1); System.out.println(period); System.out.println(period.getYears()); System.out.println(period.getMonths()); System.out.println(period.getDays()); Period period1 = period.withYears(2); System.out.println(period1); }
Time corrector: TemporalAdjuster
@Test public void test8(){ // What is the next Sunday to get the current date? TemporalAdjuster temporalAdjuster = TemporalAdjusters.next(DayOfWeek.SUNDAY); LocalDateTime localDateTime = LocalDateTime.now().with(temporalAdjuster); System.out.println(localDateTime); // Get the next working day? LocalDate localDate = LocalDate.now().with(new TemporalAdjuster() { @Override public Temporal adjustInto(Temporal temporal) { LocalDate date = (LocalDate) temporal; if (date.getDayOfWeek().equals(DayOfWeek.FRIDAY)) { return date.plusDays(3); } else if (date.getDayOfWeek().equals(DayOfWeek.SATURDAY)) { return date.plusDays(2); } else { return date.plusDays(1); } } }); System.out.println("The next working day is:" + localDate); }
Java comparator
Use background
Under normal circumstances, objects in Java can only be compared: = = or! =, You can't use > or < but in the development scenario, you need to sort mu lt iple objects. By implication, you need to compare the size of objects. How do you implement it? Use either of the two interfaces: Comparable or Comparator
Natural sorting: using the Comparable interface
explain
- For example, String and wrapper classes implement the Comparable interface, rewrite the compareTo(obj) method, and give a way to compare the sizes of two objects
- For example, after rewriting the compareTo(obj) method for String and wrapper classes, the rules are changed from small to large
- Rules for rewriting compareTo(obj):
- If the current object this is greater than the formal parameter object obj, a positive integer is returned
- If the current object this is less than the formal parameter object obj, a negative integer is returned
- Returns zero if the current object this is equal to the parameter object obj
- For user-defined classes, if sorting is required, the user-defined class can implement the Comparable interface, override the compareTo(obj) method, and specify how to sort in the compareTo(obj) method
Example of custom class code
public class Goods implements Comparable{ private String name; private double price; public Goods() { } public Goods(String name, double price) { this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } @Override public String toString() { return "Goods{" + "name='" + name + '\'' + ", price=" + price + '}'; } /** * Specify the way to compare the size of goods: sort according to the price from low to high, and then sort according to the product name from low to high * @param o * @return */ @Override public int compareTo(Object o) { if (o instanceof Goods){ Goods goods = (Goods) o; // Mode 1 if (this.price > goods.price){ return 1; }else if (this.price < goods.price){ return -1; }else { return this.name.compareTo(goods.name); } // Mode II // return Double.compare(this.price, goods.price); } throw new RuntimeException("The data type passed in is inconsistent"); } }
Custom sorting: using the Comparator interface
explain
-
background
When the element type does not implement the java.lang.Comparable interface and it is inconvenient to modify the code, or the sorting rules that implement the java.lang.Comparable interface are not suitable for the current operation, you can consider using the Comparator object to sort
-
Rewrite the compare(Object o1,Object o2) method to compare the sizes of o1 and o2:
- If a positive integer is returned, o1 is greater than o2;
- If 0 is returned, it means equal;
- If a negative integer is returned, o1 is less than o2
Code example
Comparator comparator = new Comparator() { /** * Sort strings from large to small * @param o1 * @param o2 * @return */ @Override public int compare(Object o1, Object o2) { if (o1 instanceof String && o2 instanceof String){ String s1 = (String) o1; String s2 = (String) o2; return -s1.compareTo(s2); } throw new RuntimeException("The data type entered is inconsistent"); } };
Comparison of two sorting methods
- Once the method of the Comparable interface is fixed, the size of the object of the implementation class of the Comparable interface can be compared at any position
- The Comparator interface is a temporary comparison
Other classes
System class
-
The System class represents the System. Many System level properties and control methods are placed inside this class. This class is located in the java.lang package.
-
Because the constructor of this class is private, the object of this class cannot be created, that is, the class cannot be instantiated. Its internal member variables and member methods are static, so they can also be called conveniently.
-
method
-
native long currentTimeMillis(): the function of this method is to return the current computer time. The expression format of time is the milliseconds difference between the current computer time and GMT time (Greenwich mean time) at 0:0:0:0 on January 1, 1970.
-
void exit(int status): this method is used to exit the program. The value of status is 0, which represents normal exit, and non-zero represents abnormal exit. Using this method, the exit function of the program can be realized in the graphical interface programming.
-
void gc(): this method is used to request the system for garbage collection. Whether the system recycles immediately depends on the implementation of the garbage collection algorithm in the system and the execution of the system.
-
String getProperty(String key): this method is used to obtain the value corresponding to the property named key in the system. The common attribute names and functions in the system are shown in the following table:
Attribute name Attribute description java.version Java runtime environment version java.home Java installation directory os.name The name of the operating system os.version Operating system version user.name User's account name user.home User's home directory user.dir User's current working directory
-
Math class
java.lang.Math provides a series of static methods for scientific computing. The parameter and return value types of the method are generally double.
BigInteger class, BigDecimal class
explain:
- The BigInteger of the java.math package can represent immutable integers of arbitrary precision.
- It requires high digital accuracy, so java.math.BigDecimal class is used
Code example:
@Test public void testBigInteger() { BigInteger bi = new BigInteger("12433241123"); BigDecimal bd = new BigDecimal("12435.351"); BigDecimal bd2 = new BigDecimal("11"); System.out.println(bi); // System.out.println(bd.divide(bd2)); System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP)); System.out.println(bd.divide(bd2, 25, BigDecimal.ROUND_HALF_UP)); }
Enumeration classes and annotations
Enumeration class
Declaration of enumeration class
- Understanding of enumeration classes: there are only a limited number of objects in a class. If it is certain, this class is called enumeration class
- Enumeration classes are strongly recommended when you need to define a set of constants
- If there is only one object in the enumeration class, it can be used as an implementation of singleton mode
How to customize enumeration classes
Custom enumeration classes before JDK5.0
// Custom enumeration class class Season{ // 1. Declare the attribute of the Season object and modify it with private final private final String seasonName; private final String seasonDesc; // 2. Constructor of privatization class private Season(String seasonName, String seasonDesc){ this.seasonName = seasonName; this.seasonDesc = seasonDesc; } // 3. Provide multiple objects of the current enumeration class: public static final public static final Season SPRING = new Season("spring", "in the warm spring , flowers are coming out with a rush"); public static final Season SUMMER = new Season("summer", "Summer heat"); public static final Season AUTUMN = new Season("autumn", "fresh autumn weather"); public static final Season WINTER = new Season("winter", "a world of ice and snow"); // 4. Other requirements 1: get the properties of enumeration objects public String getSeasonName() { return seasonName; } public String getSeasonDesc() { return seasonDesc; } // 4. Other claims 2: toString() @Override public String toString() { return "Season{" + "seasonName='" + seasonName + '\'' + ", seasonDesc='" + seasonDesc + '\'' + '}'; } }
JDK5.0, adding enum keyword to define enumeration class
// Define enumeration classes using enum keyword enum Season1{ // 1. Provide the object of the current enumeration class. Multiple objects are separated by commas SPRING("spring", "in the warm spring , flowers are coming out with a rush"). SUMMER("summer", "Summer heat"), AUTUMN("autumn", "fresh autumn weather"), WINTER("winter", "a world of ice and snow"); // 2. Declare the attribute of the Season object and modify it with private final private final String seasonName; private final String seasonDesc; // 3. Constructor of privatization class Season1(String seasonName, String seasonDesc){ this.seasonName = seasonName; this.seasonDesc = seasonDesc; } // 4. Other requirements 1: get the properties of enumeration objects public String getSeasonName() { return seasonName; } public String getSeasonDesc() { return seasonDesc; } }
Common methods in enumeration classes
Inherited from java.lang.Enum class
- values(): returns an array of objects of enumeration type. This method can easily traverse all enumeration values.
- valueOf(String str): you can convert a string into a corresponding enumeration class object. The required string must be the name of an enumeration class object. If not, there will be a runtime exception: IllegalArgumentException.
- toString(): returns the name of the object constant of the current enumeration class
public static void main(String[] args) { Season1 summer = Season1.SUMMER; System.out.println(summer); System.out.println(Season1.class.getSuperclass()); // values() Season1[] values = Season1.values(); for (Season1 value : values) { System.out.println(value); } for (Thread.State value : Thread.State.values()) { System.out.println(value); } // valueOf(String objName): returns the object whose object name is objName in the enumeration class // If there is no enumeration class object of objName, throw the exception illegalargumenceexception Season1 winter = Season1.valueOf("WINTER"); System.out.println(winter); }
The implementation of the interface using the enum class defined by the enum keyword
- Scenario 1: implement the interface and implement the abstract method in the enum class
- Case 2: let the enumeration class objects implement the abstract methods in the interface respectively
interface Info{ void show(); } // Define enumeration classes using enum keyword enum Season1 implements Info{ // 1. Provide the object of the current enumeration class. Multiple objects are separated by commas SPRING("spring", "in the warm spring , flowers are coming out with a rush"){ @Override public void show() { System.out.println("Where is spring"); } }, SUMMER("summer", "Summer heat") { @Override public void show() { System.out.println("Ningxia"); } }, AUTUMN("autumn", "fresh autumn weather") { @Override public void show() { System.out.println("Autumn doesn't come back"); } }, WINTER("winter", "a world of ice and snow") { @Override public void show() { System.out.println("About winter"); } }; // 2. Declare the attribute of the Season object and modify it with private final private final String seasonName; private final String seasonDesc; // 3. Constructor of privatization class Season1(String seasonName, String seasonDesc){ this.seasonName = seasonName; this.seasonDesc = seasonDesc; } // 4. Other requirements 1: get the properties of enumeration objects public String getSeasonName() { return seasonName; } public String getSeasonDesc() { return seasonDesc; } }
annotation
Understanding Annotation
-
JDK5.0 NEW
-
Annotation is actually a special tag in the code. These tags can be read during compilation, class loading and runtime, and perform corresponding processing. By using annotation, programmers can embed some supplementary information in the source file without changing the original logic
-
In Java se, annotations are used for simple purposes, such as marking outdated functions, ignoring warnings, etc. Annotations play a more important role in Java EE / Android, such as configuring any aspect of the application, replacing the cumbersome code and XML configuration left over from the old version of Java EE
Framework = annotation + reflection mechanism + design pattern
Usage examples of Annotation
- Example 1: generate document related annotations
- Example 2: format checking at compile time (JDK has three built-in basic annotations)
- @Override: restrict overriding parent class methods. This annotation can only be used for methods
- @Deprecated: used to indicate that the modified element (class, method, etc.) is obsolete. Usually because the modified structure is dangerous or there is a better choice
- @SuppressWarnings: suppress compiler warnings
- Example 3: tracking code dependencies and implementing alternative profile functions
How to customize annotations
Refer to @ SuppressWarings definition
step
- Annotation declared as @ interface
- Internally defined members, usually represented by value
- You can specify the default value of the member, which is defined by default
- If the user-defined annotation has no members, it indicates that it is an identification function
Code example
@Inherited @Repeatable(MyAnnotations.class) @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.LOCAL_VARIABLE, ElementType.TYPE_PARAMETER, ElementType.TYPE_USE }) public @interface MyAnnotation { String value() default "hello"; }
explain:
- If the annotation has members, you need to specify the value of the member when using the annotation
- Custom annotations must be accompanied by an annotation's information processing flow (using reflection) to be meaningful
- Custom annotations usually indicate two meta annotations: retention target
Meta annotation
Meta annotation: an annotation that explains existing annotations
- Retention: Specifies the life cycle of the modified Annotation: source class (default) RUNTIME. Only annotations declared as RUNTIME life cycle can provide reflection acquisition
- Target: used to specify which program elements can be modified by the modified Annotation
- Documented: indicates that the modified annotation is retained during Javadoc parsing
- Inherited: the Annotation modified by it will be inherited
How to get annotation information
Get annotation information through reflection
Premise: the lifecycle state declared in the meta annotation Retention of this annotation is required to be: RUNTIME
New features of annotations in JDK8
Repeatable annotation
- Declare @ Repeatable on MyAnnotation, and the member value is MyAnnotations.class
- Meta annotations such as Target and Retention of MyAnnotation must be the same as MyAnnotations
type annotation
- ElementType.TYPE_PARAMETER indicates that the annotation can be written in the declaration statement of type variables (such as generic declaration).
- ElementType.TYPE_USE indicates that the annotation can be written in any statement using the type
aggregate
Arrays and collections
Overview of the collection framework
Collections and arrays are structures that store multiple data, referred to as Java containers for short
Note: storage at this time mainly refers to memory level storage, and does not involve persistent storage (. TXT,. JPG,. Avi, in the database)
Characteristics of array in storage
-
Once initialized, its length is determined
-
Once an array is defined, its element type is determined, and it can only operate on data of the specified type
For example: String[] arr int[] arr;
Disadvantages of data storage
-
Once initialized, its length cannot be modified
-
The methods provided in the array are very limited, which is very inconvenient for operations such as adding, deleting and inserting data
-
The requirement to obtain the number of actual elements in the array. There are no ready-made properties or methods available in the array
-
The characteristics of array data storage: orderly and repeatable. For disordered and non repeatable requirements, array can not meet
Advantages of collective storage
- Solve the disadvantages of array data storage
Collection framework
|---- Collection Interface: a single column collection used to store data one by one |---- List Interface: store ordered and repeatable data --> "dynamic"array |---- ArrayList |---- LinkedList |---- Vector |---- Set Interface: stores unordered and unrepeatable data --> High school"Assemble“ |---- HashSet |---- LinkedHashSet |---- TreeSet |---- Map Interface: a two column set used to store a pair of data( key : value)A pair of data --> High school function: y = f(x) |---- HashMap |---- LinkedHashMap |---- TreeMap |---- HashTable |---- Properties
Collection interface
Single column set frame structure
|---- Collection Interface: a single column collection used to store data one by one |---- List Interface: store ordered and repeatable data --> "dynamic"array |---- ArrayList |---- LinkedList |---- Vector |---- Set Interface: stores unordered and unrepeatable data --> High school"Assemble“ |---- HashSet |---- LinkedHashSet |---- TreeSet
Corresponding figure:
Common methods of Collection interface
- add(Object obj): adds the element obj to the element collection
- Add all (collection Collection): adds elements from the collection collection to the current collection
- size(): gets the number of added elements
- isEmpty(): judge whether the current collection is empty
- clear(): clear collection elements
- contains(Object obj): judge whether obj is included in the current collection. When judging, equals() of the class where the obj object is located will be called
- containsAll(Collection collection): judge whether all elements in the formal parameter collection exist in the current collection
- remove(Object obj): removes obj elements from the current collection
- removeAll(Collection collection): subtraction, which removes all elements in the collection from the current collection
- retainsAll(Collection collection): intersection. Get the intersection of the current collection and the collection collection and return it to the current collection
- equals(Object obj): to return true, it is necessary to judge that the elements of the current set and the parameter set are the same
- hashCode(): returns the hash value of the current object
- toArray(): convert a collection to an array
- iterator() returns the iterator of the elements in this collection
Conversion between Collection and array
// 8.toArray(): convert a collection to an array Object[] arr = collection.toArray(); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } // Extension: converting an array to a collection: calling the static method asList() of the Arrays class List<String> list = Arrays.asList(new String[] {"aa", "bb", "cc"}); System.out.println(list);
Use the Collection collection to store objects. The class to which the object belongs must meet the requirements
- When adding data obj to the object of the implementation class of the Collection interface, the class of obj is required to override equals()
requirement
- Level 1: select the appropriate collection class to save the data and call its internal related methods
- Level 2: what is the underlying data structure of different collection classes? How to implement data operations: add, delete, modify, query, etc
Iterator interface and foreach loop
Two ways to traverse a Collection
- Using Iterator iterator
- foreach loop (or enhanced for loop)
Iterator interface defined under java.utils package: iterator
explain
- The Iterator object is called an Iterator (a kind of design pattern) and is mainly used to traverse the elements in the Collection.
- GOF defines the iterator pattern as providing a way to access each element in a container object without exposing the internal details of the object. The iterator pattern is born for containers.
- Internal method: hasNext() next()
- Every time a collection object calls the iterator() method, it gets a new iterator object, and the default cursor is before the first element of the collection.
- remove() is defined internally, which can delete the elements in the collection during traversal. This method is different from calling remove() directly from the collection
effect
Traversing Collection elements
How to get an instance
collection.iterator() returns an iterator instance
Code implementation of traversal
Iterator iterator = collection.iterator(); // hasNext(): judge whether there will be the next element while (iterator.hasNext()){ // next(): the pointer moves down; Returns the element at the collection position after moving down System.out.println(iterator.next()); }
Illustration
Use of remove()
// If next() has not been called or the remove method has been called since the next method was last called, // Calling remove again will report IllegalStateException. // remove() is defined internally, which can delete the elements in the collection during traversal. This method is different from calling remove() directly from the collection @Test public void test3() { Collection collection = new ArrayList(); collection.add(123); collection.add(456); collection.add(new Person("Jerry", 20)); collection.add(new String("Tom")); collection.add(false); Iterator iterator = collection.iterator(); // Delete "Tom" data in the collection while (iterator.hasNext()){ Object obj = iterator.next(); if ("Tom".equals(obj)){ iterator.remove(); } } iterator = collection.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } }
What's new in JDK5 – enhanced for loop: (foreach loop)
Traversal set example
@Test public void test1() { Collection collection = new ArrayList(); collection.add(123); collection.add(456); collection.add(new Person("Jerry", 20)); collection.add(new String("Tom")); collection.add(false); // For (type of element in the collection local variable: collection object) // The iterator is still called internally for(Object obj : collection){ System.out.println(obj); } }
Note: the iterator is still called internally
Traversal array example
@Test public void test2(){ int[] arr = new int[]{1, 2, 3, 4, 5, 6}; for (int a : arr){ System.out.println(a); } }
Collection sub interface: List interface
Characteristics of stored data
Store ordered, repeatable data
common method
- Add: add(Object obj)
- Delete: remove(int index) / remove(Object obj)
- Change: set(int index, Object ele)
- Query: get(int index)
- Insert: add(int index, Object ele)
- Length: size()
- ergodic
- Iterator iterator mode
- Enhanced for loop
- Normal for loop
Common implementation classes
|---- Collection Interface: a single column collection used to store data one by one |---- List Interface: store ordered and repeatable data --> "dynamic"Array, replacing the original array |---- ArrayList As List Main implementation classes of interface Unsafe thread and high efficiency Bottom use Object[] elementData storage |---- LinkedList For frequent inserts and deletions, use this efficiency ratio ArrayList high The underlying uses bidirectional list storage |---- Vector As List Interface implementation class Thread safety and low efficiency Bottom use Object[] elementData storage
Source code analysis
-
Source code analysis of ArrayList
-
In case of JDK7
ArrayList list = new ArrayList(); // The bottom layer creates an Object [] array elementData with a length of 10
list.add(123); // elementData[0] = new Integer(123);
...
list.add(11); // If the capacity of the underlying elementData array is insufficient due to this addition, the capacity will be expanded. By default, the capacity will be expanded to 1.5 times the original capacity. At the same time, the data in the original array needs to be copied to the new arrayConclusion: it is recommended to use a constructor with parameters in development: ArrayList = ArrayList (int initialCapacity);
-
Changes in JDK8
ArrayList list = new ArrayList(); // The underlying Object[] elementData = {} does not create an array with a length of 10
list.add(123); // The first time add() is called, the underlying layer creates an array with a length of 10 and adds the data to elementData
...
Subsequent addition and expansion operations are the same as JDK7
-
Summary
- The object creation of ArrayList in JDK7 is similar to the starving Han style of singleton
- The object creation of ArrayList in JDK8 is similar to the lazy type of singleton, which delays the creation of array and saves memory
-
-
-
LinkedList source code analysis
LinkedList list = new LinkedList(); // The first and last attributes of Node type are declared internally, and the default value is null
list.add(123); // Encapsulate 123 into Node and create Node object
Node is defined as a two-way linked list that embodies LinkedList
private static class Node<E> { E item; Node<E> next; Node<E> prev; Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } }
-
Source code analysis of Vector
When creating an object through the Vector() constructor, the bottom layer creates an array with a length of 10. When expanding the inverse code, the default expansion is twice the length of the original array
Requirements for stored elements
The class of the added object should override equals()
Interview question: what are the similarities and differences among ArrayList, LinkedList and Vector?
- Same: the three classes implement the List interface, and the characteristics of storing data are the same: storing orderly and repeatable data
- different
- ArrayList
- As the main implementation class of the List interface
- Unsafe thread and high efficiency
- The underlying layer uses Object[] elementData storage
- LinkedList
- For frequent inserts and deletions, using this class is more efficient than ArrayList
- The underlying uses bidirectional list storage
- Vector
- As an implementation class of the List interface
- Thread safety and low efficiency
- The underlying layer uses Object[] elementData storage
- ArrayList
Collection sub interface: Set interface
Characteristics of stored data
- Disorder
- Non repeatability
concrete:
Take HashSet as an example
- Disorder: not equal to randomness. The stored data is not added in the order of array index in the underlying array, but determined according to the hash value of the data
- Non repeatability: ensure that when the added element is judged according to equals(), it cannot return true, that is, only one element can be added to the same element
Element addition process
Take HashSet as an example
- To add element a to the HashSet, first call the hashCode() method of the class where element a is located to calculate the hash value of element a, and then calculate the storage position (i.e. index position) in the underlying array of the HashSet through some algorithm to judge whether there are elements in this position of the array
- If there are no other elements in this position, element a is added successfully -- > case 1
- If there are other elements b (or multiple elements in the form of a linked list) at this location, compare the hash values of element a and element b
- If the hash values are different, element a is added successfully -- > case 2
- If the hash values are the same, you need to call the equals() method of the class where element a is located
- equals() returns true, element a addition failed
- equals() returns false, element a is added successfully -- > case 3
- For cases 2 and 3 where the addition is successful, element a and the data already existing at the specified index position are stored in a linked list
- JDK7: put element a into the array and point to the original element
- JDK8: put the original element into the array and point to element a
- Conclusion: seven up and eight down
common method
There are no new methods defined in the Set interface, but all the methods declared in the Collection are used
Common implementation classes
|---- Collection Interface: a single column collection used to store data one by one |---- Set Interface: stores unordered and unrepeatable data --> High school"Assemble“ |---- HashSet As Set Main implementation classes of interface Thread unsafe Can store null value |---- LinkedHashSet As HashSet While adding data, each data also maintains two references, Record the previous and subsequent data of this data When traversing its internal data, it can be traversed in the order of addition For frequent traversal operations: LinkedHashSet Higher efficiency HashSet |---- TreeSet You can sort according to the specified attributes of the added object
Use of TreeSet
instructions
- The data added to the TreeSet must be objects of the same class
- There are two sorting methods: comparable and comparator
Common sorting methods
-
Natural sorting
@Test public void test1(){ TreeSet set = new TreeSet(); // Failed: cannot add objects of different classes // set.add(456); // set.add(123); // set.add("AA"); // set.add("CC"); // set.add(new User("Tom", 12)); // set.add(34); // set.add(-34); // set.add(43); // set.add(11); // set.add(8); set.add(new User("Tom", 12)); set.add(new User("Jerry", 32)); set.add(new User("Jim", 22)); set.add(new User("Mike", 65)); set.add(new User("Jack", 33)); set.add(new User("Jack", 56)); Iterator iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } }
-
Custom sorting
@Test public void test2() { Comparator comparator = new Comparator() { /** * Arranged from small to large according to age * @param o1 * @param o2 * @return */ @Override public int compare(Object o1, Object o2) { if (o1 instanceof User && o2 instanceof User){ User u1 = (User) o1; User u2 = (User) o2; return Integer.compare(u1.getAge(), u2.getAge()); } throw new RuntimeException("The data types entered do not match"); } }; TreeSet set = new TreeSet(comparator); set.add(new User("Tom", 12)); set.add(new User("Jerry", 32)); set.add(new User("Jim", 22)); set.add(new User("Mike", 65)); set.add(new User("Jack", 33)); set.add(new User("Jack", 56)); Iterator iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } }
Requirements for stored elements
-
HashSet / LinkedHashSet
-
The class of data added to Set(HashSet / LinkedHashSet) must override hashCode() and equals()
-
requirement
-
Overridden hashCode() and equals() are as consistent as possible: equal objects must have equal hash codes
-
Tip for rewriting two methods: the fields in the object used for the equals() method comparison should be used to calculate the hashCode value.
-
-
-
TreeSet
- In natural sorting, the standard for comparing whether two objects are the same is: compareTo() returns 0, no longer equals()
- In custom sorting, the criteria for comparing whether two objects are the same is: compare() returns 0 instead of equals()
Map interface
Common implementation class structure
|---- Map: Dual column data, storage key-value Right data --> Similar to high school function: y = f(x) |---- HashMap As Map Main implementation classes of Thread is unsafe and efficient storage null of key and value |---- LinkedHashMap Guaranteed in traversal map Elements can be traversed in the order they are added Reason: in the original HashMap Based on the underlying structure, a pair of pointers are added to point to the previous and subsequent elements For frequent traversal operations, this kind of execution efficiency is higher than HashMap |---- TreeMap Ensure that the added key-value Sort and realize sorting traversal. At this time, consider key Natural sorting and custom sorting Red and black trees are used at the bottom |---- Hashtable As Map Ancient implementation class Thread safe and inefficient Cannot store null of key and value |---- Properties Commonly used to process configuration files key and value All String type
Bottom layer of HashMap:
- JDK7 and before: array + linked list
- JDK8: array + linked list + red black tree
Interview questions:
- Underlying implementation principle of HashMap
- Similarities and differences between HashMap and Hashtable
- Similarities and differences between CurrentHashMap and Hashtable (not for the time being)
Understanding of storage structure
Keys in Map: unordered and non repeatable. Use Set to store all keys -- > the class where the key is located should override equals() and hashCode()
Value in Map: ordered and repeatable. Use Collection to store all values -- > the class where value is located should override equals()
A key value pair: key value constitutes an Entry object
Entries in Map: unordered and non repeatable. Set is used to store all entries
Illustration:
common method
- Add: put(Object key,Object value)
- Delete: remove(Object key)
- Change: put(Object key,Object value)
- Query: get(Object key)
- Length: size()
- Traversal:
- keySet()
- values()
- entrySet()
Memory structure description
Implementation principle of HashMap in JDK7
- HashMap map = new HashMap();
After instantiation, the bottom layer creates a one-dimensional array Entry[] table with a length of 16 - ... may have been executed multiple times
- map.put(key1, value1)
First, call hashCode() of the class where key1 is located to calculate the hash value of key1. After the hash value is calculated by some algorithm, the position stored in the Entry array is obtained- If the data in this location is empty, key1-value1 is added successfully -- > case 1
- If the data in this location is not empty, (which means that there are one or more data in this location (in the form of linked list)), compare the hash values of key1 and one or more existing data
- If the hash value of key1 is different from the hash value of existing data, key1-value1 is added successfully -- > case 2
- If the hash value of key1 is the same as that of an existing data (key2-value2), continue the comparison: call the equals(key2) method of the class where key1 is located and compare
- If equals() returns false: key1-value1 is added successfully -- > case 3
- If equals() returns true: replace value2 with value1
About case 2 and case 3: key1-value1 and the original data are stored in a linked list
During the continuous addition process, the problem of capacity expansion will be involved. The default capacity expansion method is to double the original capacity and copy the original data
The underlying implementation of HashMap in JDK8 is different from that in JDK7
- new HashMap(): the underlying layer does not create an array with a length of 16
- The underlying array of JDK8 is: Node [], not Entry []
- When the put() method is called for the first time, the underlying layer creates an array with a length of 16
- The underlying structure of JDK7 is only array + linked list. The underlying structure of JDK8 is array + linked list + red black tree
- When forming a linked list, seven up and eight down
- JDK7: the new element points to the old element
- JDK8: Old element points to new element
- When the number of data in the form of linked list of elements at an index position of the array is greater than 8 and the current array length exceeds 64, all data at this index position will be stored in red black tree instead
- When forming a linked list, seven up and eight down
Description of the underlying typical attributes of HashMap
- DEFAULT_ INITIAL_ Capability: default capacity of HashMap, 16
- DEFAULT_LOAD_FACTOR: default load factor of HashMap: 0.75
- threshold: critical value of expansion, = capacity * filling factor 16 * 0.75 = 12
- TREEIFY_THRESHOLD: if the length of the linked list in the Bucket is greater than the default value, it will be converted into a red black tree: 8
- MIN_ TREEIFY_ Capability: minimum hash table capacity when nodes in the bucket are trealized: 64
Underlying implementation principle of LinkedHashMap
The underlying structure of LinkedHashMap is the same as that of HashMap, because LinkedHashMap inherits from HashMap. The difference is that LinkedHashMap provides an Entry to replace the Node in HashMap
Node s in HashMap:
static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; V value; Node<K,V> next; Node(int hash, K key, V value, Node<K,V> next) { this.hash = hash; this.key = key; this.value = value; this.next = next; } public final K getKey() { return key; } public final V getValue() { return value; } public final String toString() { return key + "=" + value; } public final int hashCode() { return Objects.hashCode(key) ^ Objects.hashCode(value); } public final V setValue(V newValue) { V oldValue = value; value = newValue; return oldValue; } public final boolean equals(Object o) { if (o == this) return true; if (o instanceof Map.Entry) { Map.Entry<?,?> e = (Map.Entry<?,?>)o; if (Objects.equals(key, e.getKey()) && Objects.equals(value, e.getValue())) return true; } return false; } }
Entry in LinkedHashMap
static class Entry<K,V> extends HashMap.Node<K,V> { Entry<K,V> before, after; // It can record the order of adding elements Entry(int hash, K key, V value, Node<K,V> next) { super(hash, key, value, next); } }
Use of TreeMap
Adding key value to TreeMap requires that the key must be an object created by the same class, because it needs to be sorted by key: natural sorting and customized sorting
Read configuration file using Properties
It is often used to process attribute files. key and value are string types
public static void main(String[] args) { FileInputStream fileInputStream = null; try { Properties prop = new Properties(); fileInputStream = new FileInputStream("jdbc.properties"); prop.load(fileInputStream); String name = prop.getProperty("name"); String password = prop.getProperty("password"); System.out.println("name = " + name); System.out.println("password = " + password); } catch (IOException e) { e.printStackTrace(); } finally { if (fileInputStream != null) { try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
Use of Collections tool class
effect
Tool classes for manipulating Collection and Map
common method
- reverse(List): reverses the order of elements in the List
- shuffle(List): randomly sort the elements of the List collection
- sort(List): sorts the elements of the specified List set in ascending order according to the natural order of the elements
- sort(List, Comparator): sort the List collection elements according to the order generated by the specified Comparator
- swap(List, int, int): exchange the elements at i and j in the specified list set
- Object max(Collection): returns the largest element in a given collection according to the natural order of elements
- Object max(Collection, Comparator): returns the largest element in a given collection according to the order specified by the Comparator
- Object min(Collection): returns the smallest element in a given collection according to the natural order of elements
- Object min(Collection, Comparator): returns the smallest element in a given collection according to the order specified by the Comparator
- int frequency(Collection, Object): returns the number of occurrences of the specified element in the specified collection
- void copy(List dest, List src): copy the contents of src to dest
- Boolean replaceall (List, Object oldVal, Object newVal): replaces all old values of the List object with new values
Note: both ArrayList and HashMap are thread unsafe. If the program requires thread safety, you can convert ArrayList and HashMap to thread safe and use synchronized list (list) and synchronized map (map)
Interview questions
Differences between Collections and Collections
Brief description of data structure
summary
Data Structure is a subject closely related to computer hardware and software. Its research focus is to explore how to organize and store data in computer and use it efficiently in the field of computer programming. The contents include: logical relationship of data, storage structure of data, sorting Algorithm and search (or search) etc.
Understanding of data structures and algorithms
**Whether the program can complete the predetermined task quickly and efficiently depends on whether the data structure is selected correctly, and whether the program can solve the problem clearly and correctly depends on the algorithm. * * the algorithm is the essence of computer processing information, because the computer program is essentially an algorithm to tell the computer the exact steps to perform a specified task.
So people think: "Algorithms + Data Structures = Programs" (from Nicklaus Wirth, father of Pascal)
Conclusion: the algorithm is designed to solve practical problems, and the data structure is the problem carrier that the algorithm needs to deal with.
Research object of data structure
Logical structure between data

Data storage structure
- Linear list (sequential list, linked list, stack, queue)
- tree
- chart
explain:
- It is customary to regard sequential lists and linked lists as basic data structures (or real data structures)
- Traditionally, stack, queue, tree and graph are regarded as abstract data types, abbreviated as ADT
generic paradigm
Understanding of generics
Concept of generics
The so-called genericity is to allow an identifier to represent the type of a property in the class or the return value and parameter type of a method when defining a class or interface. This type parameter will be determined when using (for example, inheriting or implementing the interface, declaring variables and creating objects with this type) (that is, passing in the actual type parameter, also known as type argument).
Introduction background of generics
The collection container class cannot determine what kind of objects actually exist in the container at the design / declaration stage, so it can only design the element type as Object before JDK1.5, and use generics to solve it after JDK1.5. At this time, other parts are determined, such as how to save and manage the element Yes, so at this time, the type of the element is designed as a parameter, which is called generic. Collection, List and ArrayList are type parameters, that is, generic.
Use of generics in Collections
Examples before using generics in Collections
@Test public void test1(){ ArrayList list = new ArrayList(); list.add(78); list.add(77); list.add(89); list.add(88); // Problem 1: unsafe type // list.add("Tom"); for (Object score : list) { // Problem 2: ClassCastException may occur during forced rotation int stuScore = (int) score; System.out.println(stuScore); } }
Illustration:
Using generics in a collection example 1
@Test public void test2(){ // ArrayList<Integer> list = new ArrayList<Integer>(); // New feature of JDK7: type inference ArrayList<Integer> list = new ArrayList<>(); list.add(78); list.add(87); list.add(99); list.add(65); // When compiling, type checking will be carried out to ensure the safety of data // list.add("65"); /*for(Integer score : list){ // Strong rotation operation is avoided int stuScore = score; System.out.println(stuScore); }*/ Iterator<Integer> iterator = list.iterator(); while (iterator.hasNext()){ int stuScore = iterator.next(); System.out.println(stuScore); } }
Illustration:
Use generic example 2 in a collection
@Test public void test3(){ Map<String, Integer> map = new HashMap<>(); map.put("Tom", 87); map.put("Jerry", 87); map.put("Jack", 67); // map.put(123, "67"); Set<Map.Entry<String, Integer>> entry = map.entrySet(); Iterator<Map.Entry<String, Integer>> iterator = entry.iterator(); while (iterator.hasNext()){ Map.Entry<String, Integer> e = iterator.next(); String key = e.getKey(); Integer value = e.getValue(); System.out.println(key + " --- " + value); } }
Using generic summaries in Collections
- In JDK 5.0, the collection interface or collection class is modified to a generic structure
- When instantiating a collection class, you can specify a specific generic type
- After specifying, when defining a class or interface in a collection class or interface, the location where the generic type of the class is used by the internal structure (method, constructor, attribute, etc.) is specified as the instantiated generic type. For example: add (e e) - > after instantiation: add(Integer e)
- Note: the generic type must be a class, not a basic data type. You need to use the location of the basic data type and replace it with a wrapper class
- If the generic type is not specified during instantiation, the default type is java.lang.Object
Custom generic class, generic interface, generic method
give an example
[Order.java]
public class Order<T> { String orderName; int orderId; // The internal structure of the class can use the generics of the class T orderT; public Order(){ // Compilation failed // T[] arr = new T[10]; // Compile passed T[] arr = (T[]) new Object[10]; } public Order(String orderName, int orderId, T orderT) { this.orderName = orderName; this.orderId = orderId; this.orderT = orderT; } public String getOrderName() { return orderName; } public void setOrderName(String orderName) { this.orderName = orderName; } public int getOrderId() { return orderId; } public void setOrderId(int orderId) { this.orderId = orderId; } public T getOrderT() { return orderT; } public void setOrderT(T orderT) { this.orderT = orderT; } @Override public String toString() { return "Order{" + "orderName='" + orderName + '\'' + ", orderId=" + orderId + ", orderT=" + orderT + '}'; } // Generics of classes cannot be used in static methods /*public static void show(){ System.out.println(orderT); }*/ public void show(){ // Compilation failed /*try { }catch (T t){ }*/ } // Generic method: the generic structure appears in the method, and the generic parameters have nothing to do with the generic parameters of the class // In other words, it doesn't matter whether a generic method belongs to a generic class or not // Generic methods can be declared static because generic parameters are determined when the method is called, not when the class is instantiated public static <E> List<E> copyFromArrayToList(E[] arr){ ArrayList<E> list = new ArrayList<>(); for (E e : arr) { list.add(e); } return list; } }
[SubOrder.java]
public class SubOrder extends Order<Integer> { public static <E> List<E> copyFromArrayToList(E[] arr){ ArrayList<E> list = new ArrayList<>(); for (E e : arr) { list.add(e); } return list; } }
[SubOrder1.java]
public class SubOrder1<T> extends Order<T>{ }
Test:
public class GenericTest1 { @Test public void test1(){ // If a generic class is defined and the instantiation does not specify the generic type of the class, the generic type is considered to be Object type // Requirement: if the defined class is generic, it is recommended to specify the generic type of the class when instantiating Order order = new Order(); order.setOrderT(123); order.setOrderT("123"); // Suggestion: specify the generic type of the class when instantiating Order<String> order1 = new Order<>("orderAA", 1001, "order:AA") ; order1.setOrderT("AA:hello"); } @Test public void test2(){ // Since the subclass specifies the generic type when inheriting the parent class with generic type, it is no longer necessary to specify the generic type when instantiating the subclass object SubOrder subOrder = new SubOrder(); subOrder.setOrderT(1122); SubOrder1<String> subOrder1 = new SubOrder1<>(); subOrder1.setOrderT("order2..."); } @Test public void test3(){ // References with different generics cannot be assigned to each other ArrayList<String> list1 = null; ArrayList<Integer> list2 = new ArrayList<>(); // list1 = list2; Person p1 = null; Person p2 = null; p1 = p2; } // Test generic methods @Test public void test4(){ Order<String> order = new Order<>(); Integer[] arr = {1, 2, 3, 4}; // When a generic method is called, it indicates the type of generic parameter List<Integer> list = order.copyFromArrayToList(arr); System.out.println(list); } }
Attention
-
A generic class may have multiple parameters. In this case, multiple parameters should be placed together in angle brackets. For example:
<E1,E2,E3> -
The constructor of the generic class is as follows: public GenericClass() {}. The following is an error: public GenericClass() {}
-
After instantiation, the structure of the original generic location must be consistent with the specified generic type.
-
References of different generics cannot be assigned to each other.
Although ArrayList and ArrayList are two types at compile time, only
An ArrayList is loaded into the JVM. -
If a generic type is not specified, it will be erased. The types corresponding to the generic type are treated as Object, but they are not equivalent to Object. Experience: generic types should be used all the way. If not, they should not be used all the way.
-
If the generic structure is an interface or abstract class, you cannot create an object of the generic class.
-
jdk1.7, simplified operation of generics: ArrayList flist = new ArrayList < > ();
-
Basic data types cannot be used in the specification of generic types, but can be replaced by wrapper classes.
-
The generic type declared on the class / interface represents a type in this class or interface. It can be used as the type of non-static attribute, parameter type of non-static method and return value type of non-static method. However, the generic type of class cannot be used in static method.
-
Exception class cannot be generic
-
Cannot use new E [], but can: E[] elements = (E[])new Object[capacity];
Reference: the ArrayList source code declares: Object[] elementData, not a generic parameter type array. -
The parent class has a generic type, and the child class can choose to keep the generic type or specify the generic type:
- Subclasses do not retain the genericity of the parent class: on-demand implementation
- No type erase
- Specific type
- Subclasses retain the genericity of the parent class: generic subclasses
- remove none
- Partial retention
Conclusion: the subclass must be a "rich second generation". In addition to specifying or retaining the generics of the parent class, the subclass can also add its own generics
- Subclasses do not retain the genericity of the parent class: on-demand implementation
Application scenario example
[DAO.java]: defines general operations for operating tables in the database. ORM idea (tables in the database correspond to classes in Java)
public class DAO<T> { // Add a record public void add(T t){ } // Delete a record public boolean remove(int index){ return false; } // Modify a record public void update(int index, T t){ } // Query a record public T getIndex(int index){ return null; } // Query multiple records public List<T> getForList(int index){ return null; } public <E> E getValue(){ return null; } }
[CustomerDAO.java]
public class CustomerDAO extends DAO<Customer>{ }
[StudentDAO.java]
public class StudentDAO extends DAO<Student>{ }
The embodiment of generics in inheritance
Although class A is the parent of class B, G and g have no child parent relationship, and they are juxtaposed
Supplement: Class A is the parent class of class B It's B Parent class of
@Test public void test1(){ Object obj = null; String str = null; obj = str; Date date = new Date(); // Compilation failed // str = date; Object[] arr1 = null; String[] arr2 = null; arr1 = arr2; List<Object> list1 = null; List<String> list2 = new ArrayList<>(); // At this time, the types of list1 and list2 do not have a child parent relationship // Compilation failed // list1 = list2; /* Counter evidence method Assume list1 = list2// Error in mixing non String data */ show(list1); // show(list2); } public void show(List<Object> list){ } @Test public void test2(){ AbstractList<String> list1 = null; List<String> list2 = null; ArrayList<String> list3 = null; list1 = list3; list2 = list3; }
wildcard
Use of wildcards
Wildcard:?
Class A is the parent class of class B. G and G have no relationship. Their common parent class is G <? >
@Test public void test3() { List<Object> list1 = null; List<String> list2 = null; List<?> list = null; list = list1; list = list2; // print(list1); // print(list2); List<String> list3 = new ArrayList<>(); list3.add("AA"); list3.add("BB"); list3.add("CC"); list = list3; // Add (write): for list <? > You can't add data to it, except null // list.add("DD"); list.add(null); // Get (read): data can be read. The read data type is Object Object o = list.get(0); System.out.println(o); } public void print(List<?> list){ Iterator<?> iterator = list.iterator(); while (iterator.hasNext()){ Object obj = iterator.next(); System.out.println(obj); } }
Writing and reading of data involving a collection of wildcards
@Test public void test3() { List<Object> list1 = null; List<String> list3 = new ArrayList<>(); list3.add("AA"); list3.add("BB"); list3.add("CC"); list = list3; // Add (write): for list <? > You can't add data to it, except null // list.add("DD"); list.add(null); // Get (read): data can be read. The read data type is Object Object o = list.get(0); System.out.println(o); }
Use of restricted wildcards
- ? extends A: G<? Extensions a > can be the parent of G and G, where B is the child of A
- ? super Person: G<? Super a > can be the parent of G and G, where B is the parent of A
@Test public void test4(){ List<? extends Person> list1 = null; List<? super Person> list2 = null; List<Student> list3 = new ArrayList<>(); List<Person> list4 = new ArrayList<>(); List<Object> list5 = new ArrayList<>(); list1 = list3; list1 = list4; // list1 = list5; // list2 = list3; list2 = list4; list2 = list5; // Read data list1 = list3; Person person = list1.get(0); // Compilation failed // Person person1 = list1.get(0); list2 = list4; Object obj = list2.get(0); // Write data: // list1.add(new Student()); list2.add(new Person()); list2.add(new Student()); }
IO stream
Use of File class
Understanding of File class
- An object of the File class that represents a File or an object File record
- The File class is declared under the java.io package
- The File class involves the creation, deletion, renaming, modification time, File size and other methods of files or File directories, and does not involve the operation of writing or reading File contents. If you need to read or write File contents, you must use IO stream to complete it
- Objects of subsequent File classes are often passed as parameters to the stream constructor, indicating the "end point" of reading or writing
Instantiation of File
Common constructors
- File(String filepath)
- File(String parentPath, String childPath)
- File(File parentFile, String childPath)
Classification of paths
- Relative path: the specified path compared to a certain path
- Absolute path: the path to the file or file directory including the drive letter
explain:
-
IDEA
- If the development uses the unit test method in JUnit to test, the relative path is under the current module
- If the development uses the main() method to test, the relative path is under the current Project
-
Eclipse
- Whether you use the unit test method or the main() method, the relative path is under the current Project
path separator
- windows and DOS systems use "\" by default
- UNIX and URL s are represented by "/"
Common methods of File class
-
Get function of File class
-
public String getAbsolutePath(): get absolute path
-
public String getPath(): get path
-
public String getName(): get the name
-
public String getParent(): get the directory path of the upper level file. If none, null is returned
-
public long length(): get the file length (i.e. the number of bytes). Cannot get the length of the directory.
-
public long lastModified(): gets the last modified time, in milliseconds
The following two methods apply to file directories
-
public String[] list(): gets the name array of all files or file directories in the specified directory
-
public File[] listFiles(): get the File array of all files or File directories in the specified directory
-
-
Rename function of File class
- public boolean renameTo(File dest): rename the file to the specified file path
-
Judgment function of File class
- public boolean isDirectory(): judge whether it is a file directory
- public boolean isFile(): judge whether it is a file
- public boolean exists(): judge whether it exists
- public boolean canRead(): judge whether it is readable
- public boolean canWrite(): judge whether it is writable
- public boolean isHidden(): judge whether to hide
-
File class creation function
- public boolean createNewFile(): creates a file. If the file exists, it will not be created and false will be returned
- public boolean mkdir(): creates a file directory. If this file directory exists, it will not be created. If the upper directory of this file directory does not exist, it will not be created.
- public boolean mkdirs(): create a file directory. If the upper file directory does not exist, create it together
Note: if you create a file or the file directory does not have a write letter path, it is under the project path by default.
-
Delete function of File class
-
public boolean delete(): deletes files or folders
Delete precautions: delete in Java does not go to the recycle bin. To delete a file directory, please note that the file directory cannot contain files or file directories
-
IO stream overview
Classification of flow
-
Operational data unit
- Byte stream
- Character stream
-
Flow direction of data
- Input stream
- Output stream
-
Role of flow
- Node flow
- Processing flow
Illustration:
Flow architecture
classification | Byte input stream | Byte output stream | Character input stream | Character output stream |
---|---|---|---|---|
Abstract base class | InputStream | OutputStream | Reader | Writer |
access files | FileInputStream | FileOutputStream | FileReader | FileWriter |
Access array | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
Access pipeline | PipedInputStream | PipedOutputStream | PipedReader | PipedWriter |
Access string | StringReader | StringWriter | ||
Buffer stream | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
Conversion flow | InputStreamReader | OutPutStreamWriter | ||
Object flow | ObjectInputStream | ObjectOutputStream | ||
Print stream | PrintStream | PrintWriter | ||
Push back input stream | PushbackInputStream | PushbackReader | ||
Special flow | DataInputStream | DataOutputStream |
Several flow structures highlighted
Abstract base class | File stream | Buffer stream |
---|---|---|
InputStream | FileInputStream(read(byte[] buffer)) | BufferedInputStream(read(byte[] buffer)) |
OutputStream | FileOutputStream(write(byte[] buffer, 0, len)) | BufferedInputStream(write(byte[] buffer, 0, len) / flush()) |
Reader | FileReader(read(char[] cbuf)) | BufferedReader(read(char[] cbuf) / readLine()) |
Writer | FileWriter(write(char[] cbuf, 0, len)) | BufferedWriter(write(char[] cbuf, 0, len) / flush()) |
Standardization process of input and output
Input process
- Create an object of File class to indicate the source of data (this File must exist)
- Create the corresponding input stream and pass the object of File class as a parameter into the stream constructor
- Specific read in process: create corresponding byte [] or char []
- Close stream resource
Note: exceptions in the program need to be handled with try catch finally
Output process
- Create an object of File class to indicate the location where the data is written out (do not require that the File must exist)
- Create the corresponding output stream and pass the object of File class as a parameter into the stream constructor
- Specific writing process: write(char[] / byte[] buffer, 0, len)
- Close stream resource
Note: exceptions in the program need to be handled with try catch finally
Node stream (or file stream)
Use of FileReader / FileWrite
Use of FileReader
Description points:
- Understanding of read(): returns a character read in. If it reaches the end of the file, it returns - 1
- Exception handling: in order to ensure that the stream resources can be closed, you need to use try catch finally
- The read file must exist, otherwise FileNotFoundException will be reported
@Test public void testFileReader1() { FileReader fileReader = null; try { // 1. Instantiation of file class File file = new File("hello.txt"); // 2. Instantiation of FileReader stream fileReader = new FileReader(file); // 3. Read in operation // read(char[] cbuf): returns the number of characters read into the cbuf array each time. If it reaches the end of the file, it returns - 1 char[] cbuf = new char[5]; int len = 0; while ((len = fileReader.read(cbuf)) != -1){ // Wrong writing /*for (int i = 0; i < cbuf.length; i++) { System.out.print(cbuf[i]); }*/ // Correct writing /*for (int i = 0; i < len; i++) { System.out.print(cbuf[i]); }*/ // Wrong writing // System.out.print(new String(cbuf)); // Correct writing System.out.print(new String(cbuf, 0, len)); } } catch (IOException e){ e.printStackTrace(); } finally{ // 4. Closure of resources if (fileReader != null) { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } }
Use of FileWriter
explain:
- For output operation, the corresponding File may not exist and no exception will be reported
- If the File in the hard disk corresponding to File does not exist, this File will be automatically created during output
- If the File in the hard disk corresponding to File exists:
- If the constructor used by the stream is: FileWriter(file, false) / FileWriter(file): overwrite the original file
- If the constructor used by the stream is: FileWriter(file, true): the original file will not be overwritten, but content will be added on the basis of the original file
@Test public void testFileWriter(){ FileWriter fileWriter = null; try { // 1. Provide the object of File class to indicate the File to be written out File file = new File("hello1.txt"); // 2. Provide FileWriter object for data writing fileWriter = new FileWriter(file, false); // 3. Write out the operation fileWriter.write("I have a dream!\n"); fileWriter.write("you need to have a dream!"); } catch (IOException e) { e.printStackTrace(); } finally { // 4. Closing of flow resources if (fileWriter != null) { try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } }
Copy of text file
@Test public void testFileReaderFileWriter() { FileReader fileReader = null; FileWriter fileWriter = null; try { // 1. Create an object of File class to indicate the read in and write out files // File srcFile = new File("hello.txt"); // File destFile = new File("hello2.txt"); // Character streams cannot be used to process byte data such as pictures File srcFile = new File("Love and friendship.png"); File destFile = new File("Love and friendship 1.png"); // 2. Create objects for input and output streams fileReader = new FileReader(srcFile); fileWriter = new FileWriter(destFile); // 3. Read and write data char[] cbuf = new char[5]; // Record the number of characters read into the cbuf array each time int len = 0; while ((len = fileReader.read(cbuf)) != -1){ // Write len characters at a time fileWriter.write(cbuf, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { // 4. Close stream resources if (fileWriter != null) { try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } if (fileReader != null) { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } }
Use of FileInputStream / FileOutputStream
- For text files (. TXT,. Java,. C,. CPP), use character stream processing
- For non text files (. JPG,. MP3,. MP4,. Avi,. Doc,. PPT,...), use byte stream processing
/** * Copy the picture */ @Test public void testFileInputOutputStream(){ FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { File srcFile = new File("Love and friendship.png"); File destFile = new File("Love and friendship 2.png"); fileInputStream = new FileInputStream(srcFile); fileOutputStream = new FileOutputStream(destFile); // Replication process byte[] buffer = new byte[5]; int len = 0; while ((len = fileInputStream.read(buffer)) != -1){ fileOutputStream.write(buffer, 0, len); } } catch (IOException e) { e.printStackTrace(); }finally { if (fileInputStream != null) { try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
Note: what is the difference between relative paths used in IDEA and Eclipse?
- IDEA
- If the unit test method is used, the relative path is based on the current Module
- If main() is used, the relative path is based on the current Project
- Eclipse: both the unit test method and the main() relative path are based on the current Project
Use of buffered streams
Classes involved in buffered streams
- BufferedInputStream
- BufferedOutputStream
- BufferedReader
- BufferedWriter
effect
Function: improve the reading and writing speed of the stream
Reason for improving read and write speed: a buffer is provided internally, which is 8kb by default
public class BufferedInputStream extends FilterInputStream { private static int DEFAULT_BUFFER_SIZE = 8192; }
Typical code
Using BufferedInputStream and BufferedOutputStream
Processing non text files
/** * Method for realizing file copying */ public void copyFileWithBuffered(String srcPath, String destPath){ BufferedInputStream bufferedInputStream = null; BufferedOutputStream bufferedOutputStream = null; try { // Document making File srcFile = new File(srcPath); File destFile = new File(destPath); // 2. Flow generation // 2.1. Node flow FileInputStream fileInputStream = new FileInputStream(srcFile); FileOutputStream fileOutputStream = new FileOutputStream(destFile); // 2.2. Create buffer flow bufferedInputStream = new BufferedInputStream(fileInputStream); bufferedOutputStream = new BufferedOutputStream(fileOutputStream); // 3. Copy details byte[] buffer = new byte[1024]; int len = 0; while ((len = bufferedInputStream.read(buffer)) != -1){ bufferedOutputStream.write(buffer, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { // 4. Resource shutdown // Requirements: first close the flow of the outer layer, and then close the flow of the inner layer if (bufferedOutputStream != null) { try { bufferedOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (bufferedInputStream != null) { try { bufferedInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } // Note: when closing the outer laminar flow, the inner laminar flow will be closed automatically. The closing of the inner laminar flow can be omitted // fileOutputStream.close(); // fileInputStream.close(); } }
Using BufferedReader and BufferedWriter
Processing text files
/** * Use BufferedReader and BufferedWriter to copy text files */ @Test public void testBufferedReaderBufferedWriter(){ BufferedReader bufferedReader = null; BufferedWriter bufferedWriter = null; try { // Create files and corresponding streams bufferedReader = new BufferedReader(new FileReader(new File("dbcp.txt"))); bufferedWriter = new BufferedWriter(new FileWriter(new File("dbcp1.txt"))); // Read / write operation // Method 1: use char [] array /*char[] cbuf = new char[1024]; int len = 0; while ((len = bufferedReader.read(cbuf)) != -1){ bufferedWriter.write(cbuf, 0, len); }*/ // Method 2: use String String data; while ((data = bufferedReader.readLine()) != null){ // Method 1: // data does not contain line breaks // bufferedWriter.write(data + "\n"); // Method 2: bufferedWriter.write(data); // Provides line feed operations bufferedWriter.newLine(); } } catch (IOException e) { e.printStackTrace(); } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } if (bufferedWriter != null) { try { bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } }
Use of conversion streams
Classes involved in the transformation flow
Belongs to character stream
-
InputStreamReader: converts a byte input stream to a character input stream
Decoding: byte, byte array -- > character array, string
-
OutputStreamWriter: converts a character output stream to a byte output stream
Encoding: character array, string -- > byte, byte array
Description: encoding determines the decoding method
effect
Provides conversion between byte stream and character stream
Illustration
Typical implementation
@Test public void test1(){ InputStreamReader inputStreamReader = null; try { FileInputStream fileInputStream = new FileInputStream("dbcp.txt"); // Use the system default character set // InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream); // Parameter 2 indicates the character set: which character set to use depends on the character set used when saving the file dbcp.txt inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8); char[] cbuf = new char[20]; int len = 0; while ((len = inputStreamReader.read(cbuf)) != -1){ System.out.print(new String(cbuf,0, len)); } } catch (IOException e) { e.printStackTrace(); } finally { if (inputStreamReader != null) { try { inputStreamReader.close(); } catch (IOException e) { e.printStackTrace(); } } } }
/** * Use InputStreamReader and OutputStreamWriter together */ @Test public void test2(){ InputStreamReader inputStreamReader = null; OutputStreamWriter outputStreamWriter = null; try { File file1 = new File("dbcp.txt"); File file2 = new File("dbcp_gbk.txt"); FileInputStream fileInputStream = new FileInputStream(file1); FileOutputStream fileOutputStream = new FileOutputStream(file2); inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8); outputStreamWriter = new OutputStreamWriter(fileOutputStream, "gbk"); char[] cbuf = new char[20]; int len = 0; while ((len = inputStreamReader.read(cbuf)) != -1){ outputStreamWriter.write(cbuf, 0, len); } } catch (IOException e) { e.printStackTrace(); }finally { if (inputStreamReader != null) { try { inputStreamReader.close(); } catch (IOException e) { e.printStackTrace(); } } if (outputStreamWriter != null) { try { outputStreamWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } }
explain
The file encoding method determines the character set used in parsing
Coding table
Common coding table
- ASCII: American standard information interchange code, which can be represented by 7 bits of a byte.
- ISO8859-1: Latin code table. European code table, represented by 8 bits of a byte.
- GB2312: Chinese coding table of China. Up to two bytes encode all characters
- GBK: China's Chinese coding table has been upgraded to integrate more Chinese characters and symbols. Up to two byte encoding
- Unicode: international standard code, which integrates all characters currently used by human beings. Assign a unique character code to each character. All text is represented by two bytes.
- UTF-8: variable length encoding method. 1-4 bytes can be used to represent a character.
enlightenment
Client / browser < - > background (Java, go, python, node.js, PHP) < - > Database
The character set used before and after shall be unified: UTF-8
Use of other streams
Standard input / output stream
- System.in: standard input stream. It is input from the keyboard by default
- System.out: standard output stream, which is output from the console by default
Modify the default input and output behavior: the setin (InputStream) / setout (OutputStream) mode of the System class reassigns the input and output streams
Print stream
- PrintStream
- PrintWriter
explain:
- Provides a series of overloaded print() and println() methods for output of multiple data types
- System.out returns an instance of PrintStream
data stream
- DataInputStream
- DataOutputStream
Function: used to read or write variables or strings of basic data types
Example code:
/** * Data streams: DataInputStream and DataOutputStream * 1.Function: used to read or write variables or strings of basic data types */ @Test public void test3(){ DataOutputStream dataOutputStream = null; try { dataOutputStream = new DataOutputStream(new FileOutputStream("data.txt")); dataOutputStream.writeUTF("Liu Jianchen"); dataOutputStream.writeInt(23); dataOutputStream.writeBoolean(true); // Refresh operation to write the data in memory to the file dataOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } finally { if (dataOutputStream != null) { try { dataOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
/** * Read the basic data type variables and strings stored in the file into memory * Note: the order of reading different types of data should be consistent with the order of the data saved when the file was written */ @Test public void test4(){ DataInputStream dataInputStream = null; try { dataInputStream = new DataInputStream(new FileInputStream("data.txt")); System.out.println(dataInputStream.readUTF()); System.out.println(dataInputStream.readInt()); System.out.println(dataInputStream.readBoolean()); } catch (IOException e) { e.printStackTrace(); } finally { if (dataInputStream != null) { try { dataInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
Use of object streams
Object flow
- ObjectInputStream
- ObjectOutputStream
effect
ObjectOutputStream: objects in memory -- > files in storage and transmitted over the network: serialization process
ObjectInputStream: files in storage, objects received over the network -- > objects in memory: deserialization process
Object serialization mechanism
The object serialization mechanism allows Java objects in memory to be converted into platform independent binary streams, which allows such binary streams to be permanently stored on disk or transmitted to another network node through the network. When other programs get this binary stream, they can restore it to the original Java object
Serialization process
@Test public void testObjectOuputStream(){ ObjectOutputStream objectOutputStream = null; try { objectOutputStream = new ObjectOutputStream(new FileOutputStream("object.dat")); objectOutputStream.writeObject(new String("I Love Beijing Tiananmen ")); // Refresh operation objectOutputStream.flush(); objectOutputStream.writeObject(new Person("Wang Ming", 23)); objectOutputStream.flush(); objectOutputStream.writeObject(new Person("placed under house arrest", 23, 1001, new Account(5000))); objectOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } finally { if (objectOutputStream != null) { try { objectOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
Deserialization process
@Test public void testObjectInputStream(){ ObjectInputStream objectInputStream = null; try { objectInputStream = new ObjectInputStream(new FileInputStream("object.dat")); Object obj = objectInputStream.readObject(); String str = (String) obj; System.out.println(str); Person person = (Person) objectInputStream.readObject(); System.out.println(person); Person person1 = (Person) objectInputStream.readObject(); System.out.println(person1); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } finally { if (objectInputStream != null) { try { objectInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
Conditions to be met by the class to which the serialized object belongs
- Interface to be implemented: Serializable
- The current class needs to provide a global constant: serialVersionUID
- In addition to the Serializable interface that the current class needs to implement, all its internal implementations must also be Serializable (by default, the basic data type can be serialized)
Supplement: ObjectOutputStream and ObjectInputStream cannot serialize member variables decorated with static and transient
Use of RandomAccessFile
Random access file stream
- RandomAccessFile
instructions
- RandomAccessFile directly inherits from java.lang.Object class and implements DataInput and DataOutput interfaces
- RandomAccessFile can be used as both an input stream and an output stream
- If RandomAccessFile is used as the output stream, if the written out file does not exist, it will be automatically created during execution. If the written out file exists, the original file content will be overwritten (by default, it will be overwritten from the beginning)
- The RandomAccessFile can "insert" data through related operations: seek(int pos)
Typical code
@Test public void test1(){ RandomAccessFile randomAccessFile1 = null; RandomAccessFile randomAccessFile2 = null; try { randomAccessFile1 = new RandomAccessFile(new File("Love and friendship.png"), "r"); randomAccessFile2 = new RandomAccessFile(new File("Love and friendship 1.png"), "rw"); byte[] buffer = new byte[1024]; int len = 0; while ((len = randomAccessFile1.read(buffer)) != -1){ randomAccessFile2.write(buffer, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { if (randomAccessFile1 != null) { try { randomAccessFile1.close(); } catch (IOException e) { e.printStackTrace(); } } if (randomAccessFile2 != null) { try { randomAccessFile2.close(); } catch (IOException e) { e.printStackTrace(); } } } }
@Test public void test3() { RandomAccessFile randomAccessFile = null; ByteArrayOutputStream byteArrayOutputStream = null; try { randomAccessFile = new RandomAccessFile("hello.txt", "rw"); // Adjust the pointer to the position marked 3 randomAccessFile.seek(3); // Save all data after pointer 3 to ByteArrayOutputStream / StringBuilder byteArrayOutputStream = new ByteArrayOutputStream(); /*StringBuilder builder = new StringBuilder( (int) new File("hello.txt").length());*/ byte[] buffer = new byte[20]; int len = 0; while ((len = randomAccessFile.read(buffer)) != -1){ // builder.append(new String(buffer, 0, len)); byteArrayOutputStream.write(buffer, 0, len); } randomAccessFile.seek(3); randomAccessFile.write("xyz".getBytes()); // randomAccessFile.write(builder.toString().getBytes()); randomAccessFile.write(byteArrayOutputStream.toByteArray()); } catch (IOException e) { e.printStackTrace(); } finally { if (byteArrayOutputStream != null) { try { byteArrayOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (randomAccessFile != null) { try { randomAccessFile.close(); } catch (IOException e) { e.printStackTrace(); } } } }
Use of Path, Paths and Files
NIO instructions
- Java NIO (New IO, non blocking IO) is a new set of IO API introduced from Java version 1.4, which can replace the standard Java IO API.
- lNIO has the same function and purpose as the original IO, but it is used in a completely different way. NIO supports buffer oriented (IO is stream oriented) and channel based IO operations.
- NIO will read and write files in a more efficient way.
- With the release of JDK 7, Java has greatly extended NIO and enhanced its support for file processing and file system features, so that we call them NIO.2.
Use of Path (provided by JDK7)
Description of Path
Path replaces the original File class
How to instantiate
The static get() method provided by the Paths class is used to obtain the Path object:
- static Path get(String first, String... more): used to string multiple characters into a path
- Static Path get (uri): returns the Path corresponding to the specified uri
common method
- String toString(): returns the string representation of the calling Path object
- boolean startsWith(String path): judge whether to start with the path path
- boolean endsWith(String path): judge whether to end with path path
- boolean isAbsolute(): judge whether it is an absolute path
- Path getParent(): the returned path object contains the entire path, not the file path specified by the path object
- Path getRoot(): returns the root path of the calling path object
- Path getFileName(): returns the file name associated with the calling path object
- int getNameCount(): returns the number of elements behind the Path root directory
- Path getName(int idx): returns the path name of the specified index location idx
- Path toAbsolutePath(): returns the calling path object as an absolute path
- Path resolve(Path p): merge two paths and return the path object corresponding to the merged path
- File toFile(): converts Path to an object of file class
Files tool class (provided by JDK7)
effect
Tool class for manipulating files or file directories
common method
-
Files common methods
- Path copy(Path src, Path dest, CopyOption... how): copy files
- Path createdirectory (path, fileattribute <? >... attr): create a directory
- Path CreateFile (path, fileattribute <? >... arr): create a file
- Void delete (path): deletes a file / directory. If it does not exist, an error is reported
- Void deleteifexists (path): delete the file / directory corresponding to path if it exists
- Path move(Path src, Path dest, CopyOption... how): move src to dest
- Long size (path): returns the size of the specified file
-
Used to judge
-
Boolean exists (path, linkoption... opts): judge whether the file exists
-
Boolean isdirectory (path, linkoption... opts): judge whether it is a directory
-
Boolean isregularfile (path, linkoption... opts): judge whether it is a file
-
Boolean ishidden (path): judge whether it is a hidden file
-
Boolean isreadable (path): judge whether the file is readable
-
Boolean iswritable (path): judge whether the file is writable
-
Boolean notexists (path, linkoption... opts): judge whether the file does not exist
-
-
Content for operation
- Seekablebytechannel newbytechannel (path, openoption... how): gets the connection to the specified file, and how specifies the opening method.
- Directorystream < Path > newdirectorystream (path): open the directory specified in path
- InputStream newinputstream (path, openoption... how): get the InputStream object
- OutputStream newoutputstream (path, openoption... how): get the OutputStream object
Network programming
Use of InetAddress class
Two problems to be solved in realizing network communication
- How to accurately locate one or more hosts on the network; Locate a specific application on the host
- How to transfer data reliably and efficiently after finding the host
Two elements of network communication
- Corresponding question 1: IP and port number
- Corresponding question 2: network communication protocol: TCP/IP reference model (application layer, transport layer, network layer, physical + data link layer)
Communication element 1: IP and port number
Understanding of IP
- IP: uniquely identifies the computer (communication entity) on the Internet
- Use the InetAddress class to represent IP in Java values
- IP Classification: IPv4 and IPv6 / World Wide Web and LAN
- Domain name: www.baidu.com www.mi.com www.sina.com www.vip.com
- Domain name resolution: the domain name is easy to remember. When the domain name of a host is entered when connecting to the network, the domain name server (DNS) is responsible for converting the domain name into an IP address, so as to establish a connection with the host.
- Local loop address: 127.0.0.1 corresponds to localhost
InetAddress class
An object of this class represents an IP address
Instantiation:
- getByName(String host)
- getLocalhost()
Common methods:
- getHostName()
- getHostAddress()
Port number
- Port number: the process running on the computer
- Requirement: different processes have different port numbers
- Range: specified as a 16 bit integer 0 ~ 65535.
The combination of port number and IP address yields a network Socket: Socket
Communication element 2: network communication protocol
Typing model
The difference between TCP and UDP
-
TCP protocol:
- Before using TCP protocol, a TCP connection must be established to form a data transmission channel
- Before transmission, the "triple handshake" mode is adopted for point-to-point communication, which is reliable
- Two application processes communicating with TCP protocol: client and server.
- A large amount of data can be transmitted in the connection
- After transmission, the established connection needs to be released, which is inefficient
-
UDP protocol:
- Encapsulate the data, source and destination into packets without establishing a connection
- The size of each datagram is limited to 64K
- Whether the sending party is ready or not, the receiving party does not confirm the receipt, so it is unreliable
- Can broadcast and send
- At the end of sending data, there is no need to release resources, low overhead and high speed
TCP three handshakes and four waves
TCP network programming
Example 1: the client sends information to the server, and the server displays the data on the console
public class TCPTest1 { /** * client */ @Test public void client(){ Socket socket = null; OutputStream outputStream = null; try { // 1. Create a Socket object to indicate the IP and port number of the server InetAddress inet = InetAddress.getByName("127.0.0.1"); socket = new Socket(inet, 8899); // 2. Obtain an output stream for outputting data outputStream = socket.getOutputStream(); // 3. Write data outputStream.write("Hello, this is the client mm".getBytes()); } catch (IOException e) { e.printStackTrace(); }finally { // 4. Closure of resources if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * Server */ @Test public void server(){ ServerSocket serverSocket = null; Socket socket = null; InputStream inputStream = null; ByteArrayOutputStream byteArrayOutputStream = null; try { // 1. Create a ServerSocket on the server side and indicate its own port number serverSocket = new ServerSocket(8899); // 2. Call accept() to receive the socket from the client socket = serverSocket.accept(); // 3. Get input stream inputStream = socket.getInputStream(); // Not recommended. There is garbled code /*byte[] buffer = new byte[1024]; int len = 0; while ((len = inputStream.read(buffer)) != -1){ System.out.print(new String(buffer, 0, len)); }*/ // 4. Get the data in the input stream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[5]; int len = 0; while ((len = inputStream.read(buffer)) != -1){ byteArrayOutputStream.write(buffer, 0, len); } System.out.println(byteArrayOutputStream); System.out.println("Received from:" + socket.getInetAddress().getHostAddress() + " Data"); } catch (IOException e) { e.printStackTrace(); } finally { // 5. Closure of resources if (byteArrayOutputStream != null) { try { byteArrayOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } if (serverSocket != null) { try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
Example 2: the client sends a file to the server, and the server saves the file locally
public class TCPTest2 { @Test public void client(){ Socket socket = null; OutputStream outputStream = null; FileInputStream fileInputStream = null; try { socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090); outputStream = socket.getOutputStream(); fileInputStream = new FileInputStream("beauty.png"); byte[] buffer = new byte[1024]; int len = 0; while ((len = fileInputStream.read(buffer)) != -1){ outputStream.write(buffer, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { if (fileInputStream != null) { try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void server(){ ServerSocket serverSocket = null; Socket socket = null; InputStream inputStream = null; FileOutputStream fileOutputStream = null; try { serverSocket = new ServerSocket(9090); socket = serverSocket.accept(); inputStream = socket.getInputStream(); fileOutputStream = new FileOutputStream("beauty1.png"); byte[] buffer = new byte[1024]; int len = 0; while ((len = inputStream.read(buffer)) != -1){ fileOutputStream.write(buffer, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { if (fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } if (serverSocket != null) { try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
Example 3: send files from the client to the server, and the server saves them locally. And return "send successfully" to the client. And close the corresponding connection.
public class TCPTest3 { @Test public void client(){ Socket socket = null; OutputStream outputStream = null; InputStream inputStream = null; FileInputStream fileInputStream = null; ByteArrayOutputStream byteArrayOutputStream = null; try { socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090); outputStream = socket.getOutputStream(); fileInputStream = new FileInputStream("beauty.png"); byte[] buffer = new byte[1024]; int len = 0; while ((len = fileInputStream.read(buffer)) != -1){ outputStream.write(buffer, 0, len); } // Turn off data output socket.shutdownOutput(); // Receive data from the server and display it to the console inputStream = socket.getInputStream(); byteArrayOutputStream = new ByteArrayOutputStream(); byte[] bufferr = new byte[20]; int len1 = 0; while ((len1 = inputStream.read(bufferr)) != -1){ byteArrayOutputStream.write(bufferr, 0, len1); } System.out.println(byteArrayOutputStream); } catch (IOException e) { e.printStackTrace(); } finally { if (byteArrayOutputStream != null) { try { byteArrayOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (fileInputStream != null) { try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void server(){ ServerSocket serverSocket = null; Socket socket = null; InputStream inputStream = null; FileOutputStream fileOutputStream = null; OutputStream outputStream = null; try { serverSocket = new ServerSocket(9090); socket = serverSocket.accept(); inputStream = socket.getInputStream(); fileOutputStream = new FileOutputStream("beauty2.png"); byte[] buffer = new byte[1024]; int len = 0; while ((len = inputStream.read(buffer)) != -1){ fileOutputStream.write(buffer, 0, len); } System.out.println("Picture transfer complete"); // The server gives feedback to the client outputStream = socket.getOutputStream(); outputStream.write("Hello, beauty, I have received the photo. It's very beautiful".getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } if (serverSocket != null) { try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
UDP network programming
public class UDPTest { /** * Sender */ @Test public void sender(){ DatagramSocket socket = null; try { socket = new DatagramSocket(); String str = "I am UDP Missile sent by"; byte[] data = str.getBytes(); InetAddress inet = InetAddress.getLocalHost(); DatagramPacket packet = new DatagramPacket(data, 0, data.length, inet, 9090); socket.send(packet); } catch (IOException e) { e.printStackTrace(); } finally { socket.close(); } } /** * receiving end */ @Test public void receiver(){ DatagramSocket socket = null; try { socket = new DatagramSocket(9090); byte[] buffer = new byte[100]; DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length); socket.receive(packet); System.out.println(new String(packet.getData(), 0, packet.getLength())); } catch (IOException e) { e.printStackTrace(); } finally { socket.close(); } } }
URL programming
Understanding of URL
Uniform Resource Locator: a Uniform Resource Locator that corresponds to a resource address on the Internet
Five basic structures of URL
http://localhost:8080/examples/beauty.png?p=629&spm_id_from=pageDriver
Protocol hostname port number resource address parameter list
instantiation
URL url = new URL("http://localhost:8080/examples/beauty.png?p=629&spm_id_from=pageDriver");
common method
- public String getProtocol(): get the protocol name of the URL
- public String getHost(): get the host name of the URL
- public String getPort(): get the port number of the URL
- public String getPath(): get the file path of the URL
- public String getFile(): get the file name of the URL
- public String getQuery(): get the query name of the URL
You can read and download the corresponding url resources
public class URLTest1 { public static void main(String[] args){ HttpURLConnection urlConnection = null; InputStream inputStream = null; FileOutputStream fileOutputStream = null; try { URL url = new URL("http://localhost:8080/examples/beauty.png"); urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.connect(); inputStream = urlConnection.getInputStream(); fileOutputStream = new FileOutputStream("JavaSenior\\day10\\beauty3.png"); byte[] buffer = new byte[1024]; int len = 0; while ((len = inputStream.read(buffer)) != -1){ fileOutputStream.write(buffer, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { if (fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (urlConnection != null) { urlConnection.disconnect(); } } } }
Java reflection mechanism
Overview of reflection
primary coverage
- Overview of Java reflection mechanism
- Understand Class class and get Class instance
- Class loading and ClassLoader understanding
- Create an object for the runtime class
- Gets the complete structure of the runtime class
- Calls the specified structure of the runtime class
- Application of reflection: dynamic proxy
Understanding of reflection
Reflection is the key to being regarded as a dynamic language. Reflection mechanism allows programs to obtain the internal information of any class with the help of Reflection API during execution, and can directly operate the internal properties and methods of any object.
Frame = reflection + annotation + design pattern
Reflect the "dynamics" of reflection mechanism
@Test public void test2(){ for (int i = 0; i < 100; i++) { int num = new Random().nextInt(3); String classPath = ""; switch (num){ case 0: classPath = "java.util.Date"; break; case 1: classPath = "java.lang.Object"; break; case 2: classPath = "cn.tedu.java.Person"; break; } System.out.println(getInstance(classPath)); } } /** * Creates an object of the specified class * @param classPath Specifies the full class name of the class * @return * @throws Exception */ public Object getInstance(String classPath){ try { return Class.forName(classPath).newInstance(); } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { e.printStackTrace(); } return null; }
Reflection mechanism can provide
- Determine the class of any object at run time
- Construct an object of any class at run time
- Judge the member variables and methods of any class at run time
- Get generic information at run time
- Call the member variables and methods of any object at run time
- Processing annotations at run time
- Generate dynamic proxy
Related API
- java.lang.Class: source of reflection
- java.lang.reflect.Method
- java.lang.reflect.Field
- java.lang.reflect.Constructor
- ......
Understanding Class and obtaining Class instances
Class understanding
-
Class loading process:
After the program passes the javac.exe command, it will generate one or more bytecode files (. End of class).
Then use the java.exe command to interpret and run a bytecode file, which is equivalent to loading a bytecode file into memory. This process is called class loading
A Class loaded into memory is called a runtime Class. This runtime Class is used as an instance of Class
-
In other words, an instance of Class corresponds to a runtime Class
-
The runtime class loaded into memory will cache certain data. Within this time, you can obtain this runtime class in different ways
Several ways to get Class instances
/** * How to obtain an instance of Class (the first three need to be mastered) */ @Test public void test3() throws ClassNotFoundException { // Method 1: call the attribute of the runtime class:. Class Class<Person> clazz1 = Person.class; System.out.println(clazz1); // Method 2: call getClass() through the object of the runtime class Person p1 = new Person(); Class<? extends Person> clazz2 = p1.getClass(); System.out.println(clazz2); // Method 3: call the static method of Class: forname(String classPath) Class<?> clazz3 = Class.forName("cn.tedu.java.Person"); // clazz3 = Class.forName("java.lang.String"); System.out.println(clazz3); System.out.println(clazz1 == clazz2); System.out.println(clazz1 == clazz3); // Method 4: use class loader: classloader (understand) ClassLoader classLoader = ReflectionTest.class.getClassLoader(); Class<?> clazz4 = classLoader.loadClass("cn.tedu.java.Person"); System.out.println(clazz4); }
How to create objects of a class
- new + constructor
- To create an object of Xxx class, you can consider: check whether there are static methods in Xxx, Xxxs, XxxFactory and XxxBuilder classes. You can call their static methods to create an Xxx object
- By reflection
A description of which structures a Class instance can be
- Class: external class, member (member internal class, static internal class), local internal class, anonymous internal class
- interface: interface
- []: array
- enum: Enumeration
- Annotation: annotation @ interface
- primitive type: basic data type
- void
Understanding ClassLoader
Class loading process
Class loader
-
**Function of class loading: * * load the bytecode content of class file into memory, convert these static data into the runtime data structure of the method area, and then generate a java.lang.Class object representing this class in the heap as the access entry of class data in the method area.
-
**Class cache: * * the standard JavaSE class loader can find classes as required, but once a class is loaded into the class loader, it will remain loaded (cached) for a period of time. However, the JVM garbage collection mechanism can recycle these class objects.
Class loader classification
The process of compiling, running and executing Java classes
Use ClassLoader to load the configuration file in src directory
@Test public void test2() throws IOException { Properties properties = new Properties(); // At this time, the file is under the current Module by default // Read configuration mode 1: // FileInputStream fileInputStream = new FileInputStream("jdbc.properties"); // FileInputStream fileInputStream = new FileInputStream("src\\jdbc1.properties"); // properties.load(fileInputStream); // Read configuration mode 2: use ClassLoader // The default identification of the configuration file is: under src of the current module ClassLoader classLoader = ClassLoaderTest.class.getClassLoader(); InputStream resourceAsStream = classLoader.getResourceAsStream("jdbc1.properties"); properties.load(resourceAsStream); String user = properties.getProperty("user"); String password = properties.getProperty("password"); System.out.println("user = " + user + ", password = " + password); }
Reflection application 1: create runtime class objects
Code example
@Test public void test1() throws Exception{ Class<Person> clazz = Person.class; Person person = clazz.newInstance(); System.out.println(person); }
explain
- newInstance(): call this method to create the object of the corresponding runtime class, and internally call the empty parameter constructor of the runtime class
- To create the object of the runtime class normally with this method, you need to:
- The runtime class must provide an empty argument constructor
- The access permission of the null parameter constructor is sufficient, which is usually set to public
- A public null parameter constructor is required in JavaBean. The reason is:
- It is convenient to provide reflection and create objects of runtime classes
- When the subclass inherits this runtime class, super() is called by default to ensure that the parent class has this constructor
Reflection application 2: get the complete structure of the runtime class
Through reflection, all properties, methods, constructors, parent classes, interfaces, generics, packages, annotations, exceptions, etc. of the corresponding runtime class are obtained
Typical code
@Test public void test1(){ Class<Person> clazz = Person.class; // Get attribute structure // Getfeeds(): get the property of the current runtime class and its parent class declared as public access permission Field[] fields = clazz.getFields(); for (Field field : fields) { System.out.println(field); } System.out.println(); // Getdeclaraedfields(): get all the attributes declared in the current runtime class (excluding the attributes declared in the parent class) for (Field declaredField : clazz.getDeclaredFields()) { System.out.println(declaredField); } }
@Test public void test1(){ Class<Person> clazz = Person.class; // getMethods(): get the method that the current runtime class and its parent class declare as public access permission Method[] methods = clazz.getMethods(); for (Method m : methods) { System.out.println(m); } System.out.println(); // Getdeclaraedmethods(): get all the methods declared in the current runtime class (excluding the methods declared in the parent class) for (Method declaredMethod : clazz.getDeclaredMethods()) { System.out.println(declaredMethod); } }
/** * Get constructor */ @Test public void test1(){ Class<Person> clazz = Person.class; // getConstructors(): get the constructor declared as public in the current runtime class Constructor<?>[] constructors = clazz.getConstructors(); for (Constructor<?> constructor : constructors) { System.out.println(constructor); } System.out.println(); // Getdeclaraedconstructors(): get the constructor declared as public in the current runtime class Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors(); for (Constructor<?> declaredConstructor : declaredConstructors) { System.out.println(declaredConstructor); } } /** * Gets the parent class of the runtime class */ @Test public void test2() { Class<Person> clazz = Person.class; Class<? super Person> superclass = clazz.getSuperclass(); System.out.println(superclass); } /** * Gets the generic parent of the runtime class */ @Test public void test3() { Class<Person> clazz = Person.class; Type genericSuperclass = clazz.getGenericSuperclass(); System.out.println(genericSuperclass); } /** * Gets the generic type of the generic parent class of the runtime class */ @Test public void test4() { Class<Person> clazz = Person.class; Type genericSuperclass = clazz.getGenericSuperclass(); ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass; // Get generic type Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { // System.out.println(actualTypeArgument.getTypeName()); System.out.println(((Class) actualTypeArgument).getName()); } } /** * Gets the interface implemented by the runtime class */ @Test public void test5(){ Class<Person> clazz = Person.class; Class<?>[] interfaces = clazz.getInterfaces(); for (Class<?> anInterface : interfaces) { System.out.println(anInterface); } System.out.println(); // Gets the interface implemented by the runtime class parent class for (Class<?> anInterface : clazz.getSuperclass().getInterfaces()) { System.out.println(anInterface); } } /** * Gets the package where the runtime class is located */ @Test public void test6(){ Class<Person> clazz = Person.class; Package pack = clazz.getPackage(); System.out.println(pack); } /** * Gets the annotation of the runtime class declaration */ @Test public void test7(){ Class<Person> clazz = Person.class; Annotation[] annotations = clazz.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotations); } }
Reflection application 3: call the specified structure of the runtime class
Call the specified property
@Test public void testFeild(){ try { Class<Person> clazz = Person.class; // Create an object for the runtime class Person p = clazz.newInstance(); // 1. Getdeclaraedfield (string name): get the attribute indicating the variable name in the runtime class Field name = clazz.getDeclaredField("name"); // 2. Ensure that the current attribute is accessible name.setAccessible(true); // 3. Get or set the value of the specified property name.set(p, "Tom"); System.out.println(name.get(p)); } catch (NoSuchFieldException | InstantiationException | IllegalAccessException e) { e.printStackTrace(); } }
Call the specified method
@Test public void testMethod(){ try { Class<Person> clazz = Person.class; // Create an object for the runtime class Person p = clazz.newInstance(); /** * 1.Gets a specified method * getDeclaredMethod(): Parameter 1: indicates the name of the obtained method; parameter 2: indicates the formal parameter list of the obtained method */ Method show = clazz.getDeclaredMethod("show", String.class); show.setAccessible(true); /** * invoke(): Parameter 1: the caller of the method parameter 2: the argument assigned to the formal parameter of the method * invoke() The return value of is the return value of the method defined in the corresponding class */ Object returnValue = show.invoke(p, "CHN"); System.out.println(returnValue); Method showDesc = clazz.getDeclaredMethod("showDesc"); showDesc.setAccessible(true); // This invoke() returns null if the method in the called runtime class does not return a value // Object returnVal = showDesc.invoke(Person.class); Object returnVal = showDesc.invoke(null); System.out.println(returnVal); } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } }
Call the specified constructor
@Test public void testConstructor(){ try { Class<Person> clazz = Person.class; // Create an object for the runtime class Person p = clazz.newInstance(); // 1. Get the specified constructor // Getdeclaraedconstructor(): parameter: indicates the parameter list of the constructor Constructor<Person> constructor = clazz.getDeclaredConstructor(String.class); // 2. Ensure that this constructor is accessible constructor.setAccessible(true); // 3. Call this constructor to create the object of the runtime class Person tom = constructor.newInstance("Tom"); System.out.println(tom); } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { e.printStackTrace(); } }
Reflection application IV: dynamic agent
Principle of agent mode
Wrap the object with a proxy object and replace the original object with the proxy object. Any call to the original object is made through a proxy. The proxy object determines whether and when method calls are transferred to the original object.
Static proxy
give an example
Methods that implement the Runnable interface create multithreads
// Proxy class class MyThread implements Runnable{ } // proxy class class Thread implements Runnable{ } public class Main{ public static void main(String[] args){ MyThread t = new MyThread(); Thread thread = new Thread(t); // Start the thread; run() of calling thread thread.start(); } }
Disadvantages of static agents
- The classes of proxy class and target object are determined during compilation, which is not conducive to program expansion.
- Each agent class can only serve one interface, so there must be too many agents in program development
Characteristics of dynamic agent
Dynamic proxy refers to the method that the client calls other objects through the proxy class, and it is the proxy object that dynamically creates the target class when the program runs.
Implementation of dynamic agent
Two main issues need to be addressed
-
Question 1: how to dynamically create a proxy class and its object according to the proxy class loaded into memory
Resolve through Proxy.newInstance()
-
Question 2: how to dynamically call the method with the same name in the proxy class when calling the method through the object of the proxy class a
Implementation class and its method invoke() through InvocationHandler interface
code implementation
public class ProxyTest { public static void main(String[] args) { SuperMan superMan = new SuperMan(); // proxyInstance: object of proxy class Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan); // When a method is called through a proxy class object, it will automatically call the method with the same name in the proxy class System.out.println(proxyInstance.getBelief()); proxyInstance.eat("Sichuan Mala"); System.out.println(); NickClothFactory nickClothFactory = new NickClothFactory(); ClothFactory proxyClothFactory = (ClothFactory) ProxyFactory.getProxyInstance(nickClothFactory); proxyClothFactory.produceCloth(); } } interface Human{ String getBelief(); void eat(String food); } /** * Proxy class */ class SuperMan implements Human{ @Override public String getBelief() { return "I believe I can fly"; } @Override public void eat(String food) { System.out.println("I love eating" + food); } } class HumanUtil{ public void method1(){ System.out.println("General method I"); } public void method2(){ System.out.println("General method II"); } } class ProxyFactory{ /** * Call this method to return an object of proxy class to solve the problem * @param obj Object of the proxied class * @return */ public static Object getProxyInstance(Object obj){ MyInvocationHandler handler = new MyInvocationHandler(); handler.bind(obj); return Proxy.newProxyInstance( obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler); } } class MyInvocationHandler implements InvocationHandler{ /** * You need to use the object of the proxy class for assignment */ private Object obj; public void bind(Object obj){ this.obj = obj; } /** * When method a is called through the object of the proxy class, the following method will be automatically called: invoke() * Declare the function of method a to be executed by the proxy class in invoke() * @param proxy * @param method * @param args * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { HumanUtil humanUtil = new HumanUtil(); humanUtil.method1(); // Method: that is, the method called for the proxy class object, which completes the method to be called by the proxy object // obj: object of the proxied class Object returnValue = method.invoke(obj, args); humanUtil.method2(); // The return value of the above method is the return value of invoke() in the current class return returnValue; } }
experience
Dynamics of reflection
Other new features of Java 8
Overview of new Java 8 features
Lambda expression
Comparison of Lambda expressions before and after use
Example 1:
@Test public void test1(){ Runnable r1 = new Runnable() { @Override public void run() { System.out.println("I Love Beijing Tiananmen "); } }; r1.run(); System.out.println(); Runnable r2 = () -> System.out.println("I love the Forbidden City in Beijing"); r2.run(); }
Example 2:
@Test public void test2() { Comparator<Integer> com1 = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return Integer.compare(o1, o2); } }; int compare1 = com1.compare(12, 21); System.out.println(compare1); System.out.println(); // How to write Lambda expressions Comparator<Integer> com2 = (o1, o2) -> Integer.compare(o1, o2); int compare2 = com2.compare(32, 21); System.out.println(compare2); System.out.println(); // Method reference Comparator<Integer> com3 = Integer::compare; int compare3 = com3.compare(32, 21); System.out.println(compare3); }
Basic usage of Lambda expressions
- For example: (O1, O2) - > integer. Compare (O1, O2)
- format
- ->: Lambda operator or arrow operator
- ->Left: Lambda parameter list (actually the parameter list of abstract methods in the interface)
- ->Right: Lambda body (actually the method body of abstract method)
How to use: there are six cases
Summarize six situations:
- ->On the left: the parameter type of the Lambda parameter list can be omitted (type inference). If the Lambda parameter list has only one city, its pair () can also be omitted
- ->Right: the Lambda body should use a pair of {} packages. If there is only one execution statement (possibly a return statement), you can omit a pair of {} and return keywords
Functional interface
instructions
-
If only one abstract method is declared in an interface, the interface is called a functional interface.
-
You can use the @ functional interface annotation on an interface to check whether it is a functional interface.
-
The essence of Lambda expressions: as instances of functional interfaces
4 basic functional interfaces
Specific use:
Functional interface | Parameter type | return type | purpose |
---|---|---|---|
Consumer consumer interface | T | void | Apply operations to objects of type T, including methods: void accept (T) |
Supplier supply interface | nothing | T | Returns an object of type T, including the method: T get() |
Function < T, R > functional interface | T | R | Applies an operation to an object of type T and returns a result. The result is an object of type R. Include method: R apply (T) |
Predicate type interface | T | boolean | Determines whether an object of type T satisfies a constraint and returns a boolean value. Including method: boolean test (T) |
summary
When to use Lambda expressions?
When you need to instantiate a functional interface, you can use Lambda expressions
When to use a given functional interface?
If you need to define a functional interface during development, first check whether the functional interface provided by the existing JDK provides a functional interface that can meet the requirements. If so, you can call it directly without customization
Method reference
understand
Method reference can be regarded as a deep expression of Lambda expression. In other words, a method reference is a Lambda expression, that is, an instance of a functional interface, pointing to a method by its name.
Use situation
When the operation to be passed to the Lambda body already has an implemented method, you can use the method reference
format
Class or object:: method name
There are three cases
- Object:: non static method
- Class:: static method
- Class:: non static method
requirement
- Requirements for method reference: the formal parameter list and return value type of the abstract method in the interface are required to be the same as the formal parameter list and return value type of the method referenced by the method (for the first two types)
- When the first parameter of a functional interface method is the caller of the method to be referenced, and the second parameter is the parameter (or no parameter) of the method to be referenced: ClassName::methodName
Use suggestions
If providing an instance to a functional interface just meets the use situation of method reference, you can consider providing an instance to a functional interface. If you are not familiar with method reference, you can also use Lambda expression
Use examples
// Case 1: object: instance method // Void accept in Consumer // Void println in PrintStream @Test public void test1() { Consumer<String> con1 = str -> System.out.println(str); con1.accept("Beijing"); PrintStream ps = System.out; Consumer<String> con2 = ps::println; con2.accept("Beijing"); } // T get() in Supplier // String getName() of Employee @Test public void test2() { Employee emp = new Employee(1001, "Tom", 23, 5000); Supplier<String> sup1 = () -> emp.getName(); System.out.println(sup1.get()); Supplier<String> sup2 = emp::getName; System.out.println(sup2.get()); } // Case 2: Class: static method // Int compare in Comparator (t T1, t T2) // Int compare in Integer (t T1, t T2) @Test public void test3() { Comparator<Integer> com1 = (t1, t2) -> Integer.compare(t1, t2); System.out.println(com1.compare(12, 21)); Comparator<Integer> com2 = Integer::compare; System.out.println(com2.compare(32, 21)); } // R apply in Function (T) // Long round(Double d) in Math @Test public void test4() { Function<Long, Double> fun1 = d -> (double) Math.round(d); // Function<Long, Double> fun2 = Math::round; } // Case 3: Class: instance method // Int comapre in Comparator (t T1, t T2) // int t1.compareTo(t2) in String @Test public void test5() { Comparator<String> com1 = (s1, s2) -> s1.compareTo(s2); Comparator<String> com2 = String::compareTo; } // Boolean test in BiPredicate (t T1, t T2); // boolean t1.equals(t2) in String @Test public void test6() { BiPredicate<String, String> pre1 = (s1, s2) -> s1.equals(s2); BiPredicate<String, String> pre2 = String::equals; System.out.println(pre1.test("'", "a")); System.out.println(pre1.test("'", "a")); } // R apply in Function (T) // String getName() in Employee; @Test public void test7() { Function<Employee, String> func1 = e -> e.getName(); System.out.println(func1.apply(new Employee(1001, "Jerry", 23, 6000))); Function<Employee, String> func2 = Employee::getName; System.out.println(func2.apply(new Employee(1001, "Jerry", 23, 6000))); }
Constructor reference and array reference
Constructor reference format
- Class name:: new
Constructor reference usage requirements
Similar to the method reference, the parameter list of the abstract method of the functional interface is consistent with the formal parameter list of the constructor, and the return value type of the abstract method is the type of the class to which the constructor belongs
Constructor reference example
// Constructor reference // T get() in Supplier @Test public void test1(){ Supplier<Employee> sup1 = () -> new Employee(); Supplier<Employee> sup2 = Employee::new; System.out.println(sup2.get()); } // R apply in Function (T) @Test public void test2(){ Function<Integer, Employee> func1 = id -> new Employee(id); Employee employee = func1.apply(1001); System.out.println(employee); Function<Integer, Employee> func2 = Employee::new; System.out.println(func2.apply(1002)); } // R apply (T, t, u, U) in BiFunction @Test public void test3(){ BiFunction<Integer, String, Employee> func1 = (id, name) -> new Employee(id, name); BiFunction<Integer, String, Employee> func2 = Employee::new; }
Array reference format
- Array type []: new
Array reference example
// Array reference // R apply in Function (T) @Test public void test4(){ Function<Integer, String[]> func1 = length -> new String[length]; String[] arr1 = func1.apply(5); System.out.println(Arrays.toString(arr1)); Function<Integer, String[]> func2 = String[]::new; String[] arr2 = func2.apply(5); System.out.println(Arrays.toString(arr2)); }
Stream API
Understanding of Stream API
-
Stream focuses on the operation of data and dealing with CPU
Collections focus on the storage of data and dealing with memory
-
Java 8 provides a set of API s that can be used to filter, sort, map and regulate data in memory, similar to SQL operations on tables in the database
Attention
- Stream itself does not store elements.
- Stream does not change the source object. Instead, they return a new stream that holds the result.
- Stream operations are deferred. This means they wait until they need results
Use process of Stream
- Instantiation of Stream
- A series of intermediate operations
- Terminate operation
Precautions for using the process
- An intermediate operation chain that processes the data of the data source
- Once the termination operation is performed, the intermediate operation chain is executed and the results are generated. After that, it will not be used again
Step 1: Stream instantiation
/** * Creation method 1: through collection */ @Test public void test1(){ List<Employee> employees = EmployeeData.getEmployees(); // Default stream < E > stream(): returns a sequential stream Stream<Employee> stream = employees.stream(); // Default stream < E > parallelstream(): returns a parallel stream Stream<Employee> parallelStream = employees.parallelStream(); } /** * Creation method 2: through array */ @Test public void test2(){ int[] arr = new int[]{1, 2, 3, 4, 5, 6}; // Static < T > stream < T > stream (t [] array): returns a stream IntStream stream = Arrays.stream(arr); Employee e1 = new Employee(1001, "Tom"); Employee e2 = new Employee(1001, "Jerry"); Employee[] employees = {e1, e2}; Stream<Employee> employeeStream = Arrays.stream(employees); } /** * Creation method 3: through of() of Stream */ @Test public void test3(){ Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6); } /** * Creation method 4: create infinite flow */ @Test public void test4(){ // Iteration public static < T > stream < T > iterate (final t seed, final unaryoperator < T > F) // Traverse the first 10 even numbers Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println); // Generate public static < T > stream < T > generate (supplier < T > s) Stream.generate(Math::random).limit(10).forEach(System.out::println); }
Step 2: intermediate operation
-
Screening and slicing
method describe filter(Predicate p) Receive Lambda and exclude some elements from the stream distinct() Filter to remove duplicate elements through hashCode() and 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) -
mapping
method describe map(Function f) Receive a function as an argument, which is applied to each element and mapped to a new element 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 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. -
sort
method describe sorted() Generate a new stream, which is sorted in natural order sorted(Comparator com) Generates a new stream, sorted in comparator order
Step 3: terminate the operation
-
Match and find
method describe allMatch(Predicate p) Check that all elements match anyMatch(Predicate p) Check to see if at least one element matches noneMatch(Predicate p) Check that no elements match findFirst() Returns the first element findAny() Returns any element in the current stream count() Returns the total number of elements in the stream max(Comparator c) Returns the maximum value in the stream min(Comparator c) Returns the minimum value in the stream foreach(Consumer c) Internal iteration (using the Collection interface requires the user to do the iteration, which is called external iteration. On the contrary, the Stream API uses internal iteration - it helps you do the iteration) -
Statute
method describe reduce(T iden, BinaryOperator b) You can combine the elements in the flow repeatedly to get a value. Return T reduce(BinaryOperator b) You can combine the elements in the flow repeatedly to get a value. Return to Optional Note: the connection between map and reduce is usually called map reduce mode, which is famous for Google's use of it for web search.
-
collect
method describe 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 Collector requires an instance of Collectors
method Return type effect toList List Collect the elements in the stream into a List toSet Set Collect the elements in the stream into a Set toCollection Collection Collect the elements in the stream into the Collection counting Long Count the number of elements in the flow summingInt Integer Summing integer attributes of elements in a stream averagingInt Double Calculates the average value of the Integer attribute of the element in the flow summarizingInt IntSummaryStatistics Collect statistics for the Integer attribute in the stream. E.g. average value joining String Each string in the connection stream maxBy Optional Select the maximum value according to the comparator minBy Optional Select the minimum value according to the comparator reducing Type of reduction Starting from an initial value as an accumulator, BinaryOperator is combined with the elements in the stream one by one to reduce it to a single value collectingAndThen The type returned by the conversion function Wrap another collector and convert its result to a function groupingBy Map<K, List> According to an attribute value, the attribute is K and the result is V partitioningBy Map<Boolean, List> Partition according to true or false
Use of Optional class
understand
It is designed to solve the null pointer problem in Java
The optional class (java.util.Optional) is a container class that can store the value of type T, representing the existence of this value. Or just save null, indicating that the value does not exist. Originally, null was used to indicate that a value does not exist. Now optional can better express this concept. And you can avoid null pointer exceptions.
common method
-
Method to create an Optional class object:
- Optional. Of (T): create an optional instance, t must be non empty;
- Optional.empty(): create an empty optional instance
- Optional. Ofnullable (T): t can be null
-
Determine whether the Optional container contains objects:
- boolean isPresent(): judge whether objects are included
- Void ifpresent (Consumer <? Super T > Consumer) * *: * * if there is a value, the implementation code of the Consumer interface will be executed, and the value will be passed to it as a parameter.
-
Get the object of the Optional container:
- T get(): if the calling object contains a value, return the value; otherwise, throw an exception
- T orElse(T other): if there is a value, it will be returned; otherwise, the specified other object will be returned.
- T orelseget (Supplier <? Extensions T > other): if there is a value, it will be returned; otherwise, it will return the object provided by the Supplier interface implementation.
- T orelsethrow (Supplier <? Extensions x > exceptionsupplier): if there is a value, it will be returned; otherwise, an exception provided by the Supplier interface implementation will be thrown.
@Test public void test1(){ // empty(): value = null inside the created Optional object Optional<Object> op1 = Optional.empty(); // Does the Optional encapsulated data contain data if (op1.isPresent()) { System.out.println("Data is empty"); } // If the Optional encapsulated data value is empty, get() will report an error. Otherwise, if value is not empty, it will return value // System.out.println(op1.get()); System.out.println(op1); System.out.println(op1.isPresent()); } @Test public void test2(){ String str = "hello"; // Of (T): encapsulates data t to generate an Optional object. It is required that t must be non empty, otherwise an error will be reported Optional<String> op1 = Optional.of(str); // get() is usually used together with the of() method to obtain the internal encapsulated data value String str1 = op1.get(); System.out.println(str1); } @Test public void test3(){ // ofNullable(T t): encapsulates the value that the data t is assigned to the internal part of Optional. It is not required that t is not empty Optional<String> op1 = Optional.ofNullable("beijing"); // orElse(T t1): if the value inside Optional is not empty, this value will be returned; if value is empty, t1 will be returned String str2 = op1.orElse("shanghai"); System.out.println(str2); }
Typical exercises
It can ensure that no null pointer exception occurs during the execution of the following methods
public String getGirlName2(Boy boy){ Optional<Boy> boyOptional = Optional.ofNullable(boy); Boy boy1 = boyOptional.orElse(new Boy(new Girl("Delireba"))); Girl girl = boy1.getGirl(); Optional<Girl> girlOptional = Optional.ofNullable(girl); Girl girl1 = girlOptional.orElse(new Girl("Gulinaza")); return girl1.getName(); } @Test public void test5(){ Boy boy = null; boy = new Boy(); boy = new Boy(new Girl("Aoi Sora")); String girlName = getGirlName2(boy); System.out.println(girlName); }
project
Project requirements
- Complete the project code at least once independently
- Accumulate common bug debugging in the process of completing the project
- "Hard" view, add output statements if necessary
- Debug
- Straighten out ideas and strengthen logic
- Parsing of memory structures such as objects and arrays
- Comply with the coding specification, identifier naming specification, etc
- Add necessary comments before classes, methods, and implementation steps of specific logic in methods
- Before class, before method, before attribute: document comment
- Logical steps: single line, multi line comments
Learning mode of thinking
- Focus on the big and start with the small
- Reverse thinking and counter evidence
- See the essence through problems
- If you can't bear it, you will make a big plan
- He who knows current affairs is a hero
R apply in n (T, t, U)
@Test
public void test3(){
BiFunction<Integer, String, Employee> func1 = (id, name) -> new Employee(id, name);
BiFunction<Integer, String, Employee> func2 = Employee::new;
}
##### Array reference format - Array type[] :: new ##### Array reference example ```java // Array reference // R apply in Function (T) @Test public void test4(){ Function<Integer, String[]> func1 = length -> new String[length]; String[] arr1 = func1.apply(5); System.out.println(Arrays.toString(arr1)); Function<Integer, String[]> func2 = String[]::new; String[] arr2 = func2.apply(5); System.out.println(Arrays.toString(arr2)); }
Stream API
Understanding of Stream API
-
Stream focuses on the operation of data and dealing with CPU
Collections focus on the storage of data and dealing with memory
-
Java 8 provides a set of API s that can be used to filter, sort, map and regulate data in memory, similar to SQL operations on tables in the database
Attention
- Stream itself does not store elements.
- Stream does not change the source object. Instead, they return a new stream that holds the result.
- Stream operations are deferred. This means they wait until they need results
Use process of Stream
- Instantiation of Stream
- A series of intermediate operations
- Terminate operation
Precautions for using the process
- An intermediate operation chain that processes the data of the data source
- Once the termination operation is performed, the intermediate operation chain is executed and the results are generated. After that, it will not be used again
Step 1: Stream instantiation
/** * Creation method 1: through collection */ @Test public void test1(){ List<Employee> employees = EmployeeData.getEmployees(); // Default stream < E > stream(): returns a sequential stream Stream<Employee> stream = employees.stream(); // Default stream < E > parallelstream(): returns a parallel stream Stream<Employee> parallelStream = employees.parallelStream(); } /** * Creation method 2: through array */ @Test public void test2(){ int[] arr = new int[]{1, 2, 3, 4, 5, 6}; // Static < T > stream < T > stream (t [] array): returns a stream IntStream stream = Arrays.stream(arr); Employee e1 = new Employee(1001, "Tom"); Employee e2 = new Employee(1001, "Jerry"); Employee[] employees = {e1, e2}; Stream<Employee> employeeStream = Arrays.stream(employees); } /** * Creation method 3: through of() of Stream */ @Test public void test3(){ Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6); } /** * Creation method 4: create infinite flow */ @Test public void test4(){ // Iteration public static < T > stream < T > iterate (final t seed, final unaryoperator < T > F) // Traverse the first 10 even numbers Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println); // Generate public static < T > stream < T > generate (supplier < T > s) Stream.generate(Math::random).limit(10).forEach(System.out::println); }
Step 2: intermediate operation
-
Screening and slicing
method describe filter(Predicate p) Receive Lambda and exclude some elements from the stream distinct() Filter to remove duplicate elements through hashCode() and 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) -
mapping
method describe map(Function f) Receive a function as an argument, which is applied to each element and mapped to a new element 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 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. -
sort
method describe sorted() Generate a new stream, which is sorted in natural order sorted(Comparator com) Generates a new stream, sorted in comparator order
Step 3: terminate the operation
-
Match and find
method describe allMatch(Predicate p) Check that all elements match anyMatch(Predicate p) Check to see if at least one element matches noneMatch(Predicate p) Check that no elements match findFirst() Returns the first element findAny() Returns any element in the current stream count() Returns the total number of elements in the stream max(Comparator c) Returns the maximum value in the stream min(Comparator c) Returns the minimum value in the stream foreach(Consumer c) Internal iteration (using the Collection interface requires the user to do the iteration, which is called external iteration. On the contrary, the Stream API uses internal iteration - it helps you do the iteration) -
Statute
method describe reduce(T iden, BinaryOperator b) You can combine the elements in the flow repeatedly to get a value. Return T reduce(BinaryOperator b) You can combine the elements in the flow repeatedly to get a value. Return to Optional Note: the connection between map and reduce is usually called map reduce mode, which is famous for Google's use of it for web search.
-
collect
method describe 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 Collector requires an instance of Collectors
method Return type effect toList List Collect the elements in the stream into a List toSet Set Collect the elements in the stream into a Set toCollection Collection Collect the elements in the stream into the Collection counting Long Count the number of elements in the flow summingInt Integer Summing integer attributes of elements in a stream averagingInt Double Calculates the average value of the Integer attribute of the element in the flow summarizingInt IntSummaryStatistics Collect statistics for the Integer attribute in the stream. E.g. average value joining String Each string in the connection stream maxBy Optional Select the maximum value according to the comparator minBy Optional Select the minimum value according to the comparator reducing Type of reduction Starting from an initial value as an accumulator, BinaryOperator is combined with the elements in the stream one by one to reduce it to a single value collectingAndThen The type returned by the conversion function Wrap another collector and convert its result to a function groupingBy Map<K, List> According to an attribute value, the attribute is K and the result is V partitioningBy Map<Boolean, List> Partition according to true or false
Use of Optional class
understand
It is designed to solve the null pointer problem in Java
The optional class (java.util.Optional) is a container class that can store the value of type T, representing the existence of this value. Or just save null, indicating that the value does not exist. Originally, null was used to indicate that a value does not exist. Now optional can better express this concept. And you can avoid null pointer exceptions.
common method
-
Method to create an Optional class object:
- Optional. Of (T): create an optional instance, t must be non empty;
- Optional.empty(): create an empty optional instance
- Optional. Ofnullable (T): t can be null
-
Determine whether the Optional container contains objects:
- boolean isPresent(): judge whether objects are included
- Void ifpresent (Consumer <? Super T > Consumer) * *: * * if there is a value, the implementation code of the Consumer interface will be executed, and the value will be passed to it as a parameter.
-
Get the object of the Optional container:
- T get(): if the calling object contains a value, return the value; otherwise, throw an exception
- T orElse(T other): if there is a value, it will be returned; otherwise, the specified other object will be returned.
- T orelseget (Supplier <? Extensions T > other): if there is a value, it will be returned; otherwise, it will return the object provided by the Supplier interface implementation.
- T orelsethrow (Supplier <? Extensions x > exceptionsupplier): if there is a value, it will be returned; otherwise, an exception provided by the Supplier interface implementation will be thrown.
@Test public void test1(){ // empty(): value = null inside the created Optional object Optional<Object> op1 = Optional.empty(); // Does the Optional encapsulated data contain data if (op1.isPresent()) { System.out.println("Data is empty"); } // If the Optional encapsulated data value is empty, get() will report an error. Otherwise, if value is not empty, it will return value // System.out.println(op1.get()); System.out.println(op1); System.out.println(op1.isPresent()); } @Test public void test2(){ String str = "hello"; // Of (T): encapsulates data t to generate an Optional object. It is required that t must be non empty, otherwise an error will be reported Optional<String> op1 = Optional.of(str); // get() is usually used together with the of() method to obtain the internal encapsulated data value String str1 = op1.get(); System.out.println(str1); } @Test public void test3(){ // ofNullable(T t): encapsulates the value that the data t is assigned to the internal part of Optional. It is not required that t is not empty Optional<String> op1 = Optional.ofNullable("beijing"); // orElse(T t1): if the value inside Optional is not empty, this value will be returned; if value is empty, t1 will be returned String str2 = op1.orElse("shanghai"); System.out.println(str2); }
Typical exercises
It can ensure that no null pointer exception occurs during the execution of the following methods
public String getGirlName2(Boy boy){ Optional<Boy> boyOptional = Optional.ofNullable(boy); Boy boy1 = boyOptional.orElse(new Boy(new Girl("Delireba"))); Girl girl = boy1.getGirl(); Optional<Girl> girlOptional = Optional.ofNullable(girl); Girl girl1 = girlOptional.orElse(new Girl("Gulinaza")); return girl1.getName(); } @Test public void test5(){ Boy boy = null; boy = new Boy(); boy = new Boy(new Girl("Aoi Sora")); String girlName = getGirlName2(boy); System.out.println(girlName); }
project
Project requirements
- Complete the project code at least once independently
- Accumulate common bug debugging in the process of completing the project
- "Hard" view, add output statements if necessary
- Debug
- Straighten out ideas and strengthen logic
- Parsing of memory structures such as objects and arrays
- Comply with the coding specification, identifier naming specification, etc
- Add necessary comments before classes, methods, and implementation steps of specific logic in methods
- Before class, before method, before attribute: document comment
- Logical steps: single line, multi line comments
Learning mode of thinking
- Focus on the big and start with the small
- Reverse thinking and counter evidence
- See the essence through problems
- If you can't bear it, you will make a big plan
- He who knows current affairs is a hero