Quick Start with Java—[Java Object-Oriented]—10

Inheritance, initialization

Today's content

  • Three major features - inheritance (key points)
  • Method rewriting (emphasis)
  • super keyword (emphasis)
  • final modifier (emphasis)
  • Class initialization (difficult)
  • Instance initialization (difficult)

learning target

  • Ability to write inheritance formats for classes
  • Be able to describe the characteristics of inheritance
  • Be able to tell the characteristics of members of the subclass that call the parent class
  • Be able to explain the concept of method overriding
  • Be able to name problems that super can solve
  • Master the use of final
  • Ability to analyze class initialization process
  • Ability to analyze the instance initialization process

Chapter 6 Object-Oriented Basics – Part 2 (continued)

6.7 Inheritance

6.7.1 Overview of inheritance

Understanding inheritance

  • Inheritance : The subclass inherits the attributes and behaviors of the parent class , so that the subclass object has the same attributes and behaviors as the parent class.

Benefits of inheritance

  • Improve code reusability .

  • Improve code scalability .

  • The relationship between classes is the prerequisite for learning polymorphism .

6.7.2 Inherited formats

Through extendsthe keyword, you can declare that a subclass inherits another parent class. The definition format is as follows:

【修饰符】 class 父类 {
    
    
	...
}

【修饰符】 class 子类 extends 父类 {
    
    
	...
}

Inheritance demonstration, the code is as follows:

/*
 * 定义动物类Animal,做为父类
 */
class Animal {
    
    
    // 定义name属性
	public String name; 
    // 定义age属性
    public int age;
	// 定义动物的吃东西方法
	public void eat() {
    
    
		System.out.println(age + "岁的" + name + "在吃东西");
	}
}

/*
 * 定义猫类Cat 继承 动物类Animal
 */
class Cat extends Animal {
    
    
	// 定义一个猫抓老鼠的方法catchMouse
	public void catchMouse() {
    
    
		System.out.println("抓老鼠");
	}
}

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

演示结果:
抓老鼠
2岁的Tom在吃东西

6.7.3 Feature 1 of inheritance: member variables

private

  • Members in the parent class, whether public or private, will be inherited by the subclass.
  • Although the subclass will inherit the private members of the parent class, the subclass cannot directly access the inherited private members and can access them through the inherited public methods. as the picture shows:

Insert image description here

code show as below:

/*
 * 定义动物类Animal,做为父类
 */
class Animal {
    
    
    // 定义name属性
	private String name; 
    // 定义age属性
    public int age;
	// 定义动物的吃东西方法
	public void eat() {
    
    
		System.out.println(age + "岁的" + name + "在吃东西");
	}
}
/*
 * 定义猫类Cat 继承 动物类Animal
 */
class Cat extends Animal {
    
    
	// 定义一个猫抓老鼠的方法catchMouse
	public void catchMouse() {
    
    
		System.out.println("抓老鼠");
	}
}

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

as the picture shows:

Insert image description here

Member variables do not have the same name

If there are member variables with different names in the subclass and parent class , the access at this time has no effect . code show as below:

class Fu {
    
    
	// Fu中的成员变量。
	int num01 = 3;
}

class Zi extends Fu {
    
    
	// Zi中的成员变量
	int num02 = 4;
	// Zi中的成员方法
	public void show() {
    
    
		// 访问父类中的num,
		System.out.println("num1 = " + num1); 
		// 访问子类中的num2
		System.out.println("num2 = " + num2);
	}
}

class ExtendDemo02 {
    
    
	public static void main(String[] args) {
    
    
        // 创建子类对象
		Zi z = new Zi(); 
      	// 调用子类中的show方法
		z.show();  
	}
}

演示结果:
num1 = 3
num2 = 4

Member variable has the same name

If a member variable with the same name appears in the subclass or parent class , the access at this time will be affected . code show as below:

class Fu {
    
    
	// Fu中的成员变量。
	int num = 3;
}

class Zi extends Fu {
    
    
	// Zi中的成员变量
	int num = 4;
	public void show() {
    
    
		// 访问的num到底是子类还是父类?
		System.out.println("num = " + num);

	}
}
class ExtendsDemo03 {
    
    
	public static void main(String[] args) {
    
    
      	// 创建子类对象
		Zi z = new Zi(); 
      	// 调用子类中的show方法
		z.show(); 
	}
}
演示结果:
num = 4

When a member variable with the same name appears in a subclass and the subclass needs to access non-private member variables in the parent class, it is necessary to use the superkeyword to modify the parent class member variable, similar to what we have learned before this.

