Java Learning: Object-Oriented (2)

Five, object-oriented (two)

5.1 Keyword: this

  • In Java, the this keyword is not difficult to understand, and its function is very close to its meaning.

    • It is used inside a method (accurately speaking, an instance method or a non-static method) to represent the object calling the method
    • It is used inside a constructor to represent the object that the constructor is initializing.
  • The structure that this can call: member variables, methods and constructors

5.1.1 this usage scenario

① Members of the current object are used in the instance method or constructor

In the instance method or constructor, if you use the member variable or member method of the current class, you can add this in front of it to enhance the readability of the program. However, usually we are used to omit this.

However, when the formal member variable has the same name, if you need to use the member variable in the method or constructor, you must add this to indicate that the variable is a member variable of the class. That is: we can use this to distinguish 成员变量and 局部变量. for example:
insert image description here

In addition, when using this to access properties and methods, if they are not found in this class, they will be found in the parent class.

Example 1:

class Person{
    
    		// 定义Person类
	private String name ;	
	private int age ;			
	public Person(String name,int age){
    
    	
		this.name = name ;   
		this.age = age ;  
    }
    public void setName(String name){
    
    
        this.name = name;
    }
    public void setAge(int age){
    
    
        this.age = age;
    }
	public void getInfo(){
    
    	
		System.out.println("姓名:" + name) ;
		this.speak();
	}
	public void speak(){
    
    
		System.out.println(“年龄:” + this.age);	
	}
}

Example 2:

public class Rectangle {
    
    
    int length;
    int width;

    public int area() {
    
    
        return this.length * this.width;
    }

    public int perimeter(){
    
    
        return 2 * (this.length + this.width);
    }

    public void print(char sign) {
    
    
        for (int i = 1; i <= this.width; i++) {
    
    
            for (int j = 1; j <= this.length; j++) {
    
    
                System.out.print(sign);
            }
            System.out.println();
        }
    }

    public String getInfo(){
    
    
        return "长:" + this.length + ",宽:" + this.width +",面积:" + this.area() +",周长:" + this.perimeter();
    }
}

Test class:

public class TestRectangle {
    
    
    public static void main(String[] args) {
    
    
        Rectangle r1 = new Rectangle();
        Rectangle r2 = new Rectangle();

        System.out.println("r1对象:" + r1.getInfo());
        System.out.println("r2对象:" + r2.getInfo());

        r1.length = 10;
        r1.width = 2;
        System.out.println("r1对象:" + r1.getInfo());
        System.out.println("r2对象:" + r2.getInfo());

        r1.print('#');
        System.out.println("---------------------");
        r1.print('&');

        System.out.println("---------------------");
        r2.print('#');
        System.out.println("---------------------");
        r2.print('%');
    }
}

② Constructors in the same class call each other

this can be used as a special format for constructors in a class to call each other.

  • this(): Call the parameterless constructor of this class
  • this (list of actual parameters): call the parameterized constructor of this class
public class Student {
    
    
    private String name;
    private int age;

    // 无参构造
    public Student() {
    
    
//        this("",18);//调用本类有参构造器
    }

    // 有参构造
    public Student(String name) {
    
    
        this();//调用本类无参构造器
        this.name = name;
    }
    // 有参构造
    public Student(String name,int age){
    
    
        this(name);//调用本类中有一个String参数的构造器
        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 getInfo(){
    
    
        return "姓名:" + name +",年龄:" + age;
    }
}

Notice:

  • Recursive calls cannot occur. For example, calling its own constructor.
    • Corollary: If n constructors are declared in a class, at most n - 1 constructors use "this (parameter list)"
  • this() and this (actual parameter list) can only be declared on the first line of the constructor.
    • Corollary: In a constructor of a class, at most one "this (parameter list)" can be declared

5.2 Feature 2: Inheritance

Inherited Benefits

  • The emergence of inheritance reduces code redundancy and improves code reusability.

  • The emergence of inheritance is more conducive to the expansion of functions.

  • The emergence of inheritance creates is-aa relationship between classes and classes, which provides a prerequisite for the use of polymorphism.

    • Inheritance describes the ownership relationship between things, this relationship is: is-athe relationship. It can be seen that the parent class is more general and general, and the subclass is more specific.

Note: Don't inherit just to get a function in another class!

Grammatical Formatting in Inheritance

Through extendsthe keyword, you can declare that a class B inherits another class A, and the definition format is as follows:

[修饰符] classA {
    
    
	...
}

[修饰符] classB extendsA {
    
    
	...
}

Class B, called subclass, derived class (derived class), SubClass

Class A, called parent class, super class, base class (base class), SuperClass

code example

1. Parent class

/*
 * 定义动物类Animal,做为父类
 */
public class Animal {
    
    
    // 定义name属性
    String name;
    // 定义age属性
    int age;

    // 定义动物的吃东西方法
    public void eat() {
    
    
        System.out.println(age + "岁的"
                + name + "在吃东西");
    }
}

2. Subclasses

/*
 * 定义猫类Cat 继承 动物类Animal
 */
public class Cat extends Animal {
    
    
    int count;//记录每只猫抓的老鼠数量

    // 定义一个猫抓老鼠的方法catchMouse
    public void catchMouse() {
    
    
        count++;
        System.out.println("抓老鼠,已经抓了"
                + count + "只老鼠");
    }
}

3. Test class

public class TestCat {
    
    
    public static void main(String[] args) {
    
    
        // 创建一个猫类对象
        Cat cat = new Cat();
        // 为该猫类对象的name属性进行赋值
        cat.name = "Tom";
        // 为该猫类对象的age属性进行赋值
        cat.age = 2;
        // 调用该猫继承来的eat()方法
        cat.eat();
        // 调用该猫的catchMouse()方法
        cat.catchMouse();
        cat.catchMouse();
        cat.catchMouse();
    }
}

Inheritance Details

1. The subclass will inherit all the instance variables and instance methods of the parent class
2. The subclass cannot directly access the private (private) member variables and methods in the parent class
3. In Java, the inherited keyword uses "extends" ", that is, the subclass is not a subset of the parent class, but an "extension" of the parent class
4. Java supports multi-layer inheritance (inheritance system)

class A{
    
    }
class B extends A{
    
    }
class C extends B{
    
    }

illustrate:

  • Subclass and parent class are relative concepts

  • The top-level parent class is the Object class. All classes inherit Object by default as the parent class.

5. A parent class can have multiple subclasses at the same time

class A{
    
    }
class B extends A{
    
    }
class D extends A{
    
    }
class E extends A{
    
    }

6. Java only supports single inheritance, not multiple inheritance

public class A{
    
    }
class B extends A{
    
    }

//一个类只能有一个父类,不可以有多个直接父类。
class C extends B{
    
    } 	//ok
class C extends A,B...	//error

practise:

(1) Define a ManKind class, including

  • Member variables int sex and int salary;
  • Method void manOrWoman(): Display "man" according to the value of sex (sex1) or "woman" (sex0);
  • Method void employed(): Display "no job" (salary==0) or "job" (salary!=0) according to the value of salary.
public class ManKind {
    
    
    int sex; // 成员变量:性别
    int salary; // 成员变量:工资

