catalogue
β¨ Initial knowledge of Java and development environment installation
π What is the Java language
π Is Java the best language
π Installation of development environment
π Double precision floating point variable
π Single precision floating point variable
π Naming rules for variables
π Understand type conversion
π Understanding numerical improvement
π Execution procedure of method call
π Relationship between arguments and formal parameters
π Method with no return value
π Overload problem to be solved
π Recursive execution process analysis
β¨ Definition and use of array
π Array as an argument to the method
π Understanding reference types
π First knowledge of JVM memory area division
π Array as the return value of the method
π Preliminary cognition of class and object
π Classes and instantiation of classes
π Field / attribute / member variable
π private implementation encapsulation
π getter and setter methods
π Import classes in package
π Putting classes in packages
π Access control for packages
π More complex inheritance relationships
π Understanding polymorphism
π Method of calling rewriting in construction method
π Implement multiple interfaces
β¨ Write in front
The basic learning of Java for more than a month has finally ended, and I have a new understanding of Java. I think this blog is very suitable for the introductory learning of Java Xiaobai. There are corresponding exercises and problem solutions at the end of each chapter, so as to consolidate my learning. The production of this blog is also very difficult for bloggers. There are many dry goods. It is recommended to collect and read it carefully. If you think this blog is good, please praise, collect and comment. Your support will be seen by more people. Don't talk more nonsense. Let's come this semester!!!
β¨ Initial knowledge of Java and development environment installation
π Java Language Overview
π What is the Java language
Java is an excellent programming language with pleasing syntax and easy to understand semantics. Moreover, Java is also a technical system formed by a series of computer software and specifications. This technical system provides a complete support environment for software development and cross platform deployment, and is widely used in embedded systems, mobile terminals, enterprise servers, large computers and other occasions.
Java developers originally wanted to register the oak trademark, but unfortunately it was used by others. So I changed my name to Java (a kind of java coffee). Java developers like to drink this kind of coffee very much, which also means offering a cup of coffee full of aroma to the world. That's why the coffee icon was born.
π Master Java
James Gosling is a software expert. He was born in on May 19, 1955 CanadaοΌJava One of the co founders of the programming language, he is generally recognized as“ Java The father of.
The title of the doctoral thesis is "the algebraic regulation of constraints". After graduation, I worked in IBM and designed the first generation of IBM workstation NeWS system, but it was not valued. Later transferred to Sun. In 1990, he cooperated with Patrick Naughton, Mike Sheridan and others in the "Green Plan", and later developed a language called "Oak", which was later renamed Java. At the end of 1994, James Gosling demonstrated Java programs at the "technology, education and Design Conference" held in Silicon Valley. In 2000, Java became the most popular computer language in the world.
π Why Java
What is the relationship between JavaScript and Java? When it comes to the relationship between the two, for example. It is equivalent to the relationship between Lei Feng and Lei Fengta, or the relationship between his wife and his wife cake (there is no relationship...). At first, JavaScript was called liveScript. At that time, java was too popular, so liveScript was renamed JavaScript to promote a wave.
Β
π Is Java the best language
No, because there are more appropriate programming languages in every field.
C language is undoubtedly the king of modern computer software programming language. Almost all operating systems are written in C language. C + + is an object-oriented C language, which has been continuously improved.
Javascript is a language that can run in the browser. The rich front-end interface is inseparable from Javascript. In recent years, Node.js has occupied a place in the back end.
Python is used for system management, and provides API s for scientific computing and text processing through high-performance precompiled libraries. It is a necessary explanatory language for Linux.
So, what are the advantages of the Java language to occupy the first place in the list?
First, the syntax is relatively simple, and developers who have learned computer programming can get started quickly.
Second, it has strong competitiveness in several fields, such as server-side programming, high-performance network programs, enterprise software transaction processing, distributed computing, Android mobile terminal application development and so on.
π Installation of development environment
π JDK installation
idea is a development tool and jdk is a development environment. There are many development tools, but the development environment can only be jdk.
For the installation of jdk, I will recommend you to station B or the installation steps written by the blogger I recommend below. Remember, you must install in the order of each step. If the installation is not good, you may be negligent.
π Installation of IEDA
IDEA website: https://www.jetbrains.com/idea/download/#section=windows
IDEA related videos
IDEA installation video: https://www.bilibili.com/video/BV1s44y1b7rV/
IDEA basic development settings: https://www.bilibili.com/video/BV13T4y1L7qP/
IDEA basic fast key settings: https://www.bilibili.com/video/BV1Lv411i7wD/
IDEA basic debugging method: https://www.bilibili.com/video/BV1mv411y7D5/
β¨ Data types and operators
π Variables and types
Variable refers to the variable quantity when the program runs It is equivalent to opening up a memory space to save some data. Type is to divide the types of variables. Variables of different types have different characteristics
Variables are closely related to our memory
π Integer variable
Basic syntax format
int Variable name = Initial value;
Code example:
public static void main(String[] args) { int a = 1; System.out.println(a); }
matters needing attention:
1. int indicates that the type of variable is an integer
2. The variable name is the identification of the variable. It is used later
3. In Java, = means assignment (different from Mathematics), which means setting an initial value for a variable
4. Initialization is optional, but it is recommended to explicitly initialize when creating variables
5. Finally, don't forget the semicolon, otherwise the compilation will fail
6. / / indicates comments. Comments are used as the explanation part of the code and do not participate in compilation and operation
Β
public static void main(String[] args) { //int a = 1; //System.out.println(a); }
In Java, an int variable takes up 4 bytes. It has no direct relationship with the operating system
What are bytes?
Byte is the basic unit of space size in the computer. The computer uses binary to represent data. We think that eight bits are one byte. Our usual computer is 8GB memory, which means 8G bytes. 1KB = 1024 bytes, 1MB = 1024 KB, 1GB = 1024 MB. Therefore, 8GB is equivalent to more than 8 billion bytes
The data range represented by 4 bytes is - 2 ^ 31 - > 2 ^ 31-1, which is about - 2.1 billion to + 2.1 billion
Β
Β
Use the following code to view the integer data range in Java:
public static void main(String[] args) { System.out.println(Integer.MAX_VALUE); // Maximum value of int System.out.println(Integer.MIN_VALUE); // Minimum value of int }
If the result of the operation exceeds the maximum range of int, overflow will occur
public static void main(String[] args) { int maxValue = Integer.MAX_VALUE; System.out.println(maxValue+1); int minValue = Integer.MIN_VALUE; System.out.println(minValue-1); }
π Long integer variable
Basic syntax format:
long Variable name = Initial value;
Code example:
public static void main(String[] args) { long num = 10L; // Define a long integer variable, and the initial value can be written as 10l (lowercase L, not number 1) System.out.println(num) ; }
matters needing attention:
1. The basic syntax format is basically the same as that of creating int variables, except that the type is changed to long
2. The initialization setting value is 10l, which represents a long integer number. 10l is also OK
3. 10 can also be used for initialization. The type of 10 is int, and the type of 10L is long. It is better to use 10 L or 10 L
In Java, the long type takes up 8 bytes. The data range represented is - 2 ^ 63 - > 2 ^ 63-1
Use the following code to view the long data range in Java:
public static void main(String[] args) { System.out.println(Long.MAX_VALUE); System.out.println(Long.MIN_VALUE); }
π Double precision floating point variable
Basic syntax format
double Variable name = Initial value;
Code example:
public static void main(String[] args) { double num = 1.0; System.out.println(num); }
public static void main(String[] args) { int a = 1; int b = 2; System.out.println(a / b); }
In Java, the value of int divided by int is still int (the decimal part will be discarded directly)
If you want to get 0.5, you need to use double type calculation
public static void main(String[] args) { double a = 1.0; double b = 2.0; System.out.println(a / b); }
public static void main(String[] args) { double num = 1.1; System.out.println(num * num); }
Although the double in Java is also 8 bytes, the memory layout of floating-point numbers is very different from that of integers, and the data range cannot be simply expressed in the form of 2 ^ n. the memory layout of Java's double type complies with IEEE 754 standard (the same as C language). If you try to use limited memory space to represent possibly infinite decimal points, there will be some precision error
π Single precision floating point variable
Basic format:
float Variable name = Initial value;
Code example:
public static void main(String[] args) { float num = 1.0f; // Writing 1.0F is also OK System.out.println(num); }
float Type occupies four bytes in Java and also complies with IEEE 754 standard. Due to the small range of data accuracy, double is preferred when floating-point numbers are used in engineering, and float is not recommended.
π Character type variable
Basic format:
char Variable name = Initial value;
Code example:
public static void main(String[] args) { char ch = 'A'; System.out.println(ch); }
matters needing attention:
1. In Java, the form of single quotation mark + single letter is used to represent the character literal value
2. The character in the computer is essentially an integer. ASCII is used to represent the character in C language, while Unicode is used to represent the character in Java. Therefore, a character occupies two bytes and represents more types of characters, including Chinese
public static void main(String[] args) { char ch = 'Oh'; System.out.println(ch); }
π Byte type variable
Basic syntax format:
byte Variable name = Initial value;
Code example:
public static void main(String[] args) { byte value = 0; System.out.println(value); }
matters needing attention:
1. The byte type also represents an integer. It only occupies one byte and represents a small range (- 128 - > + 127)
2. Byte type and character type are irrelevant
π Short integer variable
Basic syntax format:
short Variable name = Initial value;
Code example:
public static void main(String[] args) { short value = 0; System.out.println(value); }
matters needing attention:
1. short takes up 2 bytes and represents the data range of - 32768 - > + 32767
2. The scope of this expression is relatively small, and it is generally not recommended
π Boolean type variable
Basic syntax format:
boolean Variable name = Initial value;
Code example:
public static void main(String[] args) { boolean value = true; System.out.println(value); }
matters needing attention:
1. There are only two values for Boolean variables. True means true and false means false
2. Java boolean type and int cannot be converted to each other. There is no such usage as 1 for true and 0 for false
3. boolean type. Some JVM s occupy 1 byte and some occupy 1 bit.
Β
Test.java:4: error: wrong operand type of binary operator '+', System.out.println(value + 1);
π String type variable
Basic syntax format:
String Variable name = "Initial value";
Code example:
public static void main(String[] args) { String name = "zhangsan"; System.out.println(name); }
matters needing attention:
1. Java uses double quotation marks + several characters to represent string literals
2. Different from the above types, String is not a basic type, but a reference type (explained later)
3. Some specific characters in the string that are not convenient for direct representation need to be escaped
The + operation of string indicates string splicing:
public static void main(String[] args) { String a = "hello"; String b = "world"; String c = a + b; System.out.println(c); }
You can also splice strings and integers:
public static void main(String[] args) { String str = "result = "; int a = 10; int b = 20; String result = str + a + b; System.out.println(result); }
Therefore, we can easily use System.out.println to print multiple strings or numbers at the same time
public static void main(String[] args) { int a = 10; int b = 20; System.out.println("a = " + a + ",b = " + b); }
π Scope of variable
That is, the range within which the variable can take effect, which is generally the code block where the variable definition is located
π Naming rules for variables
Hard index:
1. A variable name can only contain numbers, letters and underscores
2. The number cannot begin
3. Variable names are case sensitive. That is, Num and num are two different variables
Soft index:
1. Variable naming shall be descriptive, see the meaning of name
2. The variable name should not use pinyin (but not absolute)
3. Nouns are recommended for the part of speech of variable names
4. The small hump naming method is recommended for variable naming. When a variable name is composed of multiple words, the initials of other words are capitalized except the first word
Example of small hump naming:
int maxValue = 100; String studentName = "Zhang San";
π constant
literal constant
10 // int literal constant (decimal) 010 // The int literal constant (octal) starts with the number 0. 010 is the decimal 8 0x10 // The int literal constant (hexadecimal) starts with the number 0x. 0x10 is the decimal 16 10L // long literal constant. It can also be written as 10l (lowercase L) 1.0 // double literal constant. It can also be written as 1.0D or 1.0D 1.5e2 // double literal constant. Expressed in scientific notation. Equivalent to 1.5 * 10 ^ 2 1.0f // float literal constant can also be written as 1.0F true // boolen literal constant, and also false 'a' // char literal constant. There can only be one character in single quotation marks "abc" // String literal constant. There can be multiple characters in double quotation marks
Constant modified by final keyword
π Understand type conversion
Long indicates a larger range. You can assign int to long, but you can't assign long to int
Double represents a larger range. You can assign int to double, but you can't assign double to int
Conclusion: the assignment between variables of different numerical types indicates that the type with smaller range can be implicitly converted to the type with larger range, otherwise it will not
int and boolean are assigned to each other
Conclusion: int and boolean are two irrelevant types and cannot be assigned to each other
The int literal constant assigns a value to byte
Note: the data range represented by byte is - 128 - > + 127, 256 has exceeded the range, and 100 is still within the range
Conclusion: when using literal constant assignment, Java will automatically perform some checks to determine whether the assignment is reasonable
Use cast
public static void main(String[] args) { int a = 0; double b = 10.5; a = (int)b; System.out.println(a); }
Β
Conclusion: double type can be forcibly converted to int
1. Mandatory type conversion may cause precision loss. As in the example just now, after assignment, 10.5 becomes 10, and the part after the decimal point is ignored
2. Forced type conversion is not always successful, and irrelevant types cannot be forced
Type conversion summary
1. Assignment between variables of different numeric types indicates that types with a smaller range can be implicitly converted to types with a larger range
2. If you need to assign a type with a large range to a type with a small range, you need to force type conversion, but the precision may be lost
3. When assigning a literal constant, Java will automatically check the number range
π Understanding numerical improvement
Mixed operation of int and long
public static void main(String[] args) { int a = 10; long b = 20; int c = a + b; // Compilation error, prompt that converting long to int will lose precision long d = a + b; // Compile passed }
Conclusion:
When int and long are mixed, int will be promoted to long, and the result will still be of long type. You need to use variables of long type to receive the result
If you have to use int to receive results, you need to use cast
Operation of byte and byte
public static void main(String[] args) { byte a = 10; byte b = 20; byte c = a + b; System.out.println(c); // Compilation error Test.java:5: error: incompatible type: conversion from int to byte may be lost }
Conclusion:
Byte and byte are of the same type, but there is a compilation error. The reason is that although a and b are both bytes, calculating a + b will first promote a and b to int, and then calculate. The result is also int. if this is assigned to c, the above error will occur
Correct writing:
public static void main(String[] args) { byte a = 10; byte b = 20; byte c = (byte)(a + b); System.out.println(c); }
Summary of type promotion:
1. For mixed operations of different types of data, those with a small range will be promoted to those with a large range
2. For short and byte types smaller than 4 bytes, they will be promoted to 4-byte int before operation
Conversion between int and String
Convert int to String
public static void main(String[] args) { int num = 10; // Method 1 String str1 = num + ""; // Method 2 String str2 = String.valueOf(num); System.out.println(str1); System.out.println(str2); }
Convert String to int
public static void main(String[] args) { String str = "100"; int num = Integer.parseInt(str); System.out.println(str); }
π operator
π Arithmetic operator
Basic four operators
+ - * / %
a) The result of int / int or int needs to be calculated with double
public static void main(String[] args) { int a = 1; int b = 2; System.out.println(a / b); }
b)0 cannot be a divisor
public static void main(String[] args) { int a = 1; int b = 0; System.out.println(a / b); }
c) % means remainder. You can find modules not only for int, but also for double
System.out.println(11.5 % 2.0);
Incremental assignment operator + = - = * = / =%=
public static void main(String[] args) { int a = 10; a += 1; // Equivalent to a = a + 1 System.out.println(a); }
Auto increment / Auto decrement operator + +--
public static void main(String[] args) { int a = 10; int b = ++a; System.out.println(b); int c = a++; System.out.println(c); }
Conclusion:
1. If the return value of the expression is not taken from the increment operation, there is no difference between pre increment and post increment
2. If the return value of the expression is taken, the return value of pre auto increment is the value after auto increment, and the return value of post auto increment is the value before auto increment
π Relational operator
== != < > =
public static void main(String[] args) { int a = 10; int b = 20; System.out.println(a == b); System.out.println(a != b); System.out.println(a < b); System.out.println(a > b); System.out.println(a <= b); System.out.println(a >= b); }
Note: the expression return values of relational operators are boolean
π Logical operator
&& || !
Note: the operands (operands are often the result of relational operators) and return values of logical operators are boolean
Logic and&&
Rule: if both operands are true, the result is true, otherwise the result is false
public static void main(String[] args) { int a = 10; int b = 20; int c = 30; System.out.println(a < b && b < c); }
Logical or||
Rule: if both operands are false, the result is false, otherwise the result is true
public static void main(String[] args) { int a = 10; int b = 20; int c = 30; System.out.println(a < b || b < c); }
Logical non!
Rule: the operand is true and the result is false; The operand is false and the result is true (this is a unary operator with only one operand)
public static void main(String[] args) { int a = 10; int b = 20; System.out.println(!(a < b)); }
Short-circuit evaluation
&&And | observe the rules of short circuit evaluation
1. For & &, if the left expression value is False, the overall value of the expression must be false, and there is no need to evaluate the expression on the right
2. For π, if the left expression value is true, the overall value of the expression must be true, and there is no need to calculate the right expression
public static void main(String[] args) { //We all know that calculating 10 / 0 will cause the program to throw an exception //But the code works normally, indicating that 10 / 0 is not really evaluated System.out.println(10 > 20 && 10 / 0 == 0); // Print false System.out.println(10 < 20 || 10 / 0 == 0); // Print true }
π Bitwise Operators
& | ~ ^
Bitwise AND &: if both binary bits are 1, the result is 1, otherwise the result is 0
public static void main(String[] args) { int a = 10; int b = 20; System.out.println(a & b); }
Bitwise or |: if both binary bits are 0, the result is 0, otherwise the result is 1
public static void main(String[] args) { int a = 10; int b = 20; System.out.println(a|b); }
be careful: When the operands of & and | are integers (int, short, long, byte), they represent bitwise operation; when the operands are boolean, they represent logical operation
Reverse by bit ~: if this bit is 0, it turns to 1; if this bit is 1, it turns to 0
public static void main(String[] args) { int a = 0xf; System.out.printf("%x\n", ~a); }
be careful:
1. The number of 0x prefix is hexadecimal number. Hexadecimal can be regarded as a simplified representation of binary. A hexadecimal number corresponds to 4 binary bits
2. 0xf represents 15 in hexadecimal, that is, 1111 in binary
3. printf can format the output content,% x means output in hexadecimal
4. \n indicates a newline character
Bitwise exclusive or ^: if the binary bits of two numbers are the same, the result is 0, and if they are different, the result is 1
public static void main(String[] args) { int a = 0x1; int b = 0x2; System.out.printf("%x\n", a ^ b); }
π Shift operation
<< >>
Move left < <: don't use the leftmost position, and fill 0 on the rightmost position
public static void main(String[] args) { int a = 0x10; System.out.printf("%x\n", a << 1); }
Shift right > >: do not use the rightmost bit, and fill the symbol bit on the left (positive numbers complement 0, negative numbers complement 1)
public static void main(String[] args) { int a = 0x10; System.out.printf("%x\n", a >> 1); // Run results (note that they are printed in hexadecimal) //8 int b = 0xffff0000; System.out.printf("%x\n", b >> 1); // Run results (note that they are printed in hexadecimal) //ffff8000 }
π Conditional operator
Expression 1 ? Expression 2 : Expression 3
When the value of expression 1 is true, the value of the whole expression is the value of expression 2; When the value of expression 1 is false, the value of the entire expression is the value of expression 3
public static void main(String[] args) { // Find the maximum of two integers int a = 10; int b = 20; int max = a > b ? a : b; System.out.println(max); }
π Operator precedence
public static void main(String[] args) { System.out.println(1 + 2 * 3); }
public static void main(String[] args) { System.out.println(10 < 20 && 20 < 30); }
At this time, it is obvious to calculate 10 < 20 and 20 < 30 first, and then calculate & &. Otherwise, the operation of 20 & & 20 is syntactically incorrect (& & operands can only be boolean)
Summary
1.% operation can also be calculated for double in Java
2. It is necessary to distinguish between pre auto increment and post auto increment
3. Because Java is a strongly typed language, the type check is strict, so the operands such as & & must be boolean
4. Distinguish clearly when & and | represent bitwise operation and when they represent logical operation
β¨ Program logic control
π Sequential structure
The sequential structure is relatively simple. For example, the code we wrote before is a sequential structure, which is executed line by line in the order in which the code is written.
public static void main(String[] args) { System.out.println("aaa"); System.out.println("bbb"); System.out.println("ccc"); }
If you adjust the writing order of the code, the execution order also changes
public static void main(String[] args) { System.out.println("aaa"); System.out.println("ccc"); System.out.println("bbb"); }
π Branching structure
π if statement
Basic grammatical form 1
if(Boolean expression){ //Execute code when conditions are met }
Basic grammatical form 2
if(Boolean expression){ //Execute code when conditions are met }else{ //Execute code when conditions are not met }
Basic grammatical form 3
if(Boolean expression){ //Execute code when conditions are met }else if(Boolean expression){ //Execute code when conditions are met }else{ //Execute code when none of the conditions are met }
Code example 1: Determine whether a number is odd or even
public static void main(String[] args) { int num = 10; if (num % 2 == 0) { System.out.println("num It's an even number"); } else { System.out.println("num It's an odd number"); } }
Code example 2: Determine whether a number is positive or negative
public static void main(String[] args) { int num = 10; if (num > 0) { System.out.println("num Is a positive number"); } else if (num < 0) { System.out.println("num Is a negative number"); } else { System.out.println("num Is 0"); } }
Code example 3: Determine whether a year is a leap year
public static void main(String[] args) { int year = 2000; if (year % 100 == 0) { // Judgment century leap year if (year % 400 == 0) { System.out.println("It's a leap year"); } else { System.out.println("Not a leap year"); } } else { // Ordinary leap year if (year % 4 == 0) { System.out.println("It's a leap year"); } else { System.out.println("Not a leap year"); } } }
Drape else problem
public static void main(String[] args) { int x = 10; int y = 10; if (x == 10) if (y == 10) System.out.println("aaa"); else System.out.println("bbb"); } //When writing code, try to put parentheses in if and else
π switch statement
Basic grammar
switch(integer|enumeration|character|character string){ case Content 1 : { Execute statement when content is satisfied; [break;] } case Content 2 : { Execute statement when content is satisfied; [break;] } ... default:{ Execute the statement when the content is not satisfied; [break;] } }
Code example: Output the week according to the value of day
public static void main(String[] args) { int day = 1; switch(day) { case 1: System.out.println("Monday"); break; case 2: System.out.println("Tuesday"); break; case 3: System.out.println("Wednesday"); break; case 4: System.out.println("Thursday"); break; case 5: System.out.println("Friday"); break; case 6: System.out.println("Saturday"); break; case 7: System.out.println("Sunday"); break; default: System.out.println("Incorrect input"); break; } }
According to the different values of the switch, the corresponding case statement will be executed. The case statement will be ended when a break is encountered. If the value in the switch does not match the case, the statement in default will be executed. We suggest that a switch statement should preferably carry default.
Note 1 do not omit break, otherwise the effect of "multi branch selection" will be lost
public static void main(String[] args) { int day = 1; switch(day) { case 1: System.out.println("Monday"); // break; case 2: System.out.println("Tuesday"); break; } }
Note 2 the value in switch can only be integer | enumeration | character | string
public static void main(String[] args) { double num = 1.0; switch(num) { case 1.0: System.out.println("hehe"); break; case 2.0: System.out.println("haha"); break; } }
Note 3 switch cannot express complex conditions
/ for example: If num The value of is between 10 and 20, Just print hehe // Such code is easy to express using if, but it cannot be expressed using switch if (num > 10 && num < 20) { System.out.println("hehe"); }
π Cyclic structure
π while loop
Basic syntax format:
while(Cycle condition){ Circular statement; }
Code example 1: Print numbers 1 - 10
public static void main(String[] args) { int num = 1; while (num <= 10) { System.out.print(" "+num); num++; } }
Code example 2: Calculate the sum of 1 - 100
public static void main(String[] args) { int n = 1; int result = 0; while (n <= 100) { result += n; n++; } System.out.println(result); }
Code example 3: Calculate the factorial of 5
public static void main(String[] args) { int n = 1; int result = 1; while (n <= 5) { result *= n; n++; } System.out.println(result); }
Code example 4: Calculate 1+ 2! + 3! + 4! + 5!
public static void main(String[] args) { int num = 1; int sum = 0; // The outer loop is responsible for finding the sum of factorials while (num <= 5) { int factorResult = 1; int tmp = 1; // The inner loop is responsible for the details of factoring while (tmp <= num) { factorResult *= tmp; tmp++; } sum += factorResult; num++; } System.out.println("sum = " + sum); }
matters needing attention
1. Similar to if, the statement under while may not write {}, but only one statement can be supported when it is not written. It is recommended to add {}
2. Similar to if, the {suggestion after while is written on the same line as while
3. Similar to if, do not write more semicolons after while, otherwise the loop may not execute correctly
Β
int num = 1; while (num <= 10); { System.out.println(num); num++; } // results of enforcement [No output, Program dead loop]
πbreak
The function of break is to end the loop early.
Code example: Find the multiple of the first 3 in 100 - 200
public static void main(String[] args) { int num = 100; while (num <= 200) { if (num % 3 == 0) { System.out.println("A multiple of 3 was found, by:" + num); break; } num++; } }
Β πcontinue
The function of continue is to skip this cycle and immediately enter the next cycle
Code example: Find multiples of all 3 in 100 - 200
public static void main(String[] args) { int num = 100; while (num <= 200) { if (num % 3 != 0) { num++; // Don't forget the + + here! Otherwise it will loop continue; } System.out.println("A multiple of 3 was found, by:" + num); num++; } }
π for loop
Basic grammar
for(Expression 1;Expression 2;Expression 3){ Circulatory body; }
Expression 1: used to initialize a loop variable
Expression 2: loop condition
Expression 3: update loop variable
Code example 1: Print numbers 1 - 10
for (int i = 1; i <= 10; i++) { System.out.println(i); }
Code example 2: Calculate the sum of 1 - 100
int sum = 0; for (int i = 1; i <= 100; i++) { sum += i; } System.out.println("sum = " + sum); // results of enforcement 5050
Code example 3: Calculate the factorial of 5
int result = 0; for (int i = 1; i <= 5; i++) { result *= i; } System.out.println("result = " + result);
Precautions (similar to while loop)
1. Similar to if, the statement below for may not write {}, but only one statement can be supported when it is not written. It is recommended to add {}
2. Similar to if, the {suggestion after for is written on the same line as while
3. Similar to if, do not write more semicolons after for, otherwise the loop may not execute correctly
Β
π Input and output
π Output to console
Basic grammar
public static void main(String[] args) { System.out.println("msg"); // Output a string with newline System.out.print("msg"); // Output a string without line breaks System.out.printf("format, msg"); // Format output }
println output comes with \ n,
The format output mode of print without printf is basically the same as that of printf in C language
format string
π Input from keyboard
Use Scanner to read string / integer / floating point number
import java.util.Scanner; // The util package needs to be imported public class fsfa { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("Please enter your name:"); String name = sc.nextLine(); System.out.println("Please enter your age:"); int age = sc.nextInt(); System.out.println("Please enter your salary:"); float salary = sc.nextFloat(); System.out.println("Your information is as follows:"); System.out.println("full name: "+name+"\n"+"Age:"+age+"\n"+"Salary:"+salary); sc.close(); // Note that remember to call the close method } }
Use the Scanner loop to read N numbers
import java.util.Scanner; // The util package needs to be imported public class fsfa { public static void main(String[] args) { Scanner sc = new Scanner(System.in); double sum = 0.0; int num = 0; while (sc.hasNextDouble()) { double tmp = sc.nextDouble(); sum += tmp; num++; } System.out.println("sum = " + sum); System.out.println("avg = " + sum / num); sc.close(); } }
β¨ Use of methods
π Basic usage of method
π What is a method
Significance of method existence (don't recite, focus on experience):
1. It is a modular organization code (when the code scale is complex)
2. Make sure that the code is reused, and one code can be used in multiple locations
3. Make the code easier to understand
4. Directly call the existing method for development, and there is no need to make wheels repeatedly
Recall a previously written code: calculate 1! + 2! + 3! + 4! + 5!
int sum = 0; for (int i = 1; i <= 5; i++) { int tmp = 1; for (int j = 1; j <= i; j++) { tmp *= j; } sum += tmp; } System.out.println("sum = " + sum);
π Method definition syntax
Basic grammar
// Method definition public static Method return value method name([Parameter type parameter ...]){ Method body code; [return Return value]; } // Method call Return value variable = Method name(Argument...);
Code example: implement a method to add two integers
public static void main(String[] args) { int a = 10; int b = 20; // Method call int ret = add(a, b); System.out.println("ret = " + ret); } // Definition of method public static int add(int x, int y) { return x + y; }
matters needing attention
1. public and static keywords have specific meanings here. We won't discuss them for the time being, and we'll introduce them in detail later
2. When defining a method, there can be no parameters. Each parameter must specify a type
3. When defining a method, the return value can also be null. If there is no return value, the return value type should be written as void
4. Parameters during method definition are called "formal parameters", and parameters during method call are called "arguments"
5. The method definition must be in the class, and the code can be written above or below the calling position
6. There is no concept of "function declaration" in Java
π Execution procedure of method call
Basic rules
When defining a method, the code of the method will not be executed. It will only be executed when calling
When the method is called, the argument is assigned to the formal parameter
After the parameter is passed, it will be executed to the method body code
After the method is executed (when a return statement is encountered), it is executed. Return to the method call location and continue to execute
A method can be called multiple times
Code example 1 calculates the addition of two integers
public static void main(String[] args) { int a = 10; int b = 20; System.out.println("Before the method is called for the first time"); int ret = add(a, b); System.out.println("After the first method call"); System.out.println("ret = " + ret); System.out.println("Before the second method call"); ret = add(30, 50); System.out.println("After the second method call"); System.out.println("ret = " + ret); } public static int add(int x, int y) { System.out.println("In calling method x = " + x + " y = " + y); return x + y; }
Code example: calculate 1+ 2! + 3! + 4! + 5!
public static void main(String[] args) { int sum = 0; for (int i = 1; i <= 5; i++) { sum += factor(i); } System.out.println("sum = " + sum); } public static int factor(int n) { System.out.println("calculation n Factorial of! n = " + n); int result = 1; for (int i = 1; i <= n; i++) { result *= i; } return result; }
N! Drawing explanation as an example
public static int fac(int n){ if(n==1){ return 1; } int tmp = n * fac(n-1); return tmp; } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int y = fac(n); System.out.println(y); }
π Relationship between arguments and formal parameters
Code example: exchanging two integer variables
public static void main(String[] args) { int a = 10; int b = 20; swap(a, b); System.out.println("a = " + a + " b = " + b); } public static void swap(int x, int y) { int tmp = x; x = y; y = tmp; }
Cause analysis
The code just now did not complete the data exchange
For the basic type, the formal parameter is equivalent to a copy of the argument, that is, a value passing call
int a = 10; int b = 20; int x = a; int y = b; int tmp = x; x = y; y = tmp;
As you can see, the modifications to x and y do not affect a and b
Solution: pass reference type parameters (such as array to solve this problem)
public static void main(String[] args) { int[] arr = {10, 20}; swap(arr); System.out.println("a = " + arr[0] + " b = " + arr[1]); } public static void swap(int[] arr) { int tmp = arr[0]; arr[0] = arr[1]; arr[1] = tmp; }
π Method with no return value
The return value of the method is optional. Sometimes it can not be
Code example
public static void main(String[] args) { int a = 10; int b = 20; print(a, b); } public static void print(int x, int y) { System.out.println("x = " + x + " y = " + y); }
π Method overload
π Overload problem to be solved
Code example
class Test { public static void main(String[] args) { int a = 10; int b = 20; int ret = add(a, b); System.out.println("ret = " + ret); double a2 = 10.5; double b2 = 20.5; double ret2 = add(a2, b2); System.out.println("ret2 = " + ret2); } public static int add(int x, int y) { return x + y; } } // Compilation error //Test.java:13: error: incompatible type: conversion from double to int may be lost // double ret2 = add(a2, b2);
So should you create such code?
class Test { public static void main(String[] args) { int a = 10; int b = 20; int ret = addInt(a, b); System.out.println("ret = " + ret); double a2 = 10.5; double b2 = 20.5; double ret2 = addDouble(a2, b2); System.out.println("ret2 = " + ret2); } public static int addInt(int x, int y) { return x + y; } public static double addDouble(double x, double y) { return x + y; } }
This is correct (for example, Go language does this), but Java thinks that the name addInt is unfriendly, so it's better to call it add directly.
π Use overload
Code example
public static void main(String[] args) { int a = 10; int b = 20; int ret = add(a, b); System.out.println("ret = " + ret); double a2 = 10.5; double b2 = 20.5; double ret2 = add(a2, b2); System.out.println("ret2 = " + ret2); double a3 = 10.5; double b3 = 10.5; double c3 = 20.5; double ret3 = add(a3, b3, c3); System.out.println("ret3 = " + ret3); } public static int add(int x, int y) { return x + y; } public static double add(double x, double y) { return x + y; } public static double add(double x, double y, double z) { return x + y + z; }
The names of the methods are all add. But some add is to calculate the addition of int, and some are double addition; Some calculate the addition of two numbers, and some calculate the addition of three numbers. The same method name provides different versions of implementations, called Method overload.
π Overloaded rules
For the same class, it can also be different classes:
Same method name
Method has different parameters (number of parameters or parameter type)
The return value type of the method does not affect overloading
Code example
class Test { public static void main(String[] args) { int a = 10; int b = 20; int ret = add(a, b); System.out.println("ret = " + ret); } public static int add(int x, int y) { return x + y; } public static double add(int x, int y) { return x + y; } } // Compilation error //Test.java:13: error: method add(int,int) has been defined in class test
π Method recursion
π The concept of recursion
When a method calls itself in the process of execution, it is called "recursion". Recursion is equivalent to mathematical induction. It has a starting condition and then a recurrence formula.
For example, we ask n! Starting condition: when N = 1, n! 1. This starting condition is equivalent to the end condition of recursion. Recursion formula: find n, It's hard to find directly. You can convert the problem into n! = > N * (N-1)!
Code example: recursively find the factorial of N
public static int fac(int n){ if(n==1){ return 1; } int tmp = n * fac(n-1); return tmp; } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int y = fac(n); System.out.println(y); }
π Recursive execution process analysis
public static void main(String[] args) { int n = 5; int ret = factor(n); System.out.println("ret = " + ret); } public static int factor(int n) { System.out.println("Function start, n = " + n); if (n == 1) { System.out.println("End of function, n = 1 ret = 1"); return 1; } int ret = n * factor(n - 1); System.out.println("End of function, n = " + n + " ret = " + ret); return ret; }
π Recursive exercise
Code example 1 prints each bit of a number in sequence (for example, 1234 prints 1 2 3 4)
public static void print(int num) { if (num > 9) { print(num / 10); } System.out.println(num % 10); }
Code example 2 recursively find 1 + 2 + 3 +... + 10
public static int sum(int num) { if (num == 1) { return 1; } return num + sum(num - 1); }
Code example 3 writes a recursive method, enters a non negative integer and returns the sum of the numbers that make up it. For example, if you enter 1729, you should return 1 + 7 + 2 + 9, and its sum is 19
public static int sum(int num) { if (num < 10) { return num; } return num % 10 + sum(num / 10); }
Code example 4 find the nth item of Fibonacci sequence
public static int fib(int n) { if (n == 1 || n == 2) { return 1; } return fib(n - 1) + fib(n - 2); }
//Loop (iterative) implementation public static int fib2(int n) { if(n == 1 || n == 2) { return 1; } int f1 = 1; int f2 = 1; int f3 = 0; for (int i = 3; i <= n; i++) { f3 = f1+f2; f1 = f2; f2 = f3; } return f3; }
π Recursive summary
Recursion is an important way to solve programming problems
Some problems are naturally defined recursively (such as Fibonacci sequence, binary tree, etc.), so it is easy to use recursive solutions
Some problems can be solved by using recursion and non recursion (loop). It is more recommended to use loop at this time. Compared with recursion, non recursive programs are more efficient
β¨ Definition and use of array
π Basic usage of arrays
π What is an array
Arrays essentially allow us to "batch" create variables of the same type
For example:
If you need to represent two data, you can directly create two variables int a; int b
If you need to represent five data, you can create five variables int a1; int a2; int a3; int a4; int a5;
However, if you need to represent 10000 data, you can't create 10000 variables. At this time, you need to use arrays to help us create them in batch
matters needing attention: In Java, the variables contained in the array must be of the same type
π Create array
Basic grammar
// dynamic initialization data type[] Array name = new data type [] { Initialization data }; // initiate static data type[] Array name = { Initialization data };
int[] arr = new int[]{1, 2, 3}; int[] arr = {1, 2, 3};
matters needing attention: During static initialization, the number of array elements is consistent with the format of initialization data
π Use of arrays
Code ex amp le: get length & access element
public static void main3(String[] args) { int[] array = {1,2,3,4,5,6}; //System.out.println(array.length); System.out.println(array[3]); array[3] = 19; System.out.println(array[3]); }
int[] arr = {1, 2, 3}; // Get array length System.out.println("length: " + arr.length); // Implementation result: 3 // Accessing elements in an array System.out.println(arr[1]); // Execution result: 2 System.out.println(arr[0]); // Execution result: 1 arr[2] = 100; System.out.println(arr[2]); // Execution result: 100
matters needing attention
1. Use arr.length to obtain the length of the array. This operation is a member access operator. It will be often used in object-oriented later
2. Press [] to mark the array elements. Note that the subscript counts from 0
3. Use [] to read and modify data
4. The subscript access operation cannot exceed the valid range [0, length - 1]. If it exceeds the valid range, the subscript out of range exception will occur
Β
Code example: subscript out of bounds
public static void main(String[] args) { int[] arr = {1, 2, 3}; System.out.println(arr[100]); }
Code example: traversal array
public static void main(String[] args) { int[] arr = {1, 2, 3}; for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } }
Code example: use for each to traverse an array
public static void main(String[] args) { int[] arr = {1, 2, 3}; for (int x : arr) { System.out.println(x); } }
π Array as an argument to the method
π Basic Usage
Code example: print array contents
public static void main(String[] args) { int[] arr = {1, 2, 3}; printArray(arr); } public static void printArray(int[] a) { for (int x : a) { System.out.println(x); } }
π Understanding reference types
Code example 1 Parameter passed to array type
public static void printf(int[] array) { for (int i = 0; i < array.length; i++) { System.out.print(array[i]+" "); } System.out.println(); } public static void main(String[] args) { int[] array = {1,2,3,4,5,6}; printf(array); }
Β
Code example 2 Parameter passed to built-in type
public static void func1(int[] array) { array = new int[]{11,2,13,4,51,61}; } public static void func(int[] array) { array[0] = 899; } public static void main(String[] args) { int[] array = {1,2,3,4,5,6}; System.out.println(Arrays.toString(array)); func1(array); System.out.println(Arrays.toString(array)); }
public static void func1(int[] array) { array = new int[]{11,2,13,4,51,61}; } public static void func2(int[] array) { array[0] = 899; } public static void main(String[] args) { int[] array = {1,2,3,4,5,6}; System.out.println(Arrays.toString(array)); func2(array); System.out.println(Arrays.toString(array)); }
Β
Β
Summary: In essence, the so-called "reference" only stores an address. Java sets the array as a reference type. In this way, the subsequent array parameter transfer is actually just to pass the address of the array into the function parameter. This can avoid copying the whole array (the array may be longer than, so the copying cost will be great)
π Know null
Null means "null reference" in Java, that is, an invalid reference
public static void main(String[] args) { int[] arr = null; System.out.println(arr[0]); }
The function of NULL is similar to that of NULL (NULL pointer) in C language. They all represent an invalid memory location. Therefore, no read-write operation can be performed on this memory. Once reading and writing is attempted, NullPointerException will be thrown
π First knowledge of JVM memory area division
A dormitory building will be divided into several different areas: freshmen, sophomores... Computer majors, communication majors... Memory is also similar. This large corridor is divided into many parts, and each area stores different data
PC register: only a small space to store the address of the next instruction to be executed
JVM stack: the key point is to store the local variable table (of course, there are other information). The reference to the storage address such as int[] arr we just created is saved here
Native method stack: the function of the native method stack is similar to that of the virtual machine stack. Only the saved contents are local variables of the native method. In some versions of JVM implementations (such as HotSpot), the native method stack and the virtual machine stack are together. Heap: the largest memory area managed by the JVM. Objects created with new are saved on the heap (for example, the previous new int[]{1, 2, 3})
Method area: used to store class information, constants, static variables, code compiled by the real-time compiler and other data that have been loaded by the virtual machine. The bytecode compiled by the method is saved in this area
Runtime constant pool: it is a part of the method area and stores literal (string constant) and symbol references. (note that since JDK 1.7, the runtime constant pool is on the heap)
Native method:
JVM is a program implemented based on C + +. In the process of Java program execution, it is essentially necessary to call some functions provided by C + + to interact with the underlying operating system. Therefore, some functions implemented by C + + will also be called in java development
The Native method here refers to these functions implemented in C + + and called by Java
π Array as the return value of the method
Code example: write a method to * 2 each element in the array
public static void main(String[] args) { int[] arr = {1, 2, 3}; transform(arr); printArray(arr); } public static void printArray(int[] arr) { for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } public static void transform(int[] arr) { for (int i = 0; i < arr.length; i++) { arr[i] = arr[i] * 2; } }
Β
π Two dimensional array
A two - dimensional array is essentially a one - dimensional array, but each element is a one - dimensional array
Basic grammar
data type[][] Array name = new data type [Number of rows][Number of columns] { Initialization data };
public static void main5(String[] args) { int[][] array = {{1,2,3},{4,5,6}}; int[][] array2 = new int[][]{{1,2,3},{4,5,6}}; int[][] array3 = new int[2][3]; }
public static void main(String[] args) { int[][] array = {{1,2,3},{4,5,6}}; /*System.out.println(array.length); System.out.println(array[0].length);*/ for (int i = 0; i < array.length; i++) { for (int j = 0; j < array[i].length; j++) { System.out.print(array[i][j] +" "); } System.out.println(); } System.out.println("================"); for (int[] ret : array) { for (int x :ret) { System.out.print(x +" "); } System.out.println(); } System.out.println("================"); System.out.println(Arrays.deepToString(array)); }
Β
β¨ Classes and objects
π Preliminary cognition of class and object
C language is process oriented, focuses on the process, analyzes the steps to solve the problem, and gradually solves the problem through function call.
JAVA is based on object-oriented and focuses on objects. It divides one thing into different objects and completes it by the interaction between objects.
Process oriented focuses on the process, and the behavior involved in the whole process is function.
Object oriented focuses on the object, that is, the subject involved in the process, which connects the functional implementations through logic.
Process oriented: 1. Open the refrigerator 2. Put the elephant in the refrigerator 3. Close the refrigerator object oriented: opening, storing and closing the refrigerator are the operation of the refrigerator and the behavior of the refrigerator. The refrigerator is an object, so as long as the functions of the refrigerator are operated, they must be defined in the refrigerator.
[object oriented concept]
1. Object oriented is a way of thinking and an idea, such as concept and example, theory and practice, name and reality, etc.
2. A class is a general term for a class of objects. An object is an instance of the materialization of this class.
3. The benefits of object orientation: make complex things simple, just face an object.
[object oriented design]
Object oriented design holds an important experience: who owns the data and who provides external methods to operate the data (private) ((the passive party is the owner of the data and the active party is the executor)
During development: find objects, build objects, use objects, and maintain the relationship between objects.
Process oriented
object-oriented
π Classes and instantiation of classes
π class
A class is a general term for a class of objects. An object is an instance of the materialization of this class.
Simple example: the model we use to make moon cakes is a class, through which we can make moon cakes. In this example, the class is the model and the moon cake is the object, so the moon cake is an entity. A model can instantiate countless objects.
In general: a class is equivalent to a template, and an object is a sample generated by the template. A class can generate countless objects.
Declaring a class is to create a new data type, and the class is a reference type in Java. Java uses the keyword class to declare the class. Let's see the following simple declaration of a class.
Basic grammar
// Create class class <class_name>{ field;//Member properties method;//Member method } // Instantiate object <class_name> <Object name> = new <class_name>();
Class is the keyword defining the class, ClassName is the name of the class, and {} is the body of the class.
The elements in the class are called: member attributes. The functions in the class are called: member methods.
Example:
class Person { public int age;//Member property instance variable public String name; public String sex; public void eat() {//Member method System.out.println("having dinner!"); } public void sleep() { System.out.println("sleep!"); } }
π Class instantiation
The process of creating objects with class types is called class instantiation
Class instantiation the process of creating objects with class types is called class instantiation
1. A class is just a model that defines which members a class has.
2. A class can instantiate multiple objects. The instantiated objects occupy the actual physical space and store class member variables.
3. For example, instantiating an object by a class is like building a house by using an architectural design drawing in reality. A class is like a design drawing. It only designs what it needs, but there is no physical building. Similarly, a class is only a design. The instantiated object can actually store data and occupy physical space.
class Person { public int age;//Member property instance variable public String name; public String sex; public void eat() {//Member method System.out.println("having dinner!"); } public void sleep() { System.out.println("sleep!"); } } class Main{ public static void main(String[] args) { Person person = new Person();//Instantiate objects through new person.eat();//Member method calls need to be called by reference to the object person.sleep(); //Generate object instantiation object Person person2 = new Person(); Person person3 = new Person(); } }
matters needing attention
The new keyword is used to create an instance of an object
Use. To access properties and methods in an object
You can create multiple instances of the same class
class Person { //Ordinary member variables belong to objects private String name; private int age=19; //Static member variable - > class variable public static int count;//0 }
π Member of class
π Field / attribute / member variable
In the class, but the variables defined outside the method. Such variables are called "field" or "attribute" or "member variable" (all three names can be used, and generally they will not be strictly distinguished)
Used to describe what data a class contains
class Person { public String name; // field public int age; } class Test { public static void main(String[] args) { Person person = new Person(); System.out.println(person.name); System.out.println(person.age); } }
Use. To access the fields of an object
Access includes both read and write
For the field of an object, if the initial value is not explicitly set, a default initial value will be set
Default value rule
For various numeric types, the default value is 0
For boolean types, the default value is false
For reference types (String, Array, and custom classes), the default value is null
Know null
Null is a "null reference" in Java, which means that no object is referenced. It is similar to a null pointer in C language. If NULL is operated on, an exception will be thrown
class Person { public String name; public int age; } class Test { public static void main(String[] args) { Person person = new Person(); System.out.println(person.name.length()); // Get string length } }
Field local initialization
Many times, we don't want to use the default value for the field, but we need to explicitly set the initial value. It can be written as follows:
class Person { public String name = "Zhang San"; public int age = 18; } class Test { public static void main(String[] args) { Person person = new Person(); System.out.println(person.name); System.out.println(person.age); } }
π Method
Used to describe the behavior of an object
class Person { public int age = 18; public String name = "Zhang San"; public void show() { System.out.println("My name is" + name + ", this year" + age + "year"); } } class Test { public static void main(String[] args) { Person person = new Person(); person.show(); } }
There is also a special method called Construction method When instantiating an object, the method will be automatically called. The method name is the same as the class name, which is used for object initialization. Although we have been able to initialize the attribute locally, some more complex initialization logic may be required, so the construction method can be used.
static keyword
1. Modification attribute
2. Modification method
3. Code block
4. Decoration class
a) Modifier attribute
Java static attributes are related to classes and not specific instances. In other words, different instances of the same class share the same static attribute
class TestDemo{ public int a; public static int count; } class Main{ public static void main(String[] args) { TestDemo t1 = new TestDemo(); t1.a++; TestDemo.count++; System.out.println(t1.a); System.out.println(TestDemo.count); System.out.println("============"); TestDemo t2 = new TestDemo(); t2.a++; TestDemo.count++; System.out.println(t2.a); System.out.println(TestDemo.count); } }
count is modified by static and shared by all classes. And it does not belong to an object. The access method is: class name. Attribute.
b) Modification method
If you apply the static keyword to any method, this method is called a static method.
Static methods belong to classes, not objects that belong to classes.
Static methods can be called directly without creating an instance of the class.
Static methods can access static data members and change the values of static data members.
class TestDemo{ public int a; public static int count; public static void change() { count = 100; //a = 10; error non static data members cannot be accessed } } class Main{ public static void main(String[] args) { TestDemo.change();//Can be called without creating an instance object System.out.println(TestDemo.count); } }
Note 1:
Static methods are independent of instances, but related to classes. Therefore, this leads to two situations:
Static methods cannot directly use non static data members or call non static methods (both non static data members and methods are instance related)
This and super keywords cannot be used in a static context (this is the reference of the current instance, super is the reference of the parent instance of the current instance, and is also related to the current instance)
Β
Note 2:
Static is added to all the methods we have written for simplicity. But in fact, whether a method needs static or not depends on the situation. The main method is a static method
π Summary
class Person { public int age;//Instance variables are stored in objects public String name;//Instance variable public String sex;//Instance variable public static int count;//Class variables are also called static variables. They have been generated during compilation. They belong to the class itself and have only one copy. Store in method area public final int SIZE = 10;//What is modified by final is called a constant, which also belongs to an object. It is modified by final and cannot be changed later public static final int COUNT = 99;//Static constants belong to the class itself. Only one is modified by final and cannot be changed later //Instance member function public void eat() { int a = 10;//local variable System.out.println("eat()!"); } //Instance member function public void sleep() { System.out.println("sleep()!"); } //Static member function public static void staticTest(){ //Non static members cannot be accessed //sex = "man"; error System.out.println("StaticTest()"); } } class Main{ public static void main(String[] args) { //Generate object instantiation object Person person = new Person();//person is a reference to the object System.out.println(person.age);//The default value is 0 System.out.println(person.name);//The default value is null //System.out.println(person.count);// There will be a warning! //Correct access method: System.out.println(Person.count); System.out.println(Person.COUNT); Person.staticTest(); //Summary: all methods or properties modified by static do not depend on objects. person.eat(); person.sleep(); } }
Β
π encapsulation
What is encapsulation?
>The beginning is to discuss a problem: the essence of software development is the management of program complexity. If the complexity of a software code is too high, it can not continue to maintain. How to manage complexity? Encapsulation is the most basic method
When we write code, we often involve two roles: class implementer and class caller
The essence of encapsulation is that the caller of a class does not have to know much about how the class implementer implements the class, as long as he knows how to use the class
This reduces the learning and use cost of class users, thus reducing the complexity
π private implementation encapsulation
The two keywords private/ public represent "access control"
Member variables or member methods modified by public can be directly used by class callers
The member variable or member method modified by private cannot be used by the caller of the class
In other words, the user of a class does not need to know or pay attention to the private members of a class, so that the class caller can use the class at a lower cost
Use public directly
class Person { public String name = "Zhang San"; public int age = 18; } class Test { public static void main(String[] args) { Person person = new Person(); System.out.println("My name is" + person.name + ", this year" + person.age + "year"); } }
This kind of code makes the user of the class (the code of the main method) have to understand the internal implementation of the Person class before they can use this class. The learning cost is high. Once the implementer of the class modifies the code (for example, changing the name to myName), the user of the class needs to modify his own code on a large scale, and the maintenance cost is high
class Person { private String name = "Zhang San"; private int age = 18; public void show() { System.out.println("My name is" + name + ", this year" + age + "year"); } } class Test { public static void main(String[] args) { Person person = new Person(); person.show(); } }
At this time, the field has been decorated with private. The caller of the class (in the main method) cannot use it directly. Instead, it needs to use the show method. At this time, the user of the class does not need to know the implementation details of the Person class
At the same time, if the implementer of the class modifies the name of the field, the caller of the class does not need to make any modification (the caller of the class cannot access fields such as name and age at all)
matters needing attention
Private can not only modify fields, but also modify methods. Generally, we will set fields as private attributes, but whether methods need to be set to public depends on the specific situation. Generally, we want a class to provide only "necessary" public methods, rather than setting all methods to public.
π getter and setter methods
When we use private to decorate a field, we can't use this field directly
Code example
class Person { private String name = "Zhang San"; private int age = 18; public void show() { System.out.println("My name is" + name + ", this year" + age + "year"); } } class Test { public static void main(String[] args) { Person person = new Person(); person.age = 20; person.show(); } }
Code example
class Person { private String name;//Instance member variable private int age; public void setName(String name){ //name = name;// You can't write that this.name = name;//this reference represents the object that calls the method } public String getName(){ return name; } public void show(){ System.out.println("name: "+name+" age: "+age); } public static void main(String[] args) { Person person = new Person(); person.setName("caocao"); String name = person.getName(); System.out.println(name); person.show(); } }
matters needing attention
getName is the getter method, which means to get the value of this member
setName is the setter method, which means to set the value of this member
When the formal parameter name of the set method is the same as the name of the member attribute in the class, if this is not used, it is equivalent to self assignment. This represents the reference of the current instance
Not all fields must provide setter / getter methods, but which method to provide should be determined according to the actual situation. In IDEA, you can use alt + insert (or alt + F12) to quickly generate setter / getter methods
In VSCode, you can use the right mouse button menu - > source code operation to automatically generate setter / getter methods
Β
π Construction method
π Basic grammar
Constructor is a special method. When instantiating a new object with the keyword new, it will be called automatically to complete the initialization operation
new execution process
Allocate memory space for objects
Call the constructor of the object
rule of grammar
1. The method name must be the same as the class name
2. The constructor has no return value type declaration
3. There must be at least one construction method in each class (if there is no clear definition, the system will automatically generate a parameterless construction)
matters needing attention
If no constructor is provided in the class, the compiler generates a constructor without parameters by default
If a constructor is defined in a class, the default parameterless constructor will no longer be generated
The construction method supports overloading. The rules are consistent with the overloading of ordinary methods
Code example
class Person { private String name;//Instance member variable private int age; private String sex; //Default constructor construction object public Person() { this.name = "caocao"; this.age = 10; this.sex = "male"; } //Constructor with 3 arguments public Person(String name,int age,String sex) { this.name = name; this.age = age; this.sex = sex; } public void show(){ System.out.println("name: "+name+" age: "+age+" sex: "+sex); } } class Main{ public static void main(String[] args) { Person p1 = new Person();//Call the constructor without parameters. If the program does not provide it, it will call the constructor without parameters p1.show(); Person p2 = new Person("zhangfei",80,"male");//Call the constructor with 3 parameters p2.show(); } }
π this keyword
This indicates the current object reference (note that it is not the current object). You can use this to access the fields and methods of the object
class Person { private String name;//Instance member variable private int age; private String sex; //Default constructor construction object public Person() { //this calls the constructor this("bit", 12, "man");//It must be displayed on the first line } //The relationship between these two constructors is overloaded. public Person(String name,int age,String sex) { this.name = name; this.age = age; this.sex = sex; } public void show() { System.out.println("name: "+name+" age: "+age+" sex: "+sex); } } class Main { public static void main(String[] args) { Person person = new Person();//Calling a constructor without parameters person.show(); } }
We will find that inside the constructor, we can use the this keyword. The constructor is used to construct the object. Before the object is constructed, we use this. Does this still represent the current object? Of course not. This represents the reference of the current object.
π Recognize code blocks
π What is a code block
Fields are initialized in the following ways:
1. Local initialization
2. Initialize using the construction method
3. Initialize with code block
π Common code block
class Main{ public static void main(String[] args) { { //Directly use {} definition, common method block int x = 10 ; System.out.println("x1 = " +x); } int x = 100 ; System.out.println("x2 = " +x); } }
π Construct code block
class Person{ private String name;//Instance member variable private int age; private String sex; public Person() { System.out.println("I am Person init()!"); } //Instance code block { this.name = "bit"; this.age = 12; this.sex = "man"; System.out.println("I am instance init()!"); } public void show(){ System.out.println("name: "+name+" age: "+age+" sex: "+sex); } } class Main { public static void main(String[] args) { Person p1 = new Person(); p1.show(); } }
π Static code block
class Person{ private String name;//Instance member variable private int age; private String sex; private static int count = 0;//Static member variables are shared by classes in the data method area public Person(){ System.out.println("I am Person init()!"); } //Instance code block { this.name = "bit"; this.age = 12; this.sex = "man"; System.out.println("I am instance init()!"); } //Static code block static { count = 10;//Only static data members can be accessed System.out.println("I am static init()!"); } public void show(){ System.out.println("name: "+name+" age: "+age+" sex: "+sex); } } class Main { public static void main(String[] args) { Person p1 = new Person(); Person p2 = new Person();//Will static code blocks still be executed? } }
matters needing attention
No matter how many objects are generated, the static code block will be executed only once and first.
After the static code block is executed, the instance code block (construction block) is executed, and then the constructor is executed.
π Supplementary notes
π toString method
class Person { private String name; private int age; public Person(String name,int age) { this.age = age; this.name = name; } public void show() { System.out.println("name:"+name+" " + "age:"+age); } } class Main { public static void main(String[] args) { Person person = new Person("caocao",19); person.show(); //We found that the hash value of an address is printed here. The reason: the toString method of Object is called System.out.println(person); } }
You can use methods like toString to automatically convert objects to strings
class Person { private String name; private int age; public Person(String name,int age) { this.age = age; this.name = name; } public void show() { System.out.println("name:"+name+" " + "age:"+age); } //Override the toString method of Object @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } } class Main { public static void main(String[] args) { Person person = new Person("caocao",19); person.show(); System.out.println(person); } }
Β
matters needing attention:
The toString method will be called automatically at println
The operation of converting an object into a string is called serialization
ToString is the method provided by the Object class. The Person class created by us inherits from the Object class by default. We can override toString method to implement our own version of conversion string method. (we will focus on the concepts of inheritance and rewriting later.)
@Override is called "Annotation" in Java. Here @ override means that the toString method implemented below overrides the method of the parent class. The following courses will introduce annotation in detail
π Anonymous object
Objects that are not referenced are called anonymous objects
Anonymous objects can only be used when creating objects
If an object is used only once and does not need to be used later, consider using anonymous objects
class Person { private String name; private int age; public Person(String name,int age) { this.age = age; this.name = name; } public void show() { System.out.println("name:"+name+" " + "age:"+age); } } class Main { public static void main(String[] args) { new Person("caocao",19).show();//Calling methods through anonymous objects } }
π Summary of key contents
A class can produce countless objects. A class is a template and an object is a concrete instance.
The attributes defined in class can be roughly divided into several categories: class attributes and object attributes. The data attributes modified by static are called class attributes, and the methods modified by static are called class methods. The feature is that they do not depend on objects. We can call their attributes or methods only through the class name.
Static code block takes precedence over instance code block, and instance code block takes precedence over constructor.
this keyword represents the reference of the current object. Is not the current object.
β¨ object-oriented
π package
π summary
Package Is a way to organize classes
The main purpose of using packages is to ensure the uniqueness of classes
For example, you write a Test class in your code. Then your colleagues may also write a Test class. If two classes with the same name appear, they will conflict and the code will not compile
π Import classes in package
Java has provided many ready-made classes for us to use. For example
public class TextDemo { public static void main(String[] args) { java.util.Date date = new java.util.Date(); // Get a millisecond timestamp System.out.println(date.getTime()); } }
have access to java.util.Date In this way, the functions in the Java. Util package are introduced Date Class. However, this writing method is more troublesome. You can use the import statement to import the package
import java.util.Date; public class Test { public static void main(String[] args) { Date date = new Date(); // Get a millisecond timestamp System.out.println(date.getTime()); } }
If required java.util Other classes in can be used import java.util.*
import java.util.*; public class Test { public static void main(String[] args) { Date date = new Date(); // Get a millisecond timestamp System.out.println(date.getTime()); } }
However, we prefer to explicitly specify the class name to be imported. Otherwise, it is still prone to conflict
import java.util.*; import java.sql.*; public class Test { public static void main(String[] args) { // There is a class such as Date in util and sql. At this time, ambiguity will occur and compilation error will occur Date date = new Date(); System.out.println(date.getTime()); } }
In this case, you need to use the full class name
import java.util.*; import java.sql.*; public class Test { public static void main(String[] args) { java.util.Date date = new java.util.Date(); System.out.println(date.getTime()); } }
Note: import and C + + # include There is a big difference. C + + must #include to introduce other file contents, but Java does not need it. Import is just to make it easier to write code. Import is more similar to C + + namespace and using
π Static import
Use import static to import static methods and fields in a package
import static java.lang.System.*; public class Test { public static void main(String[] args) { out.println("hello"); } }
In this way, it is more convenient to write some code, such as
import static java.lang.Math.*; public class Test { public static void main(String[] args) { double x = 30; double y = 40; // Static import is more convenient to write // double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); double result = sqrt(pow(x, 2) + pow(y, 2)); System.out.println(result); } }
π Putting classes in packages
π Basic rules
Add a package statement at the top of the file to specify which package the code is in
The package name should be specified as a unique name as far as possible, usually in the inverted form of the company's domain name (e.g. com.bit.demo1)
The package name should match the code path. For example, if you create a package of com.bit.demo1, there will be a corresponding path com/bit/demo1 to store the code
If a class does not have a package statement, the class is placed in a default package
π Operation steps
1) Create a new package in IDEA: right click SRC - > New - > package
2) Enter the package name in the pop-up dialog box, such as demo1
3) Create a class in the package, right-click package name - > New - > class, and then enter the class name
4) At the same time, we can see that a package statement appears at the top of the newly created Test.java file
π Access control for packages
We have learned about public and private in the class. Members in private can only be used inside the class. If a member does not contain public and private keywords, the member can be used in other classes inside the package, but not in classes outside the package
The following code gives an example. Demo1 and Demo2 are in the same package, and Test is in other packages
Demo1.java
package com.bit.demo; public class Demo1 { int value = 0; }
Demo2.java
package com.bit.demo; public class Demo2 { public static void main(String[] args) { Demo1 demo = new Demo1(); System.out.println(demo.value); } }
Β Test.java
package com.bit.demo; public class Demo2 { public static void main(String[] args) { Demo1 demo = new Demo1(); System.out.println(demo.value); } }
// Compilation Error:(6, 32) java: value is not public in com.bit.demo.Demo1; It cannot be accessed from an external package
π Common system packages
1. java.lang: system common basic classes (String, Object). This package is automatically imported from JDK1.1.
2. java.lang.reflect:java reflection programming package;
3. java.net: network programming development package.
4. java.sql: support package for database development.
5. java.util: a tool package provided by java. (collection class, etc.) is very important
6. java.io:I/O programming development kit.
π inherit
π background
Classes created in the code are mainly used to abstract some things (including attributes and methods) in reality. Sometimes there are some associations between objective things, so there will be some associations when expressed as classes and objects
For example, design a class to represent animals
Note that we can create a separate java file for each class. The class name must match the. Java file name (case sensitive)
// Animal.java public class Animal { public String name; public Animal(String name) { this.name = name; } public void eat(String food) { System.out.println(this.name + "I am eating" + food); } }
// Cat.java class Cat { public String name; public Cat(String name) { this.name = name; } public void eat(String food) { System.out.println(this.name + "I am eating" + food); } }
// Bird.java class Bird { public String name; public Bird(String name) { this.name = name; } public void eat(String food) { System.out.println(this.name + "I am eating" + food); } public void fly() { System.out.println(this.name + "Flying οΈΏ(οΏ£οΈΆοΏ£)οΈΏ"); } }
In this code, we found a lot of redundant code
After careful analysis, we find that Animal is related to Cat and Bird:
All three classes have the same eat method and behave exactly the same
All three classes have the same name attribute and have exactly the same meaning
Logically, Cat and Bird are both Animal (is - a semantics)
At this time, inherited classes such as Animal are called parent classes, base classes or superclasses. For classes such as Cat and Bird, we are called subclasses. Derived classes are similar to real sons inheriting their father's property. Subclasses will also inherit the fields and methods of the parent class to achieve the effect of code reuse
π rule of grammar
π Basic grammar
class Subclass extends Parent class { }
Use extends to specify the parent class
A subclass in Java can only inherit one parent class (while languages such as C++/Python support multiple inheritance)
Subclasses inherit all public fields and methods of the parent class
private fields and methods of the parent class are inaccessible in subclasses
The instance of a subclass also contains the instance of the parent class. You can use the super keyword to get a reference to the instance of the parent class
The above code can be improved by inheritance. At this time, we let Cat and Bird inherit from the Animal class, so Cat does not have to write the name field and eat method when defining
class Bird extends Animal { public Bird(String name) { super(name); } public void fly() { System.out.println(this.name + "Flying οΈΏ(οΏ£οΈΆοΏ£)οΈΏ"); } }
public class Test { public static void main(String[] args) { Cat cat = new Cat("Xiao Hei"); cat.eat("Cat food"); Bird bird = new Bird("round"); bird.fly(); } }
If we change the name to private, the subclass cannot be accessed at this time
class Bird extends Animal { public Bird(String name){ super(name); } public void fly() { System.out.println(this.name + "Flying οΈΏ(οΏ£οΈΆοΏ£)οΈΏ"); } } // Compilation error Error:(19, 32) java: name stay Animal Medium is private access control
π protected keyword
Just now, we found that if the field is set to private, the subclass cannot be accessed. However, setting it to public violates our original intention of "encapsulation". The best way to achieve the best of both worlds is the protected keyword
The fields and methods modified by protected are inaccessible to the caller of the class
For subclasses of classes and other classes in the same package, the fields and methods modified by protected are accessible
// Animal.java public class Animal { protected String name; public Animal(String name) { this.name = name; } public void eat(String food) { System.out.println(this.name + "I am eating" + food); } }
// Bird.java public class Bird extends Animal { public Bird(String name){ super(name); } public void fly() { // For the protected field of the parent class, the child class can access it correctly System.out.println(this.name + "Flying οΈΏ(οΏ£οΈΆοΏ£)οΈΏ"); } }
// Test.java and Animal.java are not in the same package public class Test { public static void main(String[] args) { Animal animal = new Animal("Small animals"); System.out.println(animal.name); // There is a compilation error at this time. name cannot be accessed } }
Summary: there are four access permissions for fields and methods in Java
private: it can be accessed inside the class, but not outside the class
Default (also called package access permission): it can be accessed inside a class. Classes in the same package can be accessed, but other classes cannot
protected: it can be accessed inside a class. Subclasses and classes in the same package can be accessed. Other classes cannot be accessed
public: both inside the class and the caller of the class can access it
π More complex inheritance relationships
// Animal.java public Animal { ... } // Cat.java public Cat extends Animal { ... } // ChineseGardenCat.java public ChineseGardenCat extends Cat { ... } // OrangeCat.java public Orange extends ChineseGardenCat { ... } ......
The inheritance method just now is called multi-layer inheritance, that is, subclasses can further derive new subclasses
Always bear in mind that the classes we write are abstractions of real things. However, the projects we really encounter in the company often have complex business and may involve a series of complex concepts, which need to be represented by code. Therefore, there will be many classes written in our real projects, and the relationship between classes will be more complex
But even so, we don't want the inheritance levels between classes to be too complex. Generally, we don't want more than three-tier inheritance relationships. If there are too many inheritance levels, we need to consider refactoring the code. If you want to restrict inheritance from syntax, you can use the final keyword
π final keyword
We once learned that when the final keyword modifies a variable or field, it represents a constant (which cannot be modified)
final int a = 10; a = 20; // Compilation error
The final keyword can also modify a class, which means that the modified class cannot be inherited
final public class Animal { ... } public class Bird extends Animal { ... } // Compilation error Error:(3, 27) java: Unable to start from the final com.bit.Animal Inherit
The function of the final keyword is to restrict the class from being inherited, which means "inflexible"
In programming, flexibility is often not a good thing. Flexibility may mean more error prone
When a class decorated with final is inherited, it will compile and report an error. At this time, it can prompt us that such inheritance is contrary to the original intention of the class design
π combination
Similar to inheritance, composition is also a way to express the relationship between classes and achieve the effect of code reuse. For example, it represents a school:
public class Student { ... } public class Teacher { ... } public class School { public Student[] students; public Teacher[] teachers; }
Composition does not involve special syntax (keywords such as extensions), but only takes an instance of one class as a field of another class. This is one of the common ways we design classes
Combinatorial representation has - a semantics
In the example just now, we can understand that a school "contains" several students and teachers
Inheritance represents is - a semantics
In the above example of "animals and cats", we can understand that a cat is also "an animal"
π polymorphic
π Upward transformation
In the example just now, we wrote the following code
Bird bird = new Bird("round");
This code can also be written like this
At this time, bird2 is a reference to a parent class (Animal) and points to an instance of a child class (Bird). This writing is called upward transformation
Why is "upward transformation"?
In object-oriented programming, for some complex scenarios (many classes, very complex inheritance relationships), the program ape will draw a UML diagram to represent the relationship between classes. At this time, the parent class is usually drawn above the child class. Therefore, we call it "upward transformation" to show the direction of the parent class
Method transmission parameter
public class Test { public static void main(String[] args) { Bird bird = new Bird("round"); feed(bird); } public static void feed(Animal animal) { animal.eat("millet"); } } // results of enforcement Yuanyuan is eating millet
At this time, the type of formal parameter Animal is Animal (base class), which actually corresponds to the instance of Bird (parent class)
Method return
public class Test { public static void main(String[] args) { Animal animal = findMyAnimal(); } public static Animal findMyAnimal() { Bird bird = new Bird("round"); return bird; } }
At this time, the method findMyAnimal returns a reference of Animal type, but actually corresponds to the instance of Bird
public class Test { public static void main(String[] args) { Animal animal = findMyAnimal(); } public static Animal findMyAnimal() { Bird bird = new Bird("round"); return bird; } }
At this time, the method findMyAnimal returns a reference of Animal type, but actually corresponds to the instance of Bird
π Dynamic binding
What happens when a method with the same name appears in the subclass and parent class? Modify the previous code slightly, add the eat method with the same name to the Bird class, and add different logs in the two eat
// Animal.java public class Animal { protected String name; public Animal(String name) { this.name = name; } public void eat(String food) { System.out.println("I am a small animal"); System.out.println(this.name + "I am eating" + food); } }
// Bird.java public class Bird extends Animal { public Bird(String name) { super(name); } public void eat(String food) { System.out.println("I am a bird"); System.out.println(this.name + "I am eating" + food); } }
// Test.java public class Test { public static void main(String[] args) { Animal animal1 = new Animal("round"); animal1.eat("millet"); Animal animal2 = new Bird("flat "); animal2.eat("millet"); } }
//Execution results
I am a small animal
Yuanyuan is eating millet
I am a bird
Bian Bian is eating millet
At this point, we find that:
Although both animal1 and animal2 are references of Animal type, animal1 points to instances of Animal type and animal2 points to instances of Bird type
Call eat methods for animal1 and animal2 respectively. It is found that animal1.eat() actually calls the methods of the parent class, while animal2.eat() actually calls the methods of the child class
Therefore, in Java, which code (which is the code of the parent class method or the code of the subclass method) is executed by calling a class method, depends on whether the reference refers to the parent object or the subclass object. This procedure is determined by the program runtime (instead of the compile period), so it is called Dynamic binding
π Method rewrite
For the eat method just now: the subclass implements the method with the same name as the parent class, and the type and number of parameters are exactly the same. This is called Override / override
Notes on rewriting
1. Rewriting and overloading are completely different
2. Ordinary methods can be overridden, but static methods modified by static cannot be overridden
3. The access permission of the method overriding the subclass cannot be lower than that of the parent class
4. The return value type of the overridden method may not be the same as that of the parent class (but it is recommended to write it the same, except in special cases)
Example of method permission: change eat of subclass to private
// Animal.java public class Animal { public void eat(String food) { ... } } // Bird.java public class Bird extends Animal { // Change the eat of the subclass to private private void eat(String food) { ... } } // Compilation error //Error: (8, 10) eat(java.lang.String) in Java: com.bit.bird cannot overwrite eat(java.lang.String) in com.bit.Animal //eat(java.lang.String) // Attempting to assign lower access rights; Previously public
In addition, for overridden methods, you can use the @ Override annotation to specify them explicitly
// Bird.java public class Bird extends Animal { @Override private void eat(String food) { ... } }
With this annotation, we can check the validity. For example, if we accidentally misspell the method name (for example, write aet), the compiler will find that there is no aet method in the parent class, and an error will be compiled, indicating that it cannot constitute rewriting. We recommend that we explicitly add it when rewriting the method in the code @ Override annotation
Summary: The difference between overloading and rewriting
In fact, method rewriting is a rule at the Java syntax level, and dynamic binding is the underlying implementation of the syntax rule of method rewriting. They essentially describe the same thing, but have different emphases
π Understanding polymorphism
With face up transformation, dynamic binding and method rewriting, we can use Polymorphism We can write some code that only focuses on the parent class, which can be compatible with various subclasses at the same time
Code example: Print multiple shapes
class Shape { public void draw() { // Don't do anything } }
class Cycle extends Shape { @Override public void draw() { System.out.println("β"); } }
class Rect extends Shape { @Override public void draw() { System.out.println("β‘"); } }
class Flower extends Shape { @Override public void draw() { System.out.println("β£"); } }
// Test.java public class Test { public static void main(String[] args) { Shape shape1 = new Flower(); Shape shape2 = new Cycle(); Shape shape3 = new Rect(); drawMap(shape1); drawMap(shape2); drawMap(shape3); } // Print a single drawing public static void drawShape(Shape shape) { shape.draw(); } }
When the caller of a class writes the drawMap method, the parameter type is shape (parent class). At this time, he does not know or pay attention to the instance of which type (subclass) the current shape reference refers to. At this time, the reference of shape may call the draw method in many different ways (related to the instance corresponding to shape), This behavior is called polymorphism
What are the benefits of using polymorphism?
1) The cost of using classes by class callers is further reduced
Encapsulation means that the caller of a class does not need to know the implementation details of the class
Polymorphism allows the caller of a class not to know what the type of the class is, but to know that the object has a method
Therefore, polymorphism can be understood as a further encapsulation, which further reduces the use cost of class callers
2) It can reduce the "loop complexity" of the code and avoid using a lot of if - else
public static void drawShapes() { Rect rect = new Rect(); Cycle cycle = new Cycle(); Flower flower = new Flower(); String[] shapes = {"cycle", "rect", "cycle", "rect", "flower"}; for(String shape : shapes) { if(shape.equals("cycle")) { cycle.draw(); } else if (shape.equals("rect")) { rect.draw(); } else if (shape.equals("flower")) { flower.draw(); } } }
If polymorphism is used, there is no need to write so many if - else branch statements, and the code is simpler
public static void drawShapes() { // We created an array of Shape objects Shape[] shapes = {new Cycle(), new Rect(), new Cycle(), new Rect(), new Flower()}; for (Shape shape : shapes) { shape.draw(); } }
What is "circle complexity"?
Circle complexity is a way to describe the complexity of a piece of code. If a piece of code is flat and straightforward, it is relatively simple and easy to understand. If there are many conditional branches or loop statements, it is considered more complex to understand
Therefore, we can simply and roughly calculate the number of conditional statements and loop statements in a piece of code. This number is called "cycle complexity". If the cycle complexity of a method is too high, refactoring needs to be considered
3) More scalable
If you want to add a new shape, the code change cost is low by using polymorphism
class Triangle extends Shape { @Override public void draw() { System.out.println("β³"); } }
For the caller of a class (drawShapes method), just create an instance of a new class, and the change cost is very low. For the case where polymorphism is not used, it is necessary to modify the if - else in drawShapes, and the change cost is higher
π Downward transformation
Upward transformation is the transformation of a child object into a parent object, and downward transformation is the transformation of a parent object into a child object. Compared with upward transformation, downward transformation is less common, but it also has certain uses
// Animal.java public class Animal { protected String name; public Animal(String name) { this.name = name; } public void eat(String food) { System.out.println("I am a small animal"); System.out.println(this.name + "I am eating" + food); } }
// Bird.java public class Bird extends Animal { public Bird(String name) { super(name); } public void eat(String food) { System.out.println("I am a bird"); System.out.println(this.name + "I am eating" + food); } public void fly() { System.out.println(this.name + "Flying"); } }
π super keyword
In the previous code, due to the rewriting mechanism, the methods of the subclass are called. What if you need to call the parent method inside the subclass? You can use the super keyword
super means to get the reference of the parent class instance. It involves two common usages
1) super is used to call the constructor of the parent class (this code has been written earlier)
public Bird(String name) { super(name); }
2) Use super to call the normal methods of the parent class
public class Bird extends Animal { public Bird(String name) { super(name); } @Override public void eat(String food) { // Modify the code so that the child calls the interface of the parent class super.eat(food); System.out.println("I am a bird"); System.out.println(this.name + "I am eating" + food); } }
In this code, if you directly call eat (without super) in the eat method of the subclass, it is considered to call the eat of the subclass itself (that is, recursion). Adding the super keyword is the method of calling the parent class
be careful The functions of super and this are somewhat similar, but we should pay attention to the differences
π Method of calling rewriting in construction method
class B { public B() { // do nothing func(); } public void func() { System.out.println("B.func()"); } }
class D extends B { private int num = 1; @Override public void func() { System.out.println("D.func() " + num); } }
public class Test { public static void main(String[] args) { D d = new D(); } }
When constructing D object, B's construction method will be called
The func method is called in the construction method of B, which triggers dynamic binding and calls to func in D.
At this time, the D object itself has not been constructed, and num is in an uninitialized state with a value of 0
Conclusion: "Make objects into a working state as simple as possible". Try not to call the method in the constructor. If this method is rewritten by child class, it will trigger dynamic binding, but at this time the subclass object has not been constructed yet, some hidden but extremely difficult problems may appear.
π summary
Polymorphism is a difficult part of object-oriented programming. We will further experience the use of polymorphism in the following abstract classes and interfaces. The focus is on the coding benefits brought by polymorphism
On the other hand, if you put aside Java, polymorphism is actually a broader concept, which is not necessarily related to the syntax of "inheritance"
The "dynamic polymorphism" in C + + is similar to that in Java. However, C + + also has a "static polymorphism" (template), which has nothing to do with the inheritance system
Polymorphism in Python embodies "duck type" and has nothing to do with inheritance system
There is no concept of "inheritance" in Go language, which can also express polymorphism
π abstract class
π rule of grammar
In the example of printing graphics just now, we found that the draw method in the parent class Shape does not seem to have any actual work. The main drawing graphics are completed by the draw methods of various subclasses of Shape. Like this method without actual work, we can design it as an abstract method. The class containing abstract methods is called abstract class (abstract class)
abstract class Shape { abstract public void draw(); }
Add the abstract keyword before the draw method to indicate that it is an abstract method. At the same time, the abstract method has no method body (without {}, it cannot execute concrete code)
For a class containing abstract methods, the abstract keyword must be added to indicate that it is an abstract class
matters needing attention
1) Abstract classes cannot be instantiated directly
Shape shape = new Shape(); // Compilation error //Error:(30, 23) java: Shape is abstract; Cannot instantiate
2) Abstract methods cannot be private
abstract class Shape { abstract private void draw(); } // Compilation error //Error:(4, 27) java: illegal modifier combination: abstract and private
3) Abstract classes can contain other non abstract methods or fields. The rules of this non abstract method are the same as those of ordinary methods. It can be overridden or called directly by subclasses
abstract class Shape { abstract public void draw(); void func() { System.out.println("func"); } } class Rect extends Shape { ... } public class Test { public static void main(String[] args) { Shape shape = new Rect(); shape.func(); } } // results of enforcement //func
π Role of abstract classes
Abstract classes exist in order to be inherited
The abstract class itself cannot be instantiated. If you want to use it, you can only create a subclass of the abstract class. Then let the subclass override the abstract methods in the abstract class
π Interface
An interface is a further step of an abstract class. An abstract class can also contain non abstract methods and fields. While the methods contained in an interface are abstract methods, and fields can only contain static constants
π rule of grammar
In the example of printing graphics just now, our parent class Shape does not contain other non abstract methods, and can also be designed as an interface
interface IShape { void draw(); } class Cycle implements IShape { @Override public void draw() { System.out.println("β"); } } public class Test { public static void main(String[] args) { IShape shape = new Rect(); shape.draw(); } }
Define an interface using interface
The methods in the interface must be abstract methods, so abstract can be omitted
The methods in the interface must be public, so public can be omitted
Cycle uses implements to inherit the interface. At this time, the meaning expressed is no longer "extension", but "implementation"
When calling, you can also create an interface reference corresponding to an instance of a subclass
Interfaces cannot be instantiated alone
Extensions vs. implementations
Extension refers to the further expansion of functions when certain functions already exist
Implementation means that there is nothing at present and needs to be constructed from scratch
An interface can only contain abstract methods. For fields , Interface can only contain final static
interface IShape { void draw(); public static final int num = 10; }
The public, static and final keywords can be omitted. The omitted num still represents the public static constant
1. When we create an interface, the name of the interface generally starts with the capital letter I
2. The naming of the interface generally uses the word of "adjective"
3. Alibaba code specification stipulates that methods and attributes in the interface should not be decorated with any symbols to keep the code concise
π Implement multiple interfaces
Sometimes we need to make a class inherit from multiple parent classes at the same time. This is done in some programming languages Multiple inheritance However, Java only supports single inheritance, and a class can only extend one parent class. However, multiple interfaces can be implemented at the same time, and the similar effect of multiple inheritance can be achieved. Now we represent a group of animals through classes
class Animal { protected String name; public Animal(String name) { this.name = name; } }
In addition, we provide another set of interfaces, which respectively mean "can fly", "can run" and "can swim"
interface IFlying { void fly(); } interface IRunning { void run(); } interface ISwimming { void swim(); }
Next, we create several specific animals
class Cat extends Animal implements IRunning { public Cat(String name) { super(name); } @Override public void run() { System.out.println(this.name + "Running on four legs"); } }
class Fish extends Animal implements ISwimming { public Fish(String name) { super(name); } @Override public void swim() { System.out.println(this.name + "He is swimming with his tail"); } }
class Frog extends Animal implements IRunning, ISwimming { public Frog(String name) { super(name); } @Override public void run() { System.out.println(this.name + "Jumping forward"); } @Override public void swim() { System.out.println(this.name + "He is kicking his legs to swim"); } }
The above code shows the most common usage in Java object-oriented programming: a class inherits a parent class and implements multiple interfaces at the same time
What are the benefits of this design? Always keep the benefits of polymorphism in mind and let the program forget the type. With an interface, the user of a class does not have to focus on the specific type, but only on whether a class has some ability
π Interface usage instance
Sort an array of objects
Given a student class
class Student { private String name; private int score; public Student(String name, int score) { this.name = name; this.score = score; } @Override public String toString() { return "[" + this.name + ":" + this.score + "]"; } }
Give a student object array and sort the elements in the object array (in descending order of scores)
Student[] students = new Student[] { new Student("Zhang San", 95), new Student("Li Si", 96), new Student("Wang Wu", 97), new Student("Zhao Liu", 92), };
Let our Student class implement the Comparable interface and the compareTo method
class Student implements Comparable{ private String name; private int score; public Student(String name, int score){ this.name = name; this.score = score; } @Override public String toString(){ return "[" + this.name + ":" + this.score + "]"; } @Override public int compareTo(Object o){ Student s = (Student)o; if(this.score > s.score){ return -1; }else if (this.score < s.score){ return 1; }else{ return 0; } } }
In the sort method, the compareTo method will be called automatically. The parameter of compareTo is Object. In fact, what is passed in is an Object of Student type. Then compare the size relationship between the current Object and the parameter Object (calculated by score)
If the current object should be placed before the parameter object, a number less than 0 is returned;
If the current object should be placed after the parameter object, a number greater than 0 is returned;
Returns 0 if the current object and the parameter object are in no order
// results of enforcement [[Wang Wu:97], [Li Si:96], [Zhang San:95], [Zhao Liu:92]]
Note: for the sort method, each object of the array to be passed in is "comparable" and needs the ability of compareTo. You can define comparison rules by overriding the compareTo method
In order to further understand the interface, we can try to implement a sort method to complete the sorting process just now (using bubble sorting)
public static void sort(Comparable[] array) { for(int bound = 0; bound < array.length; bound++){ for (int cur = array.length - 1; cur > bound; cur--){ if(array[cur - 1].compareTo(array[cur]) > 0) { // Explain that the order does not meet the requirements, and exchange the position of two variables Comparable tmp = array[cur - 1]; array[cur - 1] = array[cur]; array[cur] = tmp; } } } }
Execute the code again
sort(students); System.out.println(Arrays.toString(students)); // results of enforcement [[Wang Wu:97], [Li Si:96], [Zhang San:95], [Zhao Liu:92]]
π summary
Core differences: Abstract classes can contain ordinary methods and fields. Such ordinary methods and fields can be directly used by subclasses (without rewriting), while interfaces cannot contain ordinary methods. Subclasses must override all abstract methods