Use format:

super.父类成员变量名

The subclass method needs to be modified, the code is as follows:

class Zi extends Fu {
    
    
	// Zi中的成员变量
	int num = 6;
	public void show() {
    
    
		//访问父类中的num
		System.out.println("Fu num=" + super.num);
		//访问子类中的num
		System.out.println("Zi num=" + this.num);
	}
}
演示结果:
Fu num = 5
Zi num = 6

Tips: Member variables in the Fu class are non-private and can be accessed directly from subclasses. If the member variables in the Fu class are private, subclasses cannot directly access them. Usually when coding, we follow the principle of encapsulation and use private to modify member variables. So how to access the private member variables of the parent class? right! Public getXxx methods and setXxx methods can be provided in the parent class.

Exercise: Code Analysis

class Father{
    
    
	int a = 10;
	int b = 11;
}
class Son extends Father{
    
    
	int a = 20;
	
	public void test(){
    
    
		//子类与父类的属性同名,子类对象中就有两个a
		System.out.println("父类的a:" + super.a);//10
		System.out.println("子类的a:" + this.a);//20
		System.out.println("子类的a:" + a);//20
		
		//子类与父类的属性不同名,是同一个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){
    
    
		//子类与父类的属性同名,子类对象中就有两个成员变量a,此时方法中还有一个局部变量a
		System.out.println("父类的a:" + super.a);//10
		System.out.println("子类的a:" + this.a);//20
		System.out.println("局部变量的a:" + a);//30
	}
}
public class TestInherite2 {
    
    
	public static void main(String[] args) {
    
    
		Son son = new Son();
		System.out.println(son.a);//20
		
		son.test();
		
		son.method(30);
	}
}

6.7.4 Characteristic 2 of inheritance: member methods

When there is a relationship between classes, what impact do the member methods in each class have?

Member methods do not have duplicate names

If a member method with the same name appears in the subclass's parent class , the call at this time will have no effect . When an object calls a method, it will first search for a corresponding method in the subclass. If it exists in the subclass, the method in the subclass will be executed. If it does not exist in the subclass, the corresponding method in the parent class will be executed. code show as below:

class Fu{
    
    
	public void show(){
    
    
		System.out.println("Fu类中的show方法执行");
	}
}
class Zi extends Fu{
    
    
	public void show2(){
    
    
		System.out.println("Zi类中的show2方法执行");
	}
}
public  class ExtendsDemo04{
    
    
	public static void main(String[] args) {
    
    
		Zi z = new Zi();
     	//子类中没有show方法,但是可以找到父类方法去执行
		z.show(); 
		z.show2();
	}
}

Member method has the same name - Override

If a member method with the same name appears in a subclass or parent class , the access at this time is a special case called method override.

code show as below:

class Fu {
    
    
	public void show() {
    
    
		System.out.println("Fu show");
	}
}
class Zi extends Fu {
    
    
	//子类重写了父类的show方法
	public void show() {
    
    
		System.out.println("Zi show");
	}
}
public class ExtendsDemo05{
    
    
	public static void main(String[] args) {
    
    
		Zi z = new Zi();
     	// 子类中有show方法,只执行重写后的show方法
		z.show();  // Zi show
	}
}
在父子类的继承关系当中,创建子类对象,访问成员方法的规则:
    创建的对象是谁,就优先用谁,如果没有则向上找。

注意事项:
无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类的。

重写(Override)
概念:在继承关系当中,方法的名称一样,参数列表也一样。

重写(Override):方法的名称一样,参数列表【也一样】。覆盖、覆写。
重载(Overload):方法的名称一样,参数列表【不一样】。

方法的覆盖重写特点:创建的是子类对象,则优先用子类方法。

方法覆盖重写的注意事项:见下面

rewritten application

Subclasses can define their own behavior as needed. It not only inherits the function names of the parent class, but also reimplements the parent class methods according to the needs of the subclass, thereby extending and enhancing it. For example, new mobile phones add the function of caller ID avatar, the code is as follows:

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

//智能手机类
class NewPhone extends Phone {
    
    
	
	//重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能
	public void showNum(){
    
    
		//调用父类已经存在的功能使用super
		super.showNum();
		//增加自己特有显示姓名和图片功能
		System.out.println("显示来电姓名");
		System.out.println("显示头像");
	}
}

public class ExtendsDemo06 {
    
    
	public static void main(String[] args) {
    
    
      	// 创建子类对象
      	NewPhone np = new NewPhone()
        
        // 调用父类继承而来的方法
        np.call();
      
      	// 调用子类重写的方法
      	np.showNum();

	}
}