    public void manOrWoman(){
    
     // 方法:判断男女性别并输出
        if(sex == 1){
    
     // 如果性别为 1,表示男性
            System.out.println("man"); // 输出 man
        }else if(sex == 0){
    
     // 如果性别为 0,表示女性
            System.out.println("woman"); // 输出 woman
        }
    }

    public void employeed(){
    
     // 方法:判断是否有工作并输出
        if(salary == 0){
    
     // 如果工资为 0,表示没有工作
            System.out.println("no job"); // 输出 no job
        }else{
    
     // 否则有工作
            System.out.println("job"); // 输出 job
        }
    }
}

(2) Define the class Kids to inherit ManKind and include

  • member variable int yearsOld;
  • The method printAge() prints the value of yearsOld.
package demo07;

public class Kids extends ManKind{
    
     // 继承自 ManKind
    int yearsOld; // 成员变量:年龄

    public void printAge(){
    
     // 方法:输出年龄
        System.out.println(yearsOld); // 输出成员变量 yearsOld 的值
    }
}

(3) Define the class KidsTest, instantiate the object someKid of Kids in the main method of the class, and use this object to access the member variables and methods of its parent class.

package demo07;

public class KidsTest {
    
    
    public static void main(String[] args) {
    
    
        Kids someKid = new Kids();// 实例化 Kids 类的对象 someKid
        someKid.sex = 1; // 调用继承自 ManKind 的成员变量 sex,赋值为 1
        someKid.salary = 1000; // 调用继承自 ManKind 的成员变量 salary,赋值为 1000
        someKid.manOrWoman(); // 调用继承自 ManKind 的方法 manOrWoman,输出 man
        someKid.employeed(); // 调用继承自 ManKind 的方法 employeed,输出 job
        someKid.yearsOld = 10; // 调用 Kids 自己的成员变量 yearsOld,赋值为 10
        someKid.printAge(); // 调用 Kids 自己的方法 printAge,输出 10
    }
}

5.3 Method rewriting (override/overwrite)

All methods of the parent class will be inherited by the subclass, but when a method is inherited to the subclass, the subclass feels that the original implementation of the parent class is not suitable for its current class, what should it do? Subclasses can transform the methods inherited from the parent class, which we call methods 重写 (override、overwrite). Also known as method's 重置, 覆盖.

When the program is executed, the method of the subclass will override the method of the parent class.

example

For example, the new mobile phone adds the function of displaying the avatar of the caller, the code is as follows:

public class Phone {
    
    
    public void sendMessage(){
    
    
        System.out.println("发短信");
    }
    public void call(){
    
    
        System.out.println("打电话");
    }
    public void showNum(){
    
    
        System.out.println("来电显示号码");
    }
}

//SmartPhone:智能手机
public class SmartPhone extends Phone{
    
    
    //重写父类的来电显示功能的方法
	@Override
    public void showNum(){
    
    
        //来电显示姓名和图片功能
        System.out.println("显示来电姓名");
        System.out.println("显示头像");
    }
    //重写父类的通话功能的方法
    @Override
    public void call() {
    
    
        System.out.println("语音通话 或 视频通话");
    }
}
//TestOverride类
public class TestOverride {
    
    
    public static void main(String[] args) {
    
    
        // 创建子类对象
        SmartPhone sp = new SmartPhone();

        // 调用父类继承而来的方法
        sp.call();

        // 调用子类重写的方法
        sp.showNum();
    }
}

@Override Instructions for use:

Written on the method, it is used to detect whether the requirements of the rewritten method are met. Even if this annotation is not written, as long as the requirements are met, it is the correct way to overwrite and rewrite. It is recommended to keep it, so that the compiler can help us check the format, and it can also make it clear to programmers who read the source code that this is an overridden method.

Method Overriding Requirements

  1. The method overridden by the subclass has the same , 必须as the overridden method of the parent class .方法名称参数列表

  2. The return value type of the overridden method of the subclass 不能大于The return value type of the overridden method of the parent class. (eg: Student < Person).

Note: If the return value type is a basic data type and void, it must be the same

  1. Methods overridden by subclasses use the access rights 不能小于of overridden methods of the parent class. (public > protected > default > private)

Note: ① The private method of the parent class cannot be overridden; ② The default method of the cross-package parent class cannot be overridden

  1. The exception thrown by the subclass method cannot be greater than the exception of the overridden method of the parent class

In addition, the methods with the same name and parameters in the subclass and the parent class must be declared as non-static (that is, rewriting) or static (not rewriting) at the same time. Because the static method belongs to the class, the subclass cannot override the method of the parent class.

Method overloading and rewriting

Java中的方法重载(Overloading): It means that in the same class, there can be multiple methods with the same name but different numbers or types of parameters, that is, the same method name can be overloaded through different parameter lists. When calling these overloaded methods, the compiler will choose the most appropriate method according to the type, number and order of the actual parameters. Method overloading in Java is usually used to achieve some similar functions, thereby improving code reuse.

Java中的方法重写(Overriding): means that the subclass overrides the method in the parent class, also known as overriding. Define a method in the subclass that has the same name, parameter list, and return value type as the method in the parent class, and use the @Override annotation symbol to mark it, indicating that the method in the parent class is overridden.

Method overloading and rewriting are two methods commonly used in Java to achieve code reuse and improve scalability.

(1) In the same class

public class TestOverload {
    
    
    public int max(int a, int b){
    
    
        return a > b ? a : b;
    }
    public double max(double a, double b){
    
    
        return a > b ? a : b;
    }
    public int max(int a, int b,int c){
    
    
        return max(max(a,b),c);
    }
}

(2) In the parent-child class

public class TestOverloadOverride {
    
    
    public static void main(String[] args) {
    
    
        Son s = new Son();
        s.method(1);//只有一个形式的method方法

        Daughter d = new Daughter();
        d.method(1);
        d.method(1,2);//有两个形式的method方法
    }
}

class Father{
    
    
    public void method(int i){
    
    
        System.out.println("Father.method");
    }
}
class Son extends Father{
    
    
    public void method(int i){
    
    //重写
        System.out.println("Son.method");
    }
}
class Daughter extends Father{
    
    
    public void method(int i,int j){
    
    //重载
        System.out.println("Daughter.method");
    }
}

5.4 Keyword: super

Use super in a Java class to call the specified operation in the parent class:

  • super can be used to access properties defined in the parent class
  • super can be used to call member methods defined in the parent class
  • super can be used to call the constructor of the parent class in the constructor of the subclass

Notice:

  • Especially when there are members with the same name in the child parent class, you can use super to indicate that the member in the parent class is called
  • Super's traceability is not limited to the immediate parent class
  • The usage of super and this is similar, this represents the reference of the object of this class, and super represents the identity of the memory space of the parent class

5.4.1 Super usage scenarios

①Call the overridden method of the parent class in the subclass

