Object oriented programming (basic)
Object oriented and process oriented (understanding)
- 1. Process oriented: it emphasizes the functional behavior, taking the function as the minimum unit and considering how to do it.
- 2. Object oriented: emphasize the objects with functions, take the class / object as the minimum unit, and consider who will do it.
JVM memory structure
- After compiling the source program, one or more bytecode files are generated.
- We use the class loader and interpreter in the JVM to interpret and run the generated bytecode file. This means that the class corresponding to the bytecode file needs to be loaded into memory, which involves memory parsing.
- The virtual machine stack is the stack structure mentioned at ordinary times. We store local variables in the stack structure
- Heap, we load the new structures (such as arrays and objects) into the pair space. Supplement: the attributes of objects (non static) are loaded into the heap space.
- Method area: class loading information, constant pool and static field
1. Classes and objects
1. Memory allocation mechanism of classes and objects
-
Structure analysis of java Memory
- 1. Stack: general storage of basic data types (local variables)
- 2. Heap: store objects (cat, cat, array, etc.)
- 3. Method area: constant pool (constant, such as string), class loading information
For example: schematic diagram [Cat(name,age,price)]
-
Simple analysis of the process of creating objects in java
Person p=new Person(); p.name="jack"; p.age=10;
- 1. Load the Person class information first (property and method information, which will only be loaded once)
- 2. Allocate space in the heap for default initialization
- 3. Assign the address to p, and p points to the object
- 4. Perform specified initialization, such as p.name = "jack"; p.age=10;
2. Analysis of method invocation mechanism
- When the program executes the method, it will open up an independent space (stack space)
- When the method is completed or executed to the return statement, it will return
- Return to the place where the method was called
- After returning, continue to execute the code after the method
- When the main method (stack) is executed, the whole program exits
3. Recursive call
1. Important rules
- 1. One method is to create a new protected independent space (stack space)
- 2. The local variables of the method are independent and will not affect each other
- 3. If a reference type variable (such as an array) is used in the method, the data of the reference type will be shared
- 4. Recursion must approach the condition of exiting recursion, otherwise it is infinite recursion and StackOverflowError occurs
- 5. When a method is executed and a return is encountered, it will return. The result will be returned to whoever calls it. At the same time, when the method is executed or returned, the method will also be executed
2. Print problem
public void test(int n){ if(n>2){ test(n-1); } System.out.println("n="+n); }
3. Factorial problem
public int factorial(int n){ if(n==1){ retrun 1; }else{ return factorial(n-1) * n; } }
4. Overload method
1. Benefits of overloading
- Eased the trouble of naming
- Eased the trouble of registration
2. Pay attention to details
- Method name: must be the same
- Parameter list: must be different (parameter type or number or order, at least one different, parameter name not required)
- Return type: no requirement
5. Variable parameters
1. Basic grammar
Access modifier return type method name (data type... Parameter name) {}
2. Pay attention to details
- 1. The arguments of variable parameters can be 0 or any number
- 2. Arguments to variable parameters can be arrays
- 3. The essence of variable parameters is arrays
- 4. Variable parameters can be placed in the formal parameter list together with common type parameters, but it must be ensured that the variable parameters are at the end
- 5. Only one variable parameter can appear in a formal parameter list
6. Scope
1. Pay attention to details
- Attributes and local variables can have the same name, and the principle of proximity shall be followed when accessing
- In the same scope, for example, in the same member method, two local variables cannot have the same name
- The attribute life cycle is long. It is created with the creation of the object and destroyed with the destruction of the object. A local variable with a short life cycle is created with the execution of its code block and destroyed with the end of the code block.
- Different scope
- Global variables / attributes: can be used by this class or other classes (called through objects)
- Local variable: can only be used in the corresponding method in this class
- Different modifiers
- Global variables / attributes can be modified
- Local variables cannot be decorated
7. Construction method / constructor
1. Basic grammar
[modifier] method name (formal parameter list) {method body;}
2. Explanation
- The modifier of the constructor can be default or public, protected or private
- Constructor has no return value
- Method name and class name must be the same
- Parameter lists have the same rules as member methods
- The constructor is called by the system
- Main function: complete the initialization of new objects
- When creating an object, the system will automatically call the constructor of this class to initialize the object
3. Object creation process analysis
- 1. Load the Person class information (Person.class) only once
- 2. Allocate space (address) in heap
- 3. Complete object initialization
- 3.1. Default initialization age = 0, name=null
- 3.2. Display initialization age=90 name=null
- 3.3. Constructor initialization age=20, name = Xiaoqian
- 4. The address of the object in the heap is returned to p (p is the object name, which can also be understood as a reference to the object)
8. this keyword
1. Precautions
- This keyword can be used to access the properties, methods and constructors of this class
- this is used to distinguish between properties and local variables of the current class
- Syntax for accessing member methods: this Method name (parameter list)
- Access constructor syntax: this (parameter list); Note: can only be used in constructors
- this cannot be used outside the class definition, but only in the method of the class definition
2. this memory analysis
public class This01 { //Write a main method public static void main(String[] args) { Dog dog1 = new Dog("Dazhuang", 3); System.out.println("dog1 of hashcode=" + dog1.hashCode()); dog1.info(); System.out.println("============"); Dog dog2 = new Dog("chinese rhubarb", 2); System.out.println("dog2 of hashcode=" + dog2.hashCode()); dog2.info(); } } class Dog{ //class String name; int age; // Public dog (string dName, int Dage) {/ / constructor // name = dName; // age = dAge; // } //It would be better if we could write the formal parameters of the constructor directly as attribute names //But there is a problem, according to the scope principle of variables //The constructor's name is a local variable, not an attribute //The age of the constructor is a local variable, not an attribute //==>Export this keyword to solve the problem public Dog(String name, int age){//constructor //this.name is the attribute name of the current object this.name = name; //this.age is the property age of the current object this.age = age; System.out.println("this.hashCode=" + this.hashCode()); } public void info(){//Member method, output attribute x information System.out.println("this.hashCode=" + this.hashCode()); System.out.println(name + "\t" + age + "\t"); } }
Object oriented programming (intermediate)
1. Package
Naming conventions
- com. Company name. Project name Business module name
2. Access modifier
Access level | Access modifier | similar | Same package | Subclass | Different packages |
---|---|---|---|---|---|
open | public | √ | √ | √ | √ |
under protection | protected | √ | √ | √ | × |
default | default | √ | √ | × | × |
private | private | √ | × | × | × |
3. Encapsulation
1. Pay attention to details
- 1. Subclasses inherit all properties and methods. Non private properties and methods can be accessed directly in subclasses, but private properties and methods cannot be accessed directly in subclasses. They should be accessed through public relations methods
- 2. The subclass must call the constructor of the parent class to complete the initialization of the parent class
- 3. When creating a subclass object, no matter which constructor of the subclass is used, it will always call the parameterless constructor of the parent class by default. If the parent class does not provide a parameterless constructor, you must use super in the constructor of the subclass to specify which constructor of the parent class is used to complete the initialization of the parent class. Otherwise, the compilation will not pass
- 4. If you want to specify a constructor to call the parent class, the following is displayed: Super (parameter list);
- 5. When super is used, it must be placed in the first line of the constructor (super can only be used in the constructor)
- 6. Both super() and this() can only be placed on the first line of the constructor, so the two methods cannot share a constructor
- 7. All java classes are subclasses of the Object class, and Object is the base class of all classes
- 8. The call of the parent class constructor is not limited to the direct parent class; Go up until the Object class (top-level parent class)
- 9. A subclass can inherit at most one parent class (direct inheritance), that is, the single inheritance mechanism in java
- 10. Inheritance cannot be abused. The logical relationship of is-a must be satisfied between subclasses and parent classes
public class TopBase { //The parent class is Object public TopBase() { //super(); Object's parameterless constructor System.out.println("constructor TopBase() Called...");//1 } }
public class Base extends TopBase { //Parent class //4 attributes public int n1 = 100; protected int n2 = 200; int n3 = 300; private int n4 = 400; public Base() { //Parameterless constructor System.out.println("Parent class Base()Constructor called...."); } public Base(String name, int age) {//Parametric constructor //Default super() System.out.println("Parent class Base(String name, int age)Constructor called...."); } public Base(String name) {//Parametric constructor System.out.println("Parent class Base(String name)Constructor called...."); } //The parent class provides a public method and returns n4 public int getN4() { return n4; } public void test100() { System.out.println("test100"); } protected void test200() { System.out.println("test200"); } void test300() { System.out.println("test300"); } private void test400() { System.out.println("test400"); } //call public void callTest400() { test400(); } }
//Enter ctrl + H to see the inheritance relationship of the class public class Sub extends Base { //Subclass public Sub(String name, int age) { //1. The teacher should call the parameterless constructor of the parent class, as follows or write nothing. By default, it calls super() //super();// Parameterless constructor of parent class //2. The teacher needs to call the Base(String name) constructor of the parent class //super("hsp"); //3. The teacher needs to call the Base(String name, int age) constructor of the parent class super("king", 20); //Details: when super is used, it must be placed in the first line of the constructor //Details: both super() and this() can only be placed on the first line of the constructor, so the two methods cannot share a constructor //this() can no longer be used System.out.println("Subclass Sub(String name, int age)Constructor called...."); } public Sub() {//Parameterless constructor //super(); // The default calls the parameterless constructor of the parent class super("smith", 10); System.out.println("Subclass Sub()Constructor called...."); } //When creating a subclass object, no matter which constructor of the subclass is used, the parameterless constructor of the parent class is always called by default public Sub(String name) { super("tom", 30); //do nothing... System.out.println("Subclass Sub(String name)Constructor called...."); } public void sayOk() {//Subclass method //Non private properties and methods can be accessed directly in subclasses //However, private properties and methods cannot be accessed directly in subclasses System.out.println(n1 + " " + n2 + " " + n3); test100(); test200(); test300(); //test400(); error //To provide public access through the parent class System.out.println("n4=" + getN4()); callTest400();// } }
2. Inherited memory layout
3. The essence of inheritance
/** * Explain the essence of inheritance */ public class ExtendsTheory { public static void main(String[] args) { Son son = new Son();//Memory layout //?-> At this time, please note that the information should be returned according to the search relationship //(1) First, check whether the subclass has this attribute //(2) If the subclass has this property and can be accessed, information is returned //(3) If the child class does not have this attribute, it depends on whether the parent class has this attribute (if the parent class has this attribute and can access it, it returns information..) //(4) If there is no parent class, continue to find the parent class according to the rule in (3) until Object System.out.println(son.name);//Return is big head son //System.out.println(son.age);// The return is 39 //System.out.println(son.getAge());// The return is 39 System.out.println(son.hobby);//Return is tourism } } class GrandPa { //Ye class String name = "Big head grandpa"; String hobby = "Travel"; } class Father extends GrandPa {//Parent class String name = "Big head Dad"; private int age = 39; public int getAge() { return age; } } class Son extends Father { //Subclass String name = "Big head son"; }
4. super keyword
1. Pay attention to details
- Super access is not limited to the direct parent class. If there are members with the same name in the grandfather class and this class, you can also use super to access the members of the grandfather class. If there are members with the same name in multiple base classes (superior classes), the principle of proximity is followed when using super access
2. Comparison between super and this
No. | Distinguishing points | this | super |
---|---|---|---|
1 | Access properties | Access the property in this class. If this class does not have this property, continue to find it from the parent class | Find properties from parent class |
2 | Call method | Access the method in this class. If there is no such method in this class, continue to find it from the parent class | Find method from parent class |
3 | Invoking Constructors | Calling this class constructor must be placed on the first line | Calling the parent constructor must be placed on the first line |
4 | special | Represents the current object | Accessing parent objects in subclasses |
5. Method Override
1. Pay attention to details
-
The parameter and method name of the subclass method should be exactly the same as that of the parent method
-
The return type of the subclass method is the same as that of the parent method, or it is a subclass of the parent return type. For example, the parent return type is Object and the subclass is String
-
Subclass methods cannot reduce the access rights of parent methods
2. Comparison of rewriting and overloading
name | Occurrence range | Method name | parameter list | Return type | Modifier |
---|---|---|---|---|---|
Overload | This category | Must be the same | There is at least one difference in type, number or order | No requirement | No requirement |
Override | Parent child class | Must be the same | identical | The method overridden by the subclass returns the same type as that returned by the parent class, or its subclass | Subclass methods cannot narrow the access scope of parent methods |
6. Polymorphism
1. Basic introduction
-
Methods or objects have multiple forms
-
Polymorphism is based on encapsulation and inheritance
-
When overridden, overloading reflects polymorphism
2. Pay attention to details
-
The compilation type and run type of an object can be inconsistent. The compilation type is determined when it is defined and cannot be changed
-
The running type of an object can be changed. You can view the running type through getClass()
-
The premise of polymorphism is that there is an inheritance relationship between two objects (classes)
-
Property is not rewritten! The value of the attribute depends on the compilation type
-
The instanceof comparison operator determines the running type of the object
public class PolyDetail03 { public static void main(String[] args) { BB bb = new BB(); System.out.println(bb instanceof BB);// true System.out.println(bb instanceof AA);// true //Aacompile type AA, run type BB //BB is subclass AA AA aa = new BB(); System.out.println(aa instanceof AA); System.out.println(aa instanceof BB); Object obj = new Object(); System.out.println(obj instanceof AA);//false String str = "hello"; //System.out.println(str instanceof AA); System.out.println(str instanceof Object);//true } } class AA {} //Parent class class BB extends AA {}//Subclass //----------------------------------------------------------------------------- public class Homework15 { public static void main(String[] args) { AAA obj = new BBB();//Upward transformation AAA b1 = obj; System.out.println("obj Type of operation=" + obj.getClass());//BBB obj = new CCC();//Upward transformation System.out.println("obj Type of operation=" + obj.getClass());//CCC obj = b1; System.out.println("obj Type of operation=" + obj.getClass());//BBB } } class AAA {}//Superclass class BBB extends AAA {}//Parent class class CCC extends BBB {}//Subclass
3. Upward transformation
- Polymorphism is upward transformation
- Essence: the reference of the parent class points to the object of the child class
- Syntax: parent type reference name = new subclass type ();
- characteristic
- The compilation type is on the left and the operation type is on the right
- All members in the parent class can be called (access rights are respected)
- A unique member in a subclass cannot be called
- The final running effect depends on the specific implementation of subclasses
public class PolyDetail { public static void main(String[] args) { //Upward Transformation: the reference of the parent class points to the object of the child class //Syntax: parent type reference name = new subclass type (); Animal animal = new Cat(); Object obj = new Cat();//Is that OK? Yes, Object is also a parent class of Cat //The rules for upward transformation of calling methods are as follows: //(1) All members in the parent class can be called (subject to access rights) //(2) However, you cannot call a specific member of a subclass //(#) because which members can be called in the compilation stage is determined by the compilation type //animal.catchMouse(); error //(4) The final running effect depends on the specific implementation of the subclass (running type), that is, when calling a method, find the method from the subclass (running type) //And then invoke the rule that I call the method call rule in front of me is consistent. animal.eat();//Cats eat fish animal.run();//run animal.show();//Hello, hello animal.sleep();//sleep //The teacher hopes that the catchMouse method of Cat can be called //Polymorphic downward transformation //(1) Syntax: subclass type reference name = (subclass type) parent class reference; //Ask a question? Cat is compiled as cat and run as cat Cat cat = (Cat) animal; cat.catchMouse();//A cat catches a mouse //(2) It is required that the reference of the parent class must point to an object of the current target type Dog dog = (Dog) animal; //OK? System.out.println("ok~~"); } } //Animal class public class Animal { String name = "animal"; int age = 10; public void sleep(){ System.out.println("sleep"); } public void run(){ System.out.println("run"); } public void eat(){ System.out.println("eat"); } public void show(){ System.out.println("hello,Hello"); } } //Cat class public class Cat extends Animal { public void eat(){//Method rewrite System.out.println("Cats eat fish"); } public void catchMouse(){//Cat specific methods System.out.println("A cat catches a mouse"); } } //Dog class public class Dog extends Animal {//Dog is a subclass of Animal }
4. Downward transformation
- Polymorphic downward transformation
- Syntax: subclass type reference name = (subclass type) parent type;
- Only references of the parent class can be coerced, and objects of the parent class cannot be coerced
- It is required that the reference of the parent class must point to an object in the current target type
- After the downward transformation, all members in the subclass type can be called
5. ☆ java dynamic binding mechanism
- When an object method is called, the method will be bound to the memory address / run type of the object
- When calling object properties, there is no dynamic binding mechanism. Where to declare and where to use
public class DynamicBinding { public static void main(String[] args) { //Compile type A of a, run type B A a = new B();//Upward transformation System.out.println(a.sum());//?40 -> 30 System.out.println(a.sum1());//?30-> 20 } } class A {//Parent class public int i = 10; //Dynamic binding mechanism: public int sum() {//Parent class sum() return getI() + 10;//20 + 10 } public int sum1() {//Parent class sum1() return i + 10;//10 + 10 } public int getI() {//Parent class getI return i; } } class B extends A {//Subclass public int i = 20; // public int sum() { // return i + 20; // } public int getI() {//Subclass getI() return i; } // public int sum1() { // return i + 10; // } }
6. Application of polymorphism
1. Polymorphic array
- The definition type of the array is the parent type, and the actual element type saved in it is the subclass type
public class PloyArray { public static void main(String[] args) { //Application example: an existing inheritance structure is as follows: it is required to create a Person object // Two Student objects and two Teacher objects are uniformly placed in the array, and the say method of each object is called Person[] persons = new Person[5]; persons[0] = new Person("jack", 20); persons[1] = new Student("mary", 18, 100); persons[2] = new Student("smith", 19, 30.1); persons[3] = new Teacher("scott", 30, 20000); persons[4] = new Teacher("king", 50, 25000); //Loop through the polymorphic array and call say for (int i = 0; i < persons.length; i++) { //Teacher's note: person[i] the compilation type is Person, and the running type is determined according to the actual situation with JVM System.out.println(persons[i].say());//Dynamic binding mechanism //Everyone here is smart Use type judgment + downward transformation if(persons[i] instanceof Student) {//Judge whether the running type of person[i] is Student Student student = (Student)persons[i];//Downward transformation student.study(); //Small partners can also use a statement ((student) persons [i]) study(); } else if(persons[i] instanceof Teacher) { Teacher teacher = (Teacher)persons[i]; teacher.teach(); } else if(persons[i] instanceof Person){ //System.out.println("your type is wrong, please check yourself...); } else { System.out.println("Your type is wrong, Please check yourself..."); } } } } public class Person {//Parent class private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String say() {//Return name and age return name + "\t" + age; } } //Student class public class Student extends Person { private double score; public Student(String name, int age, double score) { super(name, age); this.score = score; } public double getScore() { return score; } public void setScore(double score) { this.score = score; } //Override parent say @Override public String say() { return "student " + super.say() + " score=" + score; } //Unique method public void study() { System.out.println("student " + getName() + " Learning java..."); } } //Teacher class public class Teacher extends Person { private double salary; public Teacher(String name, int age, double salary) { super(name, age); this.salary = salary; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } //Write and override the say method of the parent class @Override public String say() { return "teacher " + super.say() + " salary=" + salary; } //Unique method public void teach() { System.out.println("teacher " + getName() + " Talking java curriculum..."); } }
2. Polymorphic parameters
- The formal parameter type defined by the method is the parent type, and the argument is allowed to be the child type
public class PloyParameter { public static void main(String[] args) { Worker tom = new Worker("tom", 2500); Manager milan = new Manager("milan", 5000, 200000); PloyParameter ployParameter = new PloyParameter(); ployParameter.showEmpAnnual(tom); ployParameter.showEmpAnnual(milan); ployParameter.testWork(tom); ployParameter.testWork(milan); } //showEmpAnnual(Employee e) //Achieve the annual salary of any employee object and call the method [e.getAnnual() in the main method. public void showEmpAnnual(Employee e) { System.out.println(e.getAnnual());//Dynamic binding mechanism } //Add a method, testWork. If it is an ordinary employee, call the work method. If it is a manager, call the manage method public void testWork(Employee e) { if(e instanceof Worker) { ((Worker) e).work();//Downward transition operation } else if(e instanceof Manager) { ((Manager) e).manage();//Downward transition operation } else { System.out.println("No treatment..."); } } } //Parent class public class Employee { private String name; private double salary; public Employee(String name, double salary) { this.name = name; this.salary = salary; } //Method of getting annual salary public double getAnnual() { return 12 * salary; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } } //Subclass Manager public class Manager extends Employee{ private double bonus; public Manager(String name, double salary, double bonus) { super(name, salary); this.bonus = bonus; } public double getBonus() { return bonus; } public void setBonus(double bonus) { this.bonus = bonus; } public void manage() { System.out.println("manager " + getName() + " is managing"); } //Rewrite the method of getting annual salary @Override public double getAnnual() { return super.getAnnual() + bonus; } } //Subclass Worker public class Worker extends Employee { public Worker(String name, double salary) { super(name, salary); } public void work() { System.out.println("Ordinary staff " + getName() + " is working"); } @Override public double getAnnual() { //Because ordinary employees have no other income, they can directly call the parent method return super.getAnnual(); } }
7,Object
1. = = comparison with equals
- ==Is a comparison operator
- ==: you can judge both the basic type and the reference type
- ==: if the basic type is judged, whether the values are equal is judged
- ==: if the reference type is judged, whether the addresses are equal is judged, that is, whether the panudan is the same object
- equals method
- equals: it is a method in the Object class. You can only judge the reference type
- The default judgment is whether the addresses are equal. Subclasses often override this method to judge whether the contents are equal
//equals source code in Object public boolean equals(Object obj) { return (this == obj); } //equals source code in Integer public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false; } //equals source code in String public boolean equals(Object anObject) { if (this == anObject) {//If it is the same object return true;//Return true } if (anObject instanceof String) {//Judgment type String anotherString = (String)anObject;//Downward transformation int n = value.length; if (n == anotherString.value.length) {//If the length is the same char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) {//Then compare the characters one by one if (v1[i] != v2[i]) return false; i++; } return true;//Returns true if all characters of two strings are equal } } return false;//If the comparison is not a string, false is returned directly }
2. hashCode method
- If two references point to the same object, the hash value must be the same
- If two references point to different objects, the hash value is different
- The hash value is mainly based on the address number. The hash value cannot be completely equivalent to the address
3. toString method
Default return: hexadecimal of full class name + @ + hash value
Subclasses often override the toString method to return the property information of the object
public class ToString_ { public static void main(String[] args) { /* Object toString() source code (1)getClass().getName() Full class name of the class (package name + class name) (2)Integer.toHexString(hashCode()) Converts the hashCode value of an object to a hexadecimal string public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } */ Monster monster = new Monster("goblin ", "Mountain patrolling", 1000); System.out.println(monster.toString() + " hashcode=" + monster.hashCode()); System.out.println("==When outputting an object directly, toString Method is called by default=="); System.out.println(monster); //Equivalent monster toString() } } class Monster { private String name; private String job; private double sal; public Monster(String name, String job, double sal) { this.name = name; this.job = job; this.sal = sal; } //Override the toString method to output the properties of the object //Use the shortcut keys to Alt + insert - > toString @Override public String toString() { //After rewriting, the attribute value of the object is generally output. Of course, programmers can customize it themselves return "Monster{" + "name='" + name + '\'' + ", job='" + job + '\'' + ", sal=" + sal + '}'; } @Override protected void finalize() throws Throwable { System.out.println("fin.."); } }
4. finalize method
- When an object is recycled, the system automatically calls the finalize method of the object. Subclasses can override this method to release resources
- When to recycle: when an object does not have any references, the jvm considers the object as a garbage object, and will use the garbage collection mechanism to destroy the object. Before destroying the object, it will call the finalize method first
- The call of garbage collection mechanism is determined by the system (that is, it has its own GC algorithm), or through System.gc(); Actively trigger garbage collection mechanism
//Demonstrate the use of Finalize public class Finalize_ { public static void main(String[] args) { Car bmw = new Car("bmw"); //At this time, the car object is garbage. The garbage collector will recycle (destroy) the object and call the finalize method of the object before destroying the object //, programmers can write their own business logic code in finalize (such as releasing resources: database connection, or opening files...) //, if the programmer does not override finalize, it will call finalize of the Object class, that is, the default processing //, if the programmer rewrites finalize, he can implement his own logic bmw = null; System.gc();//Actively invoke the garbage collector System.out.println("The program exited...."); } } class Car { private String name; //Properties, resources.. public Car(String name) { this.name = name; } //Override finalize @Override protected void finalize() throws Throwable { System.out.println("We destroy cars" + name ); System.out.println("Some resources were released..."); } }