Tips: When rewriting here, use super. Parent class member method, which means calling the member method of the parent class.

Precautions

  1. It must be ensured that the name of the method between the parent and child classes is the same, and the parameter list is also the same.
    @Override: written in front of the method to detect whether the override is valid and correct.
    Even if this annotation is not written, as long as it meets the requirements, it is the correct way to overwrite and rewrite it.

  2. The return value type of the subclass method must be [less than or equal to] the return value type of the parent class method (less than is actually its subclass).
    Small extension tip: The java.lang.Object class is the common highest parent class (ancestor class) of all classes, and java.lang.String is a subclass of Object.

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

  3. The permissions of the subclass method must be [greater than or equal to] the permission modifier of the parent class method.
    Small extension tip: public > protected > default > private
    Note: The default is not the Chinese character default, but nothing is written and left blank.

  4. Several special methods cannot be overridden

    • Static methods cannot be overridden
    • Private methods that are not visible in subclasses cannot be overridden
    • final methods cannot be overridden

practise

1. Declare the parent class: Person class
, including attributes: name, age, gender.
The attributes are privatized, and get/set
includes the getInfo() method: For example: Name: Zhang San, age: 23, gender: male

2. Declare the subclass: Student class, inherit the Person class,
add new attributes: score,
attribute privatization, get/set
includes getInfo() method: For example: Name: Zhang San, age: 23, gender: male, score: 89

3. Declare the subclass: Teacher class, inherit the Person class,
add new attributes: salary,
attribute privatization, get/set
includes getInfo() method: For example: Name: Zhang San, age: 23, gender: male, salary: 10000

public class Person {
    
    
	private String name;
	private int age;
	private char gender;
	public Person(String name, int age, char gender) {
    
    
		super();
		this.name = name;
		this.age = age;
		this.gender = gender;
	}
	public Person() {
    
    
		super();
	}
	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 char getGender() {
    
    
		return gender;
	}
	public void setGender(char gender) {
    
    
		this.gender = gender;
	}
	
	//包含getInfo()方法:例如:姓名:张三,年龄:23,性别:男
	public String getInfo(){
    
    
		return "姓名:" + name + ",年龄:" + age +",性别:" + gender;
	}
}
public class Student extends Person {
    
    
	private int score;

	public Student() {
    
    
	}

	public Student(String name, int age, char gender, int score) {
    
    
		setName(name);
		setAge(age);
		setGender(gender);
		this.score = score;
	}

	public int getScore() {
    
    
		return score;
	}

	public void setScore(int score) {
    
    
		this.score = score;
	}
	//包含getInfo()方法:例如:姓名:张三,年龄:23,性别:男,成绩:89
	public String getInfo(){
    
    
		//方式一:
//		return "姓名:" + getName() + ",年龄:" + getAge() + ",成绩:" + score;
		
		//方法二:
		return super.getInfo() + ",成绩:" + score;
	}
	
}
public class Teacher extends Person {
    
    
	private double salary;

	public Teacher() {
    
    
	}

	public Teacher(String name, int age, char gender, double salary) {
    
    
		setName(name);
		setAge(age);
		setGender(gender);
		this.salary = salary;
	}

	public double getSalary() {
    
    
		return salary;
	}

	public void setSalary(double salary) {
    
    
		this.salary = salary;
	}
	
	//包含getInfo()方法:例如:姓名:张三,年龄:23,性别:男,薪资:10000
	public String getInfo(){
    
    
		return super.getInfo() + ",薪资:" + salary;
	}
}

public class TestPersonExer2 {
    
    
	public static void main(String[] args) {
    
    
		Person p = new Person("张三", 23, '男');
		System.out.println(p.getInfo());
		
		Student s = new Student("陈琦", 25, '男', 89);
		System.out.println(s.getInfo());
		
		Teacher t = new Teacher("柴林燕", 18, '女', 11111);
		System.out.println(t.getInfo());
	}
}

6.7.5 Characteristic 3 of inheritance: construction method

When there is a relationship between classes, what impact do the construction methods in each class have?

First we have to recall two things, the definition format and function of the constructor method.

  1. The name of the constructor method is consistent with the class name. Therefore, subclasses cannot inherit the construction methods of parent classes.
  2. The function of the constructor is to initialize member variables. Therefore, during the initialization process of the subclass, the initialization action of the parent class must be performed first. There is one constructor in the subclass by default super(), which means calling the constructor of the parent class. Only after the parent class member variables are initialized can they be used by the subclass. code show as below:
class Fu {
    
    
  private int n;
  Fu(){
    
    
    System.out.println("Fu()");
  }
}
class Zi extends Fu {
    
    
  Zi(){
    
    
    // super(),调用父类构造方法
    super();
    System.out.println("Zi()");
  } 
}
public class ExtendsDemo07{
    
    
  public static void main (String args[]){
    
    
    Zi zi = new Zi();
  }
}
输出结果:
Fu()
Zi()

What if the parent class does not have a no-argument constructor?

For example:

public class Person {
    
    
	private String name;
	private int age;
	public Person(String name, int age) {
    
    
		super();
		this.name = name;
		this.age = age;
	}
	//其他成员方法省略
}
public class Student extends Person{
    
    
	private int score;
}

At this time, the subclass code reports an error.

Solution: In the subclass constructor, use super (actual parameter list) to explicitly call the parameterized constructor of the parent class.

public class Student extends Person{
    
    
	private int score;

	public Student(String name, int age) {
    
    
		super(name, age);
	}
	public Student(String name, int age, int score) {
    
    
		super(name, age);
		this.score = score;
	}
	
	//其他成员方法省略
}

practise

1. The parent class Graphic
contains attributes: name (graph name), which is privatized. It does not provide no-parameter construction, but only provides parameter-based construction. It includes the
area getArea(): returns 0.0
and the perimeter getPerimeter() method: returns 0.0
for display. Information getInfo() method: returns the shape name, area, and perimeter

2. The subclass Circle inherits the Graphic graphic
and includes attributes: radius
overrides the getArea() and getPerimeter() methods for area and perimeter, and displays information getInfo() plus radius information.

3. The subclass Rectange inherits the Graphic graphic
and includes attributes: length, width,
overrides the getArea() and perimeter getPerimeter() methods, and displays the getInfo() plus length and width information.

public class Graphic {
    
    
	private String name;

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

	public String getName() {
    
    
		return name;
	}

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

	// 包含求面积getArea()和求周长getPerimeter()方法,显示信息getInfo()
	public double getArea() {
    
    
		return 0.0;
	}

	public double getPerimeter() {
    
    
		return 0.0;
	}

	/*
	 * this对象:调用当前方法的对象,如果是Graphic对象,那么就会执行Graphic的getArea()和getPerimeter()
	 * this对象:调用当前方法的对象,如果是Circle对象,那么就会执行Circle的getArea()和getPerimeter()
	 * this对象:调用当前方法的对象,如果是Rectangle对象,那么就会执行Rectangle的getArea()和getPerimeter()
	 */
	public String getInfo() {
    
    
		return "图形:" + name + ",面积:" + getArea() + ",周长:" + getPerimeter();
	}
}
public class Circle extends Graphic {
    
    
	private double radius;

	public Circle(String name, double radius) {
    
    
		super(name);
		this.radius = radius;
	}

	public double getRadius() {
    
    
		return radius;
	}

	public void setRadius(double radius) {
    
    
		this.radius = radius;
	}

	@Override//表示这个方法是重写的方法
	public double getArea() {
    
    
		return Math.PI * radius * radius;
	}

	@Override//表示这个方法是重写的方法
	public double getPerimeter() {
    
    
		return Math.PI * radius * 2;
	}

	/*@Override//表示这个方法是重写的方法
	public String getInfo() {
		return super.getInfo() + ",半径:" + radius;
	}*/
	
}

public class Rectangle extends Graphic {
    
    
	private double length;
	private double width;
	
	public Rectangle(String name, double length, double width) {
    
    
		super(name);
		this.length = length;
		this.width = width;
	}

	public double getLength() {
    
    
		return length;
	}

	public void setLength(double length) {
    
    
		this.length = length;
	}

	public double getWidth() {
    
    
		return width;
	}

	public void setWidth(double width) {
    
    
		this.width = width;
	}

	@Override
	public double getArea() {
    
    
		return length*width;
	}

	@Override
	public double getPerimeter() {
    
    
		return 2*(length + width);
	}
	
}

public class TestGraphicExer3 {
    
    
	public static void main(String[] args) {
    
    
		Graphic g = new Graphic("通用图形");
		System.out.println(g.getInfo());
		
		Circle c = new Circle("圆", 1.2);
		System.out.println(c.getInfo());//调用getInfo()方法的对象是c
		
		Rectangle r = new Rectangle("矩形", 3, 5);
		System.out.println(r.getInfo());
	}
}

6.7.6 Characteristic 4 of Inheritance: Single Inheritance Limitation

  1. Java only supports single inheritance and does not support multiple inheritance.