  • If the subclass does not override the method of the parent class, as long as the permission modifier allows, the method of the parent class can be directly called in the subclass;
  • If the subclass overrides the method of the parent class, it needs to be passed in the subclass to super.call the overridden method of the parent class, otherwise the method rewritten by the subclass is called by default

Example:

public class Phone {
    
    
    public void sendMessage(){
    
    
        System.out.println("发短信");
    }
    public void call(){
    
    
        System.out.println("打电话");
    }
    public void showNum(){
    
    
        System.out.println("来电显示号码");
    }
}

//smartphone:智能手机
public class SmartPhone extends Phone{
    
    
    //重写父类的来电显示功能的方法
    public void showNum(){
    
    
        //来电显示姓名和图片功能
        System.out.println("显示来电姓名");
        System.out.println("显示头像");

        //保留父类来电显示号码的功能
        super.showNum();//此处必须加super.,否则就是无限递归,那么就会栈内存溢出
    }
}

Summarize:

  • There are no super. and this. in front of the method.

    • First find the matching method from the subclass, if not, then find it from the direct parent class, if not, continue to trace back
  • The method is preceded by this.

    • First find the matching method from the subclass, if not, then find it from the direct parent class, if not, continue to trace back
  • The method is preceded by super.

    • Find it from the direct parent class of the current subclass, if not, continue to trace back

②Call the member variable with the same name in the parent class in the subclass

  • If the instance variable has the same name as the local variable, you can add this. in front of the instance variable to distinguish it
  • If the instance variable of the subclass and the instance variable of the parent class have the same name, and the instance variable of the parent class is still visible in the subclass, in order to access the instance variable declared by the parent class in the subclass, you need to add super. before the instance variable of the parent class, otherwise The default access is the instance variable declared by the subclass itself
  • If the instance variables of the parent and child classes do not have the same name, as long as the permission modifier allows, the instance variables declared in the parent class can be directly accessed in the subclass, and can also be accessed by using this.instance or super.instance variable

Example:

class Father{
    
    
	int a = 10;
	int b = 11;
}
class Son extends Father{
    
    
	int a = 20;
    
    public void test(){
    
    
		//子类与父类的属性同名,子类对象中就有两个a
		System.out.println("子类的a:" + a);//20  先找局部变量找,没有再从本类成员变量找
        System.out.println("子类的a:" + this.a);//20   先从本类成员变量找
        System.out.println("父类的a:" + super.a);//10    直接从父类成员变量找
		
		//子类与父类的属性不同名,是同一个b
		System.out.println("b = " + b);//11  先找局部变量找,没有再从本类成员变量找,没有再从父类找
		System.out.println("b = " + this.b);//11   先从本类成员变量找,没有再从父类找
		System.out.println("b = " + super.b);//11  直接从父类局部变量找
	}
	
	public void method(int a, int b){
    
    
		//子类与父类的属性同名,子类对象中就有两个成员变量a,此时方法中还有一个局部变量a		
		System.out.println("局部变量的a:" + a);//30  先找局部变量
        System.out.println("子类的a:" + this.a);//20  先从本类成员变量找
        System.out.println("父类的a:" + super.a);//10  直接从父类成员变量找

        System.out.println("b = " + b);//13  先找局部变量
		System.out.println("b = " + this.b);//11  先从本类成员变量找
		System.out.println("b = " + super.b);//11  直接从父类局部变量找
    }
}
class Test{
    
    
    public static void main(String[] args){
    
    
        Son son = new Son();
		son.test();
		son.method(30,13);  
    }
}

Summary: different starting points (proximity principle)

  • Variables are not preceded by super. and this.

    • If a variable is used in a constructor, code block, or method, first check whether it is declared by the current block 局部变量,
    • If it is not a local variable, start with the currently executing code本类去找成员变量
    • If it is not found in the class currently executing the code, it will look up 父类声明的成员变量(permission modifiers allow access in subclasses)
  • Variables are preceded by this.

    • When looking for member variables through this, first start from the currently executing codeThis class finds member variables
    • If it is not found in the class currently executing the code, it will look up == member variables declared by the parent class (== permission modifiers allow access in subclasses)
  • Variables preceded by super.

    • Find member variables through super, and directly find member variables from the direct parent class of the currently executing code (permission modifiers allow access in subclasses)
    • If there is no direct parent class, go to the parent class of the parent class to find it (permission modifiers allow access in subclasses)

Special Note: Subclass declarations and member variables with the same name as the parent class should be avoided

③Call the parent class constructor in the subclass constructor

In Java, a subclass can call the constructor of the parent class to initialize the member variables of the parent class, and use the super() method to explicitly call the constructor of the parent class. If the constructor of the subclass does not explicitly call the constructor of the superclass, the no-argument constructor of the superclass will be called by default. Use the super() method on the first line of the subclass constructor to call the superclass constructor. For example:

class Parent {
    
    
    int x;
    Parent(int x) {
    
    
        this.x = x;
    }
}

class Child extends Parent {
    
    
    int y;
    Child(int x, int y) {
    
    
        super(x); // 调用父类的构造器,初始化父类的 x 成员变量
        this.y = y;
    }
}

public class Test {
    
    
    public static void main(String[] args) {
    
    
        Child c = new Child(10, 20);
        System.out.println(c.x); // 输出 10,父类的 x 成员变量已经被初始化
        System.out.println(c.y); // 输出 20
    }
}

Use the super() method in the constructor of the subclass to explicitly call the constructor of the parent class, so that the subclass can also complete the initialization of the parent class during initialization, ensuring the correct operation of the program. At the same time, in actual programming, you need to pay attention to the following points:

  1. If the parent class constructor is not explicitly called in the subclass constructor, the system will call the parent class's no-argument constructor by default. If the parent class does not have a no-argument constructor or the access control of the no-argument constructor is private, it will compile mistake. At this time, you need to explicitly call the parent class constructor in the subclass constructor, and the syntax is super (parameter list).
  2. The call to the superclass constructor should be placed on the first line of the subclass constructor.
  3. If the parent class constructor has multiple constructors, the subclass can explicitly call the specified parent class constructor through super(parameter list). A subclass constructor can only call one superclass constructor, and it must be declared on the first line.
  4. When there is an initialization statement in the parent class constructor, the subclass must write its own constructor and call the parent class constructor.

5.4.2 this and super

1. The meaning of this and super

this: the current object

  • In constructors and non-static code blocks, objects that are being new
  • In an instance method, the object that calls the current method

super: Refers to the members declared by the parent class

2. The usage format of this and super

  • this
    • this.Member variable: represents a member variable of the current object, not a local variable
    • this.Member method: Indicates a member method of the current object, you can completely omit this.
    • this() or this (actual parameter list): call another constructor to assist in the instantiation of the current object, only in the first line of the constructor, only the constructor of this class will be found, and an error will be reported if it cannot be found
  • super
    • super. Member variable: Indicates a member variable of the current object, which is declared in the parent class
    • super. Member method: Indicates a member method of the current object, which is declared in the parent class
    • super() or super (list of actual parameters): Call the constructor of the parent class to assist in the instantiation of the current object, only in the first line of the constructor, only the corresponding constructor of the direct parent class will be found, and an error will be reported if it cannot be found

practise

1. Write a class demo account named Account. The properties and methods of this class are shown in the figure below. Attributes included in this class: account id, balance balance, annualInterestRate; methods included: accessor method (getter and setter methods), method getMonthlyInterest() that returns monthly interest rate, withdrawal method withdraw(), deposit method deposit() .

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-ZPqLKGpD-1680682124909)(images/image-20220324003430464.png)]