//一个类只能有一个父类,不可以有多个父类。
class C extends A{
    
    } 	//ok
class C extends AB...	//error
  1. Java supports multi-level inheritance (inheritance system).
class A{
    
    }
class B extends A{
    
    }
class C extends B{
    
    }

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

  1. Subclass and parent class are relative concepts.
  2. A parent class can have multiple subclasses at the same time

6.8 super

The parent class space takes precedence over subclass objects.

Each time a subclass object is created, the parent class space is initialized first, and then the subclass object itself is created. The purpose is that if the subclass object contains its corresponding parent class space, it can contain the members of its parent class. If the parent class members are not privately modified, the subclass can use the parent class members at will. The code is reflected in the fact that when the constructor of a subclass is called, the constructor of the parent class must be called first.

public class Person {
    
    
	private String name;
	private int age;
	//其他代码省略
}
public class Student extends Person{
    
    
	private int score;
	//其他成员方法省略
}
public class Test{
    
    
    public static void main(String[] args){
    
    
    	Student stu = new Student();
    }
}

Insert image description here

The meaning of super and this

  • super : represents the storage space identifier of the parent class (can be understood as a reference to the father).

    • When looking for member variables and member methods through super, find them directly from the parent class space (inherited from the parent class including the parent class).
    • super() or super (actual parameter list) can only be found from the direct parent class
    • Through super, you can only access the parent class that is visible in the subclass (non-private, cross-package cannot be the default)
  • this : represents a reference to the current object .

    • When looking for member variables and member methods through this, first look for them in the current class. If they are not found, they will go up to the parent class.
    • But this() or this(actual parameter list) will only be found in this class

Note: Neither super nor this can appear in static methods or static code blocks, because both super and this exist in objects .

How to use super

1. super.member variable

Access the member variables of the parent class space in the child class object, that is, access the member variables inherited from the parent class that are still visible in the child class.

(1) The subclass does not have member variables with the same name as the parent class

public class Test{
    
    
    public static void main(String[] args){
    
    
    	Son s = new Son();
    	s.test();
    }
}
class Father{
    
    
	int a = 10;
}
class Son extends Father{
    
    
	public void test(){
    
    
		System.out.println(super.a);//10
		System.out.println(this.a);//10
		System.out.println(a);//10
	}
}

(2) The subclass has member variables with the same name as the parent class

public class Test{
    
    
    public static void main(String[] args){
    
    
    	Son s = new Son();
    	s.test();
    }
}
class Father{
    
    
	int a = 10;
}
class Son extends Father{
    
    
	int a = 20;
	public void test(){
    
    
		System.out.println(super.a);//10
		System.out.println(this.a);//20
		System.out.println(a);//20
	}
}

(3) The method has local variables and member variables with the same name

public class Test{
    
    
    public static void main(String[] args){
    
    
    	Son s = new Son();
    	s.test(30);
    }
}
class Father{
    
    
	int a = 10;
}
class Son extends Father{
    
    
	int a = 20;
	public void test(int a){
    
    
		System.out.println(super.a);//10
		System.out.println(this.a);//20
		System.out.println(a);//30
	}
}

2. super. member method

Access the member methods inherited from the parent class that are still visible in the subclass in the subclass object

(1) Subclasses have no overridden methods

public class Test{
    
    
    public static void main(String[] args){
    
    
    	Son s = new Son();
    	s.test();
    }
}
class Father{
    
    
	public void method(){
    
    
		System.out.println("aa");
	}
}
class Son extends Father{
    
    
	public void test(){
    
    
		method();//aa
		this.method();//aa
		super.method();//aa
	}
}

(2) Subclasses override methods of parent classes

public class Test{
    
    
    public static void main(String[] args){
    
    
    	Son s = new Son();
    	s.test();
    }
}
class Father{
    
    
	public void method(){
    
    
		System.out.println("aa");
	}
}
class Son extends Father{
    
    
	public void method(){
    
    
		System.out.println("bb");
	}
	public void test(){
    
    
		method();//bb
		this.method();//bb
		super.method();//aa
	}
}

3. super() or super(actual parameter list)

this(...)    	--    本类的构造方法
super(...)   	--    父类的构造方法

There is a default super() in each constructor method of the subclass, which calls the empty parameter constructor of the parent class. Manually calling the parent class constructor will override the default super().

Both super() and this() must be in the first line of the constructor, so they cannot appear at the same time.

6.9 final

final: final, unchangeable, its usage is:

1. Modification category

Indicates that this class cannot be inherited and has no subclasses

final class Eunuch{
    
    //太监类
	
}
class Son extends Eunuch{
    
    //错误
	
}

2. Modification method

Indicates that this method cannot be overridden by subclasses

class Father{
    
    
	public final void method(){
    
    
		System.out.println("father");
	}
}
class Son extends Father{
    
    
	public void method(){
    
    //错误
		System.out.println("son");
	}
}

3. Declare constants

If a variable is modified with final, its value cannot be modified, that is, a constant

final can modify member variables (static class variables and non-static instance variables) and local variables

If a member variable is modified with final, there is no set method, and there must be an explicit assignment statement, and the default value of the member variable cannot be used.

Constant names modified by final generally have writing standards, and all letters are capitalized .

public class Test{
    
    
    public static void main(String[] args){
    
    
    	final int MIN_SCORE = 0;
    	final int MAX_SCORE = 100;
    }
}
class Chinese{
    
    
	public static final String COUNTRY = "中华人民共和国";	
	private final String BLOODTYPE = "A";//显示赋值
    private final String CARDID;//如果没有显示赋值,必须保证在
	private String name;
	public Chinese(String cardId, String name) {
    
    
		super();
		this.CARDID = cardId;
		this.name = name;
	}
	public Chinese() {
    
    
		super();
		CARDID = "000000000000000000";//必须在所有构造器中进行赋值
	}
	public String getName() {
    
    
		return name;
	}
	public void setName(String name) {
    
    
		this.name = name;
	}
	//final修饰的没有set方法
	public static String getCountry() {
    
    
		return COUNTRY;
	}
	public String getCardId() {
    
    
		return cardId;
	}
	public String getBloodType() {
    
    
		return bloodType;
	}
}

6.10 Class initialization

6.10.1 Static code blocks

Syntax format:

【修饰符】 class 类名{
    
    
    static{
    
    
        静态代码块语句;
    }
}

Position: In addition to the methods in the class, a class can have multiple (usually only one is written)

Function: Complete class initialization

6.10.2 Class initialization

After a class is loaded into memory, a Class object will be created in the method area (study in detail in the reflection chapter later) to store all the information of the class. At this time, memory is allocated for the static variables of the class, and then the class variables are initialized. Well, in fact, the class initialization process calls a () method, and this method is automatically generated by the compiler. The compiler will merge all the code in the following two parts into the class initialization () method body in order .

(1) Explicit assignment statements for static class member variables

(2) Statements in static code blocks

The entire class will only be initialized once. If the parent class is not initialized when the subclass is initialized, the parent class will be initialized first.

Sample code 1: single class

public class Test{
    
    
    public static void main(String[] args){
    
    
    	Father.test();
    }
}
class Father{
    
    
	private static int a = getNumber();
	static{
    
    
		System.out.println("Father(1)");
	}
	private static int b = getNumber();
	static{
    
    
		System.out.println("Father(2)");
	}
	
	public static int getNumber(){
    
    
		System.out.println("getNumber()");
		return 1;
	}
	
	public static void test(){
    
    
		System.out.println("Father:test()");
	}
}
运行结果:
getNumber()
Father(1)
getNumber()
Father(2)
Father:test()

Insert image description here

Sample code 2: parent and child classes

public class Test{
    
    
    public static void main(String[] args){
    
    
    	Son.test();
        System.out.println("-----------------------------");
        Son.test();
    }
}
class Father{
    
    
	private static int a = getNumber();
	static{
    
    
		System.out.println("Father(1)");
	}
	private static int b = getNumber();
	static{
    
    
		System.out.println("Father(2)");
	}
	
	public static int getNumber(){
    
    
		System.out.println("Father:getNumber()");
		return 1;
	}
}
class Son extends Father{
    
    
	private static int a = getNumber();
	static{
    
    
		System.out.println("Son(1)");
	}
	private static int b = getNumber();
	static{
    
    
		System.out.println("Son(2)");
	}
	
	public static int getNumber(){
    
    
		System.out.println("Son:getNumber()");
		return 1;
	}
	
	public static void test(){
    
    
		System.out.println("Son:test()");
	}	
}
运行结果:
Father:getNumber()
Father(1)
Father:getNumber()
Father(2)
Son:getNumber()
Son(1)
Son:getNumber()
Son(2)
Son:test()
-----------------------------
Son:test()

in conclusion:

Each class has a class initialization method () method, and then when the subclass is initialized, if it is found that the parent class is loaded and not initialized, the parent class will be loaded and initialized first, and then the subclass will be loaded and initialized. A class will only be initialized once.