package demo08;

public class Account {
    
    
    private int id; //账号id
    private double balance; //余额balance
    private double annualInterestRate; //年利率annualInterestRate
    public Account(int id, double balance, double annualInterestRate) {
    
    
        this.id = id;
        this.balance = balance;
        this.annualInterestRate = annualInterestRate;

    }
    public int getId() {
    
     // 获取账户
        return id;
    }

    public void setId(int id) {
    
     // 设置账户
        this.id = id;
    }

    public double getBalance() {
    
     // 获取余额
        return balance;
    }

    public void setBalance(double balance) {
    
     // 设置余额
        this.balance = balance;
    }

    public double getAnnualInterestRate() {
    
     //获取年利率
        return annualInterestRate;
    }

    public void setAnnualInterestRate(double annualInterestRate) {
    
     // 设置年利率
        this.annualInterestRate = annualInterestRate;
    }

    public double getMonthlyInterest() {
    
     // 获取月利率
        return annualInterestRate / 12;
    }

    public void withdraw(double amount) {
    
     // 取款
        if (amount > balance) {
    
    
            System.out.println("余额不足");
        } else {
    
    
            balance -= amount;
            System.out.println("成功取款" + amount + "元,账户余额为" + balance + "元");
        }
    }

    public void deposit(double amount) {
    
     // 存款
        balance += amount;
        System.out.println("成功存款" + amount + "元,账户余额为" + balance + "元");
    }
}

2. Create a subclass CheckAccount of the Account class to represent an account that can be overdrafted. An attribute overdraft is defined in the account to represent the overdraft limit. Override the withdraw method in the CheckAccount class, and its algorithm is as follows:

如果(取款金额<账户余额),
	可直接取款
如果(取款金额>账户余额),
	计算需要透支的额度
	判断可透支额overdraft是否足够支付本次透支需要,如果可以
		将账户余额修改为0,冲减可透支金额
	如果不可以
		提示用户超过可透支额的限额
package demo08;

public class CheckAccount extends Account{
    
    
    private double overdraft;

    public CheckAccount(int id, double balance, double annualInterestRate, double overdraft) {
    
    
        super(id, balance, annualInterestRate);
        this.overdraft = overdraft;
    }

    public double getOverdraft() {
    
    
        return overdraft;
    }

    public void setOverdraft(double overdraft) {
    
    
        this.overdraft = overdraft;
    }
    @Override
    public void withdraw(double amount) {
    
     // 取款
        if (amount <= getBalance() + overdraft) {
    
    
            if (amount <= getBalance()) {
    
    
                setBalance(getBalance() - amount);
                System.out.println("成功取款" + amount + "元,账户余额为" + getBalance() + "元");
            } else {
    
    
                double overdraftAmount = amount - getBalance();
                setBalance(0);
                overdraft -= overdraftAmount;
                System.out.println("成功取款" + amount + "元,账户余额为0元,已透支" + overdraftAmount + "元,可透支额为" + overdraft + "元");
            }
        } else {
    
    
            System.out.println("余额不足,可透支额为" + overdraft + "元");
        }
    }
}

Requirements:
Write a user program to test the Account class. In the user program, create an Account object with an account number of 1122, a balance of 20,000, and an annual interest rate of 4.5%. Use the withdraw method to withdraw 30,000 yuan and print the balance.
Then use the withdraw method to withdraw 2,500 yuan, use the deposit method to deposit 3,000 yuan, and then print the balance and monthly interest rate.
Tip: In the withdrawal method withdraw, it is necessary to judge whether the user's balance can meet the requirements of the withdrawal amount, and if not, a prompt should be given.
Write a user program to test the CheckAccount class. In the user program, create a CheckAccount object with an account number of 1122, a balance of 20,000, an annual interest rate of 4.5%, and an overdraft limit of 5,000 yuan.
Use the withdraw method to withdraw 5,000 yuan, and print the account balance and overdraft amount.
Then use the withdraw method to withdraw 18,000 yuan, and print the account balance and overdraft amount.
Then use the withdraw method to withdraw 3,000 yuan, and print the account balance and overdraft amount.
Tips:
(1) The construction method of the subclass CheckAccount needs to initialize all the 3 attributes inherited from the parent class and the attributes of the subclass itself.
(2) The attribute balance of the parent class Account is set to private, but its value needs to be modified in the withdraw method of the subclass CheckAccount, so the balance attribute of the parent class should be modified and defined as protected.

package demo08;
public class Test {
    
    
    public static void main(String[] args) {
    
    
        // 创建账号为1122、余额为20000、年利率4.5%的Account对象
        Account account = new Account(1122, 20000, 0.045);
        // 使用withdraw方法提款30000元,并打印余额
        account.withdraw(30000);
        // 使用withdraw方法提款2500元,使用deposit方法存款3000元,然后打印余额和月利率
        account.withdraw(2500);
        account.deposit(3000);
        System.out.println("账户余额为" + account.getBalance() + "元,月利率为" + account.getMonthlyInterest() * 100 + "%");

        // 创建账号为1122、余额为20000、年利率4.5%,可透支限额为5000元的CheckAccount对象
        CheckAccount checkAccount = new CheckAccount(1122, 20000, 0.045, 5000);
        // 使用withdraw方法提款5000元,并打印账户余额和可透支额
        checkAccount.withdraw(5000);
        System.out.println("账户余额为" + checkAccount.getBalance() + "元,可透支额为" + checkAccount.getOverdraft() + "元");
        // 使用withdraw方法提款18000元,并打印账户余额和可透支额
        checkAccount.withdraw(18000);
        System.out.println("账户余额为" + checkAccount.getBalance() + "元,可透支额为" + checkAccount.getOverdraft() + "元");
        // 使用withdraw方法提款3000元,并打印账户余额和可透支额
        checkAccount.withdraw(3000);
        System.out.println("账户余额为" + checkAccount.getBalance() + "元,可透支额为" + checkAccount.getOverdraft() + "元");
    }
}

>运行结果
余额不足
成功取款2500.0元,账户余额为17500.0元
成功存款3000.0元,账户余额为20500.0元
账户余额为20500.0元,月利率为0.375%
成功取款5000.0元,账户余额为15000.0元
账户余额为15000.0元,可透支额为5000.0元
成功取款18000.0元,账户余额为0元,已透支3000.0元,可透支额为2000.0元
账户余额为0.0元,可透支额为2000.0元
余额不足,可透支额为2000.0元
账户余额为0.0元,可透支额为2000.0

The whole process of subclass object instantiation

[External link image transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the image and upload it directly (img-GiQ5vZpD-1680443622972)(images/image-20220324003713230.png)]

Example:

class Creature {
    
    
    public Creature() {
    
    
        System.out.println("Creature无参数的构造器");
	}
}
class Animal extends Creature {
    
    
    public Animal(String name) {
    
    
        System.out.println("Animal带一个参数的构造器,该动物的name为" + name);
    }
    public Animal(String name, int age) {
    
    
        this(name);
        System.out.println("Animal带两个参数的构造器,其age为" + age);
	}
}
public class Dog extends Animal {
    
    
    public Dog() {
    
    
        super("汪汪队阿奇", 3);
        System.out.println("Dog无参数的构造器");
    }
    public static void main(String[] args) {
    
    
        new Dog();
	}
}

5.5 Feature Three: Polymorphism

There are a thousand Hamlets in the eyes of a thousand readers.

5.5.1 Form and embodiment of polymorphism

object polymorphism

Polymorphism is the most important concept in object-oriented, embodied in Java: polymorphism of objects: the reference of the parent class points to the object of the subclass

Format: (parent class type: refers to the parent class type inherited by the subclass, or the interface type implemented)

父类类型 变量名 = 子类对象;

Example:

Person p = new Student();

Object o = new Person();//Object类型的变量o,指向Person类型的对象

o = new Student(); //Object类型的变量o,指向Student类型的对象

Object polymorphism: In Java, an object of a subclass can be used instead of an object of the parent class. Therefore, a reference type variable may point to (reference) many different types of objects

polymorphic understanding

Java reference variables have two types: 编译时类型and 运行时类型. The compile-time type 声明is determined by the type used by the variable, and the runtime type is 实际赋给该变量的对象determined by the variable. Abbreviation: When compiling, look to the left; when running, look to the right.

  • If the compile-time type is inconsistent with the runtime type, there will be polymorphism of the object (Polymorphism)
  • In the case of polymorphism, "look at the left": look at the reference of the parent class (the parent class does not have the method specific to the subclass) "look at the
    right": look at the object of the subclass (actually run is the rewriting of the subclass method of the parent class)

Prerequisites for polymorphism: ① class inheritance relationship ② method rewriting

example

public class Pet {
    
    
    private String nickname; //昵称

    public String getNickname() {
    
    
        return nickname;
    }

    public void setNickname(String nickname) {
    
    
        this.nickname = nickname;
    }

    public void eat(){
    
    
        System.out.println(nickname + "吃东西");
    }
}
public class Cat extends Pet {
    
    
    //子类重写父类的方法
    @Override
    public void eat() {
    
    
        System.out.println("猫咪" + getNickname() + "吃鱼仔");
    }

    //子类扩展的方法
    public void catchMouse() {
    
    
        System.out.println("抓老鼠");
    }
}
public class Dog extends Pet {
    
    
    //子类重写父类的方法
    @Override
    public void eat() {
    
    
        System.out.println("狗子" + getNickname() + "啃骨头");
    }

    //子类扩展的方法
    public void watchHouse() {
    
    
        System.out.println("看家");
    }
}

1. The assignment of local variables in the method reflects polymorphism

public class TestPet {
    
    
    public static void main(String[] args) {
    
    
        //多态引用
        Pet pet = new Dog();
        pet.setNickname("小白");

        //多态的表现形式
        /*
        编译时看父类:只能调用父类声明的方法,不能调用子类扩展的方法;
        运行时,看“子类”,如果子类重写了方法,一定是执行子类重写的方法体;
         */
        pet.eat();//运行时执行子类Dog重写的方法
//      pet.watchHouse();//不能调用Dog子类扩展的方法

        pet = new Cat();
        pet.setNickname("雪球");
        pet.eat();//运行时执行子类Cat重写的方法
    }
}

2. The formal parameter declaration of the method reflects polymorphism

public class Person{
    
    
    private Pet pet;
    public void adopt(Pet pet) {
    
    //形参是父类类型,实参是子类对象
        this.pet = pet;
    }
    public void feed(){
    
    
        pet.eat();//pet实际引用的对象类型不同,执行的eat方法也不同
    }
}
public class TestPerson {
    
    
    public static void main(String[] args) {
    
    
        Person person = new Person();

        Dog dog = new Dog();
        dog.setNickname("小白");
        person.adopt(dog);//实参是dog子类对象,形参是父类Pet类型
        person.feed();

        Cat cat = new Cat();
        cat.setNickname("雪球");
        person.adopt(cat);//实参是cat子类对象,形参是父类Pet类型
        person.feed();
    }
}

3. Method return value type reflects polymorphism

public class PetShop {
    
    
    //返回值类型是父类类型,实际返回的是子类对象
    public Pet sale(String type){
    
    
        switch (type){
    
    
            case "Dog":
                return new Dog();
            case "Cat":
                return new Cat();
        }
        return null;
    }
}
public class TestPetShop {
    
    
    public static void main(String[] args) {
    
    
        PetShop shop = new PetShop();

        Pet dog = shop.sale("Dog");
        dog.setNickname("小白");
        dog.eat();

        Pet cat = shop.sale("Cat");
        cat.setNickname("雪球");
        cat.eat();
    }
}

In development, sometimes when we design an array, or a member variable, or a method's formal parameter and return value type, we cannot determine its specific type, but can only determine that it is a certain series of types.

case:

(1) Declare a Dog class, including the public void eat() method, and output "dog gnaws bones"

(2) Declare a Cat class, including the public void eat() method, and output "the cat eats the fish"

(3) Declare a Person class with the following functions:

  • Contains pet properties
  • Contains the method of adopting a pet public void adopt (pet type Pet)
  • Contains the method public void feed() for feeding pets, implemented as calling the pet object.eat() method
public class Dog {
    
    
    public void eat(){
    
    
        System.out.println("狗啃骨头");
    }
}
public class Cat {
    
    
    public void eat(){
    
    
        System.out.println("猫吃鱼仔");
    }
}
public class Person {
    
    
    private Dog dog;

    //adopt:领养
    public void adopt(Dog dog){
    
    
        this.dog = dog;
    }

    //feed:喂食
    public void feed(){
    
    
        if(dog != null){
    
    
            dog.eat();
        }
    }
}

5.5.2 Advantages and Disadvantages of Polymorphism

Benefits : Different subclass objects referenced by variables have different execution methods, realizing dynamic binding. The code writing is more flexible, the function is more powerful, and the maintainability and scalability are better.

Disadvantages : If a reference type variable is declared as the type of the parent class, but actually refers to the subclass object, then the variable can no longer access the properties and methods added in the subclass.

Student m = new Student();
m.school = "pku"; 	//合法,Student类有school成员变量
Person e = new Student(); 
e.school = "pku";	//非法,Person类没有school成员变量

// 属性是在编译时确定的,编译时e为Person类型,没有school成员变量,因而编译错误。

In development:

Using the parent class as the formal parameter of the method is the most frequently used polymorphism occasion. Even if a new subclass is added, the method does not need to be changed, which improves the scalability and conforms to the principle of opening and closing.

【Opening and closing principle OCP】

  • Open for extension, closed for modification
  • Popular explanation: Various components in a software system, such as modules (Modules), classes (Classes), and functions (Functions), should introduce new functions without modifying existing codes.

5.5.3 Virtual Method Invocation

In Java, a virtual method refers to a method whose call entry address cannot be determined at the compilation stage, but can only be determined at the runtime stage, that is, a method that may be rewritten.

Person e = new Student();
e.getInfo();	//调用Student类的getInfo()方法