6.11 Instance initialization

6.11.1 Non-static code blocks

Syntax format:

【修饰符】 class 类名{
    
    
    {
    
    
        非静态代码块语句;
    }
}

In addition to methods in a class, there can be multiple

Function: Complete instance initialization

6.11.2 Instance initialization

In fact, when the code we write is compiled, it will automatically process the code, sort out a () class initialization method, and also sort out one or more (...) instance initialization methods. How many instance initialization methods a class has are determined by how many constructors the class has.

The method body of the instance initialization method consists of four parts:

(1) super() or super(actual parameter list) Which one to choose here depends on which sentence is in the first line of the original constructor. If it is not written, the default is super()

(2) Explicit assignment statements for non-static instance variables

(3) Non-static code blocks

(4) Corresponding code in the constructor

Special note: (2) and (3) are merged in order, (1) must be at the front (4) must be at the end

Execution features:

  • It will only be executed when the object is created.
  • Which constructor is called is to specify its corresponding instance initialization method.
  • When creating a subclass object, the instance initialization corresponding to the parent class will be executed first. Which instance initialization method of the parent class is executed depends on whether super() or super (actual parameter list) is used.

Sample code 1: single class

public class Test{
    
    
    public static void main(String[] args){
    
    
    	Father f1 = new Father();
    	Father f2 = new Father("atguigu");
    }
}
class Father{
    
    
	private int a = getNumber();
	private String info;
	{
    
    
		System.out.println("Father(1)");
	}
	Father(){
    
    
		System.out.println("Father()无参构造");
	}
	Father(String info){
    
    
		this.info = info;
		System.out.println("Father(info)有参构造");
	}
	private int b = getNumber();
	{
    
    
		System.out.println("Father(2)");
	}
	
	public int getNumber(){
    
    
		System.out.println("Father:getNumber()");
		return 1;
	}
}
运行结果:
Father:getNumber()
Father(1)
Father:getNumber()
Father(2)
Father()无参构造
Father:getNumber()
Father(1)
Father:getNumber()
Father(2)
Father(info)有参构造

Insert image description here

Sample code 2: parent and child classes

public class Test{
    
    
    public static void main(String[] args){
    
    
    	Son s1 = new Son();
        System.out.println("-----------------------------");
    	Son s2 = new Son("atguigu");
    }
}
class Father{
    
    
	private int a = getNumber();
	private String info;
	{
    
    
		System.out.println("Father(1)");
	}
	Father(){
    
    
		System.out.println("Father()无参构造");
	}
	Father(String info){
    
    
		this.info = info;
		System.out.println("Father(info)有参构造");
	}
	private int b = getNumber();
	{
    
    
		System.out.println("Father(2)");
	}
	
	public static int getNumber(){
    
    
		System.out.println("Father:getNumber()");
		return 1;
	}
}
class Son extends Father{
    
    
	private int a = getNumber();
	{
    
    
		System.out.println("Son(1)");
	}
	private int b = getNumber();
	{
    
    
		System.out.println("Son(2)");
	}
	public Son(){
    
    
		System.out.println("Son():无参构造");
	}
	public Son(String info){
    
    
		super(info);
		System.out.println("Son(info):有参构造");
	}
	public static int getNumber(){
    
    
		System.out.println("Son:getNumber()");
		return 1;
	}
}
运行结果:
Father:getNumber()
Father(1)
Father:getNumber()
Father(2)
Father()无参构造
Son:getNumber()
Son(1)
Son:getNumber()
Son(2)
Son():无参构造
-----------------------------
Father:getNumber()
Father(1)
Father:getNumber()
Father(2)
Father(info)有参构造
Son:getNumber()
Son(1)
Son:getNumber()
Son(2)
Son(info):有参构造

Sample code 3: parent-child class, method overriding

public class Test{
    
    
    public static void main(String[] args){
    
    
    	Son s1 = new Son();
    	System.out.println("-----------------------------");
    	Son s2 = new Son("atguigu");
    }
}
class Father{
    
    
	private int a = getNumber();
	private String info;
	{
    
    
		System.out.println("Father(1)");
	}
	Father(){
    
    
		System.out.println("Father()无参构造");
	}
	Father(String info){
    
    
		this.info = info;
		System.out.println("Father(info)有参构造");
	}
	private int b = getNumber();
	{
    
    
		System.out.println("Father(2)");
	}
	