The method with the same name and the same parameters as the parent class is defined in the subclass. In the case of polymorphism, the method of the parent class at this time is called a virtual method. The parent class dynamically calls the methods belonging to the subclass according to the different subclass objects assigned to it. this method. Such method calls cannot be determined at compile time.

静态链接(或早起绑定): When a bytecode file is loaded into the JVM, if the called target method is known at compile time and remains unchanged at runtime. In this case, the process of converting the symbolic reference of the calling method into a direct reference is called static linking. Then calling such a method is called a non-virtual method call. For example, calling static methods, private methods, final methods, parent class constructors, and overloaded constructors of this class.

动态链接(或晚期绑定): If the called method cannot be determined during compilation, that is to say, the symbolic reference of the calling method can only be converted into a direct reference during program running. Since this reference conversion process is dynamic, it is also called It is a dynamic link. Calling such a method is called a virtual method call. For example, call the rewritten method (for the parent class), the implemented method (for the interface).

5.5.4 Member variables are not polymorphic

  • If the subclass rewrites the method of the parent class, it means that the method defined in the subclass completely covers the method of the same name in the parent class, and the system will not be able to transfer the method in the parent class to the subclass.

  • For instance variables, this phenomenon does not exist. Even if the instance variable that is exactly the same as the parent class is defined in the subclass, it is still impossible for this instance variable to override the instance variable defined in the parent class.

public class TestVariable {
    
    
    public static void main(String[] args) {
    
    
        Base b = new Sub();
        System.out.println(b.a);
        System.out.println(((Sub)b).a);

        Sub s = new Sub();
        System.out.println(s.a);
        System.out.println(((Base)s).a);
    }
}
class Base{
    
    
    int a = 1;
}
class Sub extends Base{
    
    
    int a = 2;
}

5.5.5 Upward Transformation and Downward Transformation

First of all, which type of object an object creates when it is new will not change from beginning to end. That is, the runtime type of this object, and the essential type is used to not change. However, when this object is assigned to variables of different types, the compile-time types of these variables are different.
Polymorphism, there must be a time when the subclass object is assigned to the parent class variable. At this time, there 编译期间will be a type conversion phenomenon.
However, after using the parent class variable to receive the subclass object, we 不能调用have methods that the subclass has but the parent class does not have. This is also a little "little trouble" that polymorphism brings us. Therefore, if you want to call a method unique to a subclass, you must do type conversion so that 编译通过.

  • Upcasting : When the type of the variable on the left (parent class) > the type of the object/variable on the right (subclass), we call it upcasting

    • At this time, when compiling according to the type of the variable on the left, you can only call the variables and methods in the parent class, and you cannot call the unique variables and methods of the subclass.
    • However, at runtime, it is still the type of the object itself , so the executed method is the method body rewritten by the subclass.
    • At this time, it must be safe, and it is also done automatically
  • Downcasting : When the type (subclass) of the variable on the left < the compile-time type (parent class) of the object/variable on the right, we call it downcasting

    • At this time, according to the type of the variable on the left when compiling, you can call the unique variables and methods of the subclass
    • However, at runtime, it is still the type of the object itself
    • Not all downward transformations through compilation are correct, and ClassCastException may occur. For safety, you can use the isInstanceof keyword to judge

Upward transformation: automatic completion

Downward transformation: (subclass type) parent class variable

public class ClassCastTest {
    
    
    public static void main(String[] args) {
    
    
        //没有类型转换
        Dog dog = new Dog();//dog的编译时类型和运行时类型都是Dog

        //向上转型
        Pet pet = new Dog();//pet的编译时类型是Pet,运行时类型是Dog
        pet.setNickname("小白");
        pet.eat();//可以调用父类Pet有声明的方法eat,但执行的是子类重写的eat方法体
//        pet.watchHouse();//不能调用父类没有的方法watchHouse

        Dog d = (Dog) pet;
        System.out.println("d.nickname = " + d.getNickname());
        d.eat();//可以调用eat方法
        d.watchHouse();//可以调用子类扩展的方法watchHouse

        Cat c = (Cat) pet;//编译通过,因为从语法检查来说,pet的编译时类型是Pet,Cat是Pet的子类,所以向下转型语法正确
        //这句代码运行报错ClassCastException,因为pet变量的运行时类型是Dog,Dog和Cat之间是没有继承关系的
    }
}

5.5.6 Keyword: instanceof

In order to avoid the occurrence of ClassCastException, Java provides instanceofthe keyword to check the type of reference variables. The code format is as follows:

//检验对象a是否是数据类型A的对象,返回值为boolean型
对象a instanceof 数据类型A 
  • illustrate:
    • As long as instanceof returns true, it must be safe to cast to this type, and ClassCastException will not be reported.
    • If object a belongs to subclass B of class A, the value of a instanceof A is also true.
    • It is required that the class to which object a belongs and class A must be in the relationship between a subclass and a parent class, otherwise a compilation error occurs.

code:

public class TestInstanceof {
    
    
    public static void main(String[] args) {
    
    
        Pet[] pets = new Pet[2];
        pets[0] = new Dog();//多态引用
        pets[0].setNickname("小白");
        pets[1] = new Cat();//多态引用
        pets[1].setNickname("雪球");

        for (int i = 0; i < pets.length; i++) {
    
    
            pets[i].eat();

            if(pets[i] instanceof Dog){
    
    
                Dog dog = (Dog) pets[i];
                dog.watchHouse();
            }else if(pets[i] instanceof Cat){
    
    
                Cat cat = (Cat) pets[i];
                cat.catchMouse();
            }
        }
    }
}

Practice: Written Test & Interview

Topic 1: The difference between inherited member variables and inherited methods

class Base {
    
    
    int count = 10;
    public void display() {
    
    
        System.out.println(this.count);
    }
}

class Sub extends Base {
    
    
    int count = 20;
    public void display() {
    
    
        System.out.println(this.count);
    }
}

public class FieldMethodTest {
    
    
    public static void main(String[] args){
    
    
        Sub s = new Sub();
        System.out.println(s.count);
        s.display();
        Base b = s;
        System.out.println(b == s);
        System.out.println(b.count);
        b.display();
    }
}

Topic 2:

//考查多态的笔试题目:
public class InterviewTest1 {
    
    

	public static void main(String[] args) {
    
    
		Base base = new Sub();
		base.add(1, 2, 3);

//		Sub s = (Sub)base;
//		s.add(1,2,3);
	}
}

class Base {
    
    
	public void add(int a, int... arr) {
    
    
		System.out.println("base");
	}
}

class Sub extends Base {
    
    

	public void add(int a, int[] arr) {
    
    
		System.out.println("sub_1");
	}

//	public void add(int a, int b, int c) {
    
    
//		System.out.println("sub_2");
//	}

}

Topic 3:

//getXxx()和setXxx()声明在哪个类中,内部操作的属性就是哪个类里的。
public class InterviewTest2 {
    
    
	public static void main(String[] args) {
    
    
		Father f = new Father();
		Son s = new Son();
		System.out.println(f.getInfo());//atguigu
		System.out.println(s.getInfo());//尚硅谷
		s.test();//尚硅谷  atguigu
		System.out.println("-----------------");
		s.setInfo("大硅谷");
		System.out.println(f.getInfo());//atguigu
		System.out.println(s.getInfo());//大硅谷
		s.test();//大硅谷  atguigu
	}
}

class Father {
    
    
	private String info = "atguigu";

	public void setInfo(String info) {
    
    
		this.info = info;
	}

	public String getInfo() {
    
    
		return info;
	}
}

class Son extends Father {
    
    
	private String info = "尚硅谷";
	
	public void setInfo(String info) {
    
    
		this.info = info;
	}

	public String getInfo() {
    
    
		return info;
	}
	
	public void test() {
    
    
		System.out.println(this.getInfo());
		System.out.println(super.getInfo());
	}
}

Question 4: Is polymorphism a compile-time behavior or a runtime behavior?

//证明如下:
class Animal  {
    
    
	protected void eat() {
    
    
		System.out.println("animal eat food");
	}
}

class Cat  extends Animal  {
    
    
	protected void eat() {
    
    
		System.out.println("cat eat fish");
	}
}

class Dog  extends Animal  {
    
    
	public void eat() {
    
    
		System.out.println("Dog eat bone");
	}
}

class Sheep  extends Animal  {
    
    
	public void eat() {
    
    
		System.out.println("Sheep eat grass");
	}
}

public class InterviewTest {
    
    
	public static Animal  getInstance(int key) {
    
    
		switch (key) {
    
    
		case 0:
			return new Cat ();
		case 1:
			return new Dog ();
		default:
			return new Sheep ();
		}

	}

	public static void main(String[] args) {
    
    
		int key = new Random().nextInt(3);
		System.out.println(key);

		Animal  animal = getInstance(key);
		animal.eat(); 
	}
}

5.6 Use of the Object class

A class java.lang.Objectis the root class of the class hierarchy, the parent class of all other classes. Each class is used Objectas a superclass.

  • There are polymorphic references between variables of Object type and objects of any reference data type except Object

    method(Object obj){
          
          } //可以接收任何类作为其参数
    
    Person o = new Person();  
    method(o);
    
    
  • All objects (including arrays) implement the methods of this class.

  • If a class does not specify a parent class, it inherits from the Object class by default. For example:

    public class Person {
          
          
    	...
    }
    //等价于:
    public class Person extends Object {
          
          
    	...
    }
    

5.6.1 Methods of the Object class

According to the JDK source code and the API documentation of the Object class, there are 11 methods contained in the Object class. Here we mainly focus on 6 of them:

1. (Key) equals()

= =:

  • Primitive types compare values: true whenever the values ​​of two variables are equal.

    int a=5; 
    if(a==6){
          
          }
    
  • Reference types compare references (whether they point to the same object): == returns true only when they point to the same object.

    Person p1=new Person();  	    
    Person p2=new Person();
    if (p1==p2){
          
          }
    
    • When using "==" for comparison, on both sides of the symbol 数据类型必须兼容(except for the basic data types that can be automatically converted), otherwise the compilation error

**equals():**All classes inherit Object, so they get the equals() method. Can also be overridden.

  • Only reference types can be compared. The function of equals() in the Object class source code is the same as "==": to compare whether they point to the same object.

    image-20220503104750655
  • Format: obj1.equals(obj2)

  • Special case: When using the equals() method for comparison, for classes File, String, Date and wrapper classes (Wrapper Class), the type and content are compared regardless of whether the references are the same object;

    • Reason: The equals() method of the Object class is overridden in these classes.
  • When customizing equals(), it can be overridden. Used to compare whether the "contents" of two objects are equal

  • The principle of overriding the equals() method

    • 对称性: If x.equals(y) returns "true", then y.equals(x) should also return "true".

    • 自反性: x.equals(x) must return "true".

    • 传递性: If x.equals(y) returns "true" and y.equals(z) returns "true", then z.equals(x) should also return "true".

    • 一致性: If x.equals(y) returns "true", as long as the contents of x and y remain unchanged, no matter how many times you repeat x.equals(y), the return is "true".

    • In any case, x.equals(null) always returns "false";

      x.equals (an object of a different type than x) always returns "false".

  • Rewrite example:

class User{
    
    
	private String host;
	private String username;
	private String password;
	public User(String host, String username, String password) {
    
    
		super();
		this.host = host;
		this.username = username;
		this.password = password;
	}
	public User() {
    
    
		super();
	}
	public String getHost() {
    
    
		return host;
	}
	public void setHost(String host) {
    
    
		this.host = host;
	}
	public String getUsername() {
    
    
		return username;
	}
	public void setUsername(String username) {
    
    
		this.username = username;
	}
	public String getPassword() {
    
    
		return password;
	}
	public void setPassword(String password) {
    
    
		this.password = password;
	}
	@Override
	public String toString() {
    
    
		return "User [host=" + host + ", username=" + username + ", password=" + password + "]";
	}
	@Override
	public boolean equals(Object obj) {
    
    
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		User other = (User) obj;
		if (host == null) {
    
    
			if (other.host != null)
				return false;
		} else if (!host.equals(other.host))
			return false;
		if (password == null) {
    
    
			if (other.password != null)
				return false;
		} else if (!password.equals(other.password))
			return false;
		if (username == null) {
    
    
			if (other.username != null)
				return false;
		} else if (!username.equals(other.username))
			return false;
		return true;
	}
	
}

Interview question: The difference between == and equals

  • == can compare both primitive types and reference types. For basic types, it is to compare values, and for reference types, it is to compare memory addresses

  • For equals, it belongs to the method in the java.lang.Object class. If the method has not been overridden, it is also == by default; we can see that the equals method of String and other classes has been overridden, and the String class is in It is used a lot in daily development, and over time, the erroneous view that equals is a comparative value has been formed.

  • Specifically, it depends on whether the equals method of Object is rewritten in the custom class to judge.

  • Normally, overriding the equals method will compare whether the corresponding properties in the class are equal.

Exercise 1:

int it = 65;
float fl = 65.0f;
System.out.println("65和65.0f是否相等?" + (it == fl)); // 输出 false
//65 和 65.0f 不相等,因为它们虽然值相同,但数据类型不同

char ch1 = 'A'; char ch2 = 12;
System.out.println("65和'A'是否相等?" + (it == ch1)); // 输出 true
//65 和 'A' 相等,因为在 char 类型中,A 的 Unicode 码值是 65,也就是说 ch1 的值是 65
System.out.println("12和ch2是否相等?" + (12 == ch2)); // 输出 true
//12 和 ch2 相等,因为它们的值相同,都是 12

String str1 = new String("hello");
String str2 = new String("hello");
System.out.println("str1和str2是否相等?" + (str1 == str2)); // 输出 false
//str1 和 str2 不相等,因为它们虽然存储的字符串相同,但是是两个不同的对象,比较的是两者在内存中的引用地址

System.out.println("str1是否equals str2?" + (str1.equals(str2))); // 输出 true
//str1.equals(str2) 返回 true,说明两个对象存储的字符串相等
System.out.println("hello" == new java.util.Date()); // 抛出编译错误,因为无法比较两个不同类型的对象