	public int getNumber(){
    
    
		System.out.println("Father:getNumber()");
		return 1;
	}
}
class Son extends Father{
    
    
	private int a = getNumber();
	{
    
    
		System.out.println("Son(1)");
	}
	private int b = getNumber();
	{
    
    
		System.out.println("Son(2)");
	}
	public Son(){
    
    
		System.out.println("Son():无参构造");
	}
	public Son(String info){
    
    
		super(info);
		System.out.println("Son(info):有参构造");
	}
	public int getNumber(){
    
    
		System.out.println("Son:getNumber()");
		return 1;
	}
}
运行结果:
Son:getNumber()  //子类重写getNumber()方法,那么创建子类的对象,就是调用子类的getNumber()方法,因为当前对象this是子类的对象。
Father(1)
Son:getNumber()
Father(2)
Father()无参构造
Son:getNumber()
Son(1)
Son:getNumber()
Son(2)
Son():无参构造
-----------------------------
Son:getNumber()
Father(1)
Son:getNumber()
Father(2)
Father(info)有参构造
Son:getNumber()
Son(1)
Son:getNumber()
Son(2)
Son(info):有参构造

Sample code 4: Class initialization and instance initialization

public class Test{
    
    
    public static void main(String[] args){
    
    
    	Son s1 = new Son();
    	System.out.println("----------------------------");
    	Son s2 = new Son();
    }
}
class Father{
    
    
	static{
    
    
		System.out.println("Father:static");
	}
	{
    
    
		System.out.println("Father:not_static");
	}
	Father(){
    
    
		System.out.println("Father()无参构造");
	}
}
class Son extends Father{
    
    
	static{
    
    
		System.out.println("Son:static");
	}
	{
    
    
		System.out.println("Son:not_static");
	}
	Son(){
    
    
		System.out.println("Son()无参构造");
	}
}
运行结果:
Father:static
Son:static
Father:not_static
Father()无参构造
Son:not_static
Son()无参构造
----------------------------
Father:not_static
Father()无参构造
Son:not_static
Son()无参构造

in conclusion:

Class initialization must take precedence over instance initialization.

Class initialization is only done once.

Instance initialization is performed every time an object is created.

Constructors and non-static code blocks

To some extent, non-static code blocks are complementary to constructors, and non-static code blocks are always executed before the constructor is executed. Unlike a constructor, a non-static code block is a piece of code that is fixed to execute and cannot receive any parameters. Therefore, non-static code blocks initialize all objects of the same class in exactly the same way. For this reason, it is not difficult to find the basic usage of non-static code blocks. If there is a piece of initialization processing code that is exactly the same for all objects and does not need to receive any parameters, you can extract this initialization processing code into the non-static code block.

That is, if there is the same initialization code in each constructor, and these initialization codes do not need to receive parameters, they can be defined in a non-static code block. By extracting the same code in multiple constructors and defining it in a non-static code block, the reuse of the initial code can be better improved and the maintainability of the entire application can be improved.

6.12 Proximity principle/this/super: solving complex problems

(1) When accessing a variable in a method, if there is no this., super., then the principle of proximity is followed and the most recently declared one is found.

Sample code one:

public class Test{
    
    
    public static void main(String[] args){
    
    
    	Son s = new Son();
    	System.out.println(s.getNum());//10
    	
    	Daughter d = new Daughter();
    	System.out.println(d.getNum());//20
    }
}
class Father{
    
    
	protected int num = 10;
	public int getNum(){
    
    
		return num;
	}
}
class Son extends Father{
    
    
	private int num = 20;
}
class Daughter extends Father{
    
    
	private int num = 20;
	public int getNum(){
    
    
		return num;
	}
}

(2) When looking for a way

If this. and super. are not added, the default is to add this.

If this. is added, it will be searched from the class of the current object first. If it is not found, it will be automatically searched from the parent class.

If super. is added, search directly from the parent class.

public class Test{
    
    
    public static void main(String[] args){
    
    
    	Son s = new Son();
    	s.test();
    	
    	Daughter d = new Daughter();
    	d.test();
    }
}
class Father{
    
    
	protected int num = 10;
	public int getNum(){
    
    
		return num;
	}
	
}
class Son extends Father{
    
    
	private int num = 20;
	public void test(){
    
    
		System.out.println(getNum());//10
		System.out.println(this.getNum());//10
		System.out.println(super.getNum());//10
	}
}
class Daughter extends Father{
    
    
	private int num = 20;
	public int getNum(){
    
    
		return num;
	}
	public void test(){
    
    
		System.out.println(getNum());//20
		System.out.println(this.getNum());//20
		System.out.println(super.getNum());//10
	}
}

Guess you like

Origin blog.csdn.net/weixin_42258633/article/details/125678667