Exercise 2:

Write the Order class, which has int-type orderId, String-type orderName, corresponding getter() and setter() methods, a constructor with two parameters, and overrides the equals() method of the parent class: public boolean equals(Object obj) , and judge whether the two objects created in the test class are equal.

public class Order {
    
    
    private int orderId; // 订单编号
    private String orderName; // 订单名称

    /**
     * 两个参数的构造器
     * @param orderId 订单编号
     * @param orderName 订单名称
     */
    public Order(int orderId, String orderName) {
    
    
        this.orderId = orderId;
        this.orderName = orderName;
    }

    /**
     * 获取订单编号
     * @return 订单编号
     */
    public int getOrderId() {
    
    
        return orderId;
    }

    /**
     * 设置订单编号
     * @param orderId 订单编号
     */
    public void setOrderId(int orderId) {
    
    
        this.orderId = orderId;
    }

    /**
     * 获取订单名称
     * @return 订单名称
     */
    public String getOrderName() {
    
    
        return orderName;
    }

    /**
     * 设置订单名称
     * @param orderName 订单名称
     */
    public void setOrderName(String orderName) {
    
    
        this.orderName = orderName;
    }

    /**
     * 重写 equals 方法,判断两个对象是否相等
     * @param obj 待比较对象
     * @return true(相等)/false(不相等)
     */
    @Override
    public boolean equals(Object obj) {
    
    
        if (this == obj) //判断是否为同一个对象
            return true;
        if (obj instanceof Order) {
    
     //判断是否为同一类型
            Order order = (Order) obj;
            return this.orderId == order.orderId && this.orderName.equals(order.orderName); // 判断两个对象的 orderId 和 orderName 是否相等
        }
        return false;
    }

    public static void main(String[] args) {
    
    
        Order order1 = new Order(1, "order1"); // 创建 Order 对象 1
        Order order2 = new Order(2, "order2"); // 创建 Order 对象 2
        Order order3 = new Order(1, "order1"); // 创建 Order 对象 3
        System.out.println(order1.equals(order2)); // 判断 Order 对象 1 和 2 是否相等
        // 结果:false
        System.out.println(order1.equals(order3)); // 判断 Order 对象 1 和 3 是否相等
        // 结果:true
    }
}

2. (emphasis) toString()

Method signature: public String toString()

① By default, toString() returns "the hexadecimal form of the object's runtime type@object's hashCode value"

② When connecting String and other types of data, the toString() method is automatically called

Date now=new Date();
System.out.println(“now=+now);  //相当于
System.out.println(“now=+now.toString()); 

③ If we directly System.out.println (object), it will automatically call toString() of this object by default

Because the memory address of the object is actually stored in the variable of the reference data type of Java, but Java hides the memory address information from the programmer, so the memory address cannot be displayed directly, so when you print the object, the JVM calls it for you object's toString().

④ The toString() method can be rewritten in the user-defined type as required.
For example, the String class rewrites the toString() method to return the value of the string.

s1="hello";
System.out.println(s1);//相当于System.out.println(s1.toString());

For example a custom Person class:

public class Person {
    
      
    private String name;
    private int age;

    @Override
    public String toString() {
    
    
        return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
    }
}

3、clone()

//Object类的clone()的使用
public class CloneTest {
    
    
	public static void main(String[] args) {
    
    
		Animal a1 = new Animal("花花");
		try {
    
    
			Animal a2 = (Animal) a1.clone();
			System.out.println("原始对象:" + a1);
			a2.setName("毛毛");
			System.out.println("clone之后的对象:" + a2);
		} catch (CloneNotSupportedException e) {
    
    
			e.printStackTrace();
		}
	}
}

class Animal implements Cloneable{
    
    
	private String name;

	public Animal() {
    
    
		super();
	}

	public Animal(String name) {
    
    
		super();
		this.name = name;
	}

	public String getName() {
    
    
		return name;
	}

	public void setName(String name) {
    
    
		this.name = name;
	}

	@Override
	public String toString() {
    
    
		return "Animal [name=" + name + "]";
	}
	
	@Override
	protected Object clone() throws CloneNotSupportedException {
    
    
		// TODO Auto-generated method stub
		return super.clone();
	}
	
}

4、finalize()

  • When an object is recycled, the system automatically calls the object's finalize() method. (not called by the garbage collector, but called by the object of this class)
    • The finalize method of an object should always 不要主动调用be called by the garbage collection mechanism.
  • When is it recycled: When an object does not have any references, the JVM considers the object to be a garbage object, and will use the garbage collection mechanism to destroy the object at an indeterminate time later. Before destroying the object, it will call finalize ()method.
  • Subclasses can override this method in order to perform necessary cleanup operations before the object is cleaned up. For example, disconnect related connection resources within the method.
    • If this method is overridden so that a new reference variable re-references the object, the object will be reactivated.
  • This method has been deprecated in JDK 9 标记为过时.
public class FinalizeTest {
    
    
	public static void main(String[] args) {
    
    
		Person p = new Person("Peter", 12);
		System.out.println(p);
		p = null;//此时对象实体就是垃圾对象,等待被回收。但时间不确定。
		System.gc();//强制性释放空间
	}
}

class Person{
    
    
	private String name;
	private int age;

	public Person(String name, int age) {
    
    
		super();
		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;
	}
	//子类重写此方法,可在释放对象前进行某些操作
	@Override
	protected void finalize() throws Throwable {
    
    
		System.out.println("对象被释放--->" + this);
	}
	@Override
	public String toString() {
    
    
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
}

5、getClass()

public final Class<?> getClass(): Get the runtime type of the object

Because Java has polymorphism, the compile-time type of a variable that refers to a data type may not be consistent with the runtime type, so if you need to check the type of the object that the variable actually points to, you need to use the getClass() method

public static void main(String[] args) {
    
    
	Object obj = new Person();
	System.out.println(obj.getClass());//运行时类型
}

result:

class com.atguigu.java.Person

6、hashCode()

public int hashCode(): returns the hash value of each object. (Follow-up will focus on the collection framework chapter)

public static void main(String[] args) {
    
    
	System.out.println("AA".hashCode());//2080
    System.out.println("BB".hashCode());//2112
}

5.6.2 Keyword: native

Use the native keyword to indicate that this method is a native function, that is, this method is implemented in a C/C++non-Java language, and 被编译成了DLLis called by Java.

  • Native methods have method bodies and are written in C language. Since the source code of the method body of the local method is not open source to us, we cannot see the method body

  • When defining a native method in Java, an implementation body is not provided.

1. Why use the native method

Java is very convenient to use, but it is not easy to implement some tasks in Java, or when we care about the efficiency of the program, for example: Java needs to exchange information with some underlying operating systems or some hardware. The native method is just such a communication mechanism: it provides us with a very concise interface, and we don't need to understand the cumbersome details outside of the Java application.

2. The method declared by native can be used as the same as other Java methods for the caller

The existence of native methods does not have any impact on other classes calling these native methods. In fact, other classes calling these methods don't even know that it is calling a native method. The JVM will control all the details of calling native methods.

Guess you like

Origin blog.csdn.net/weixin_52357829/article/details/129909882