Java full stack JavaSE: 13. Object oriented

Keywords: Java JavaSE

1, Encapsulation

1.1 package overview

1. Why encapsulation?

  • If I want to use the washing machine, I just need to press the switch and washing mode. Is it necessary to understand the internal structure of the washing machine? Is it necessary to touch the motor?
  • The computer we use has CPU, hard disk, keyboard, mouse, etc. each part works together through some connection, but each part is independent
  • In real life, there is a boundary between each individual and each group, and there is a boundary between each group. The information within the same individual and group is exchanged, but it is hidden from the outside.

Object oriented programming language is a simulation of the objective world. The internal information of everything in the objective world is hidden inside the object. The outside world can not operate and modify directly, but can only access and modify it in a specified way. Encapsulation can be considered as a protective barrier to prevent the code and data of this class from being freely accessed by other classes. Proper encapsulation can make the code easier to understand and maintain, and also strengthen the security of the code.

As our system becomes more and more complex and there will be more and more classes, we must grasp the access boundary between classes. The object-oriented development principle should follow the "high cohesion and low coupling", which is one of the manifestations of "high cohesion and low coupling":

  • High cohesion: the internal data operation details of the class are completed by themselves, and external interference is not allowed;
  • Low coupling: only a small amount of methods are exposed for use

Hide the internal complexity of objects and only expose simple interfaces. It is convenient for external calls, so as to improve the scalability and maintainability of the system. Generally speaking, hide what should be hidden and expose what should be exposed. This is the design idea of encapsulation.

2. How to implement encapsulation?

Generally speaking, encapsulation is to hide what should be hidden and expose what should be exposed. So how to control the degree of exposure? It depends on the access control modifier, also known as the permission modifier.

The access control modifier controls the corresponding visible boundary. The boundaries are as follows:

(1) Class

(2) Package

(3) Subclass

(4) Module: introduced after Java 9

Permission modifier

Permission modifiers: public,protected, default, private

Modifier This categoryThis packageOther steamed stuffed bun subclassesOther packages are not subclasses
Private: private×××
default××
Protected: protected×
Public: public

External class: only public and default permission modifiers can be used

Member variable, member method, constructor, member inner class: public,protected, default, private

Tip: protected modifies non static members. When * * cross packages, * * can only be accessed in non static members of subclasses, and cannot be accessed in static members whether objects are created or not.

Example 1: non subclasses and subclasses in this package
package com.atguigu.test01.access1;

public class Father {
	public int a;
	protected int b;
	int c;
	private int d;
	
	public static int e;
	protected static int f;
	static int g;
	private static int h;
}

class Mother{
	public Mother(){
		
	}
}
package com.atguigu.test01.access1;

//This package is not a subclass
public class Other {
	public static void method(){
		Father obj = new Father();
		System.out.println(obj.a);
		System.out.println(obj.b);
		System.out.println(obj.c);
//		System.out.println(obj.d);// Cross class invisible
		
		System.out.println(Father.e);
		System.out.println(Father.f);
		System.out.println(Father.g);
//		System.out.println(h);// Cross class invisible
	}
	
	public void fun(){
		Father obj = new Father();
		System.out.println(obj.a);
		System.out.println(obj.b);
		System.out.println(obj.c);
//		System.out.println(obj.d);// Cross class invisible
		
		System.out.println(Father.e);
		System.out.println(Father.f);
		System.out.println(Father.g);
//		System.out.println(h);// Cross class invisible
	}
}

package com.atguigu.test01.access1;

//In this package subclass
public class Sub extends Father{
	public static void method(){
		//Static direct access and non static access are not allowed
/*		System.out.println(a);
		System.out.println(b);
		System.out.println(c);
		System.out.println(d);*/
		
		Father obj = new Father();
		System.out.println(obj.a);
		System.out.println(obj.b);
		System.out.println(obj.c);
//		System.out.println(obj.d);// Cross class invisible
		
		System.out.println(e);
		System.out.println(f);
		System.out.println(g);
//		System.out.println(h);// Cross class invisible
	}
	
	public void fun(){
		System.out.println(a);
		System.out.println(b);
		System.out.println(c);
//		System.out.println(d);// Cross class invisible
		
		System.out.println(e);
		System.out.println(f);
		System.out.println(g);
//		System.out.println(h);// Cross class invisible
	}
}

Example 2: cross package subclasses and non subclasses
package com.atguigu.test01.access1;

public class Father {
	public int a;
	protected int b;
	int c;
	private int d;
	
	public static int e;
	protected static int f;
	static int g;
	private static int h;
}

package com.atguigu.test01.other;

import com.atguigu.test01.access1.Father;

public class Another {
	public static void method(){
		Father obj = new Father();
		System.out.println(obj.a);
//		System.out.println(obj.b);// Cross package non subclass invisible
//		System.out.println(obj.c);// Cross package invisible
//		System.out.println(obj.d);// Cross class invisible
		
		System.out.println(Father.e);
//		System.out.println(Father.f);// Cross package non subclass invisible
//		System.out.println(Father.g);// Cross package invisible
//		System.out.println(h);// Cross class invisible
	}
	
	public void fun(){
		Father obj = new Father();
		System.out.println(obj.a);
//		System.out.println(obj.b);// Cross package non subclass invisible
//		System.out.println(obj.c);// Cross package invisible
//		System.out.println(obj.d);// Cross class invisible
		
		System.out.println(Father.e);
//		System.out.println(Father.f);// Cross package non subclass invisible
//		System.out.println(Father.g);// Cross package invisible
//		System.out.println(h);// Cross class invisible
	}
}

package com.atguigu.test01.other;

import com.atguigu.test01.access1.Father;

public class Son extends Father{
	public static void method(){
		//Static direct access and non static access are not allowed
/*		System.out.println(a);
		System.out.println(b);
		System.out.println(c);
		System.out.println(d);*/
		
		Father obj = new Father();
		System.out.println(obj.a);
//		System.out.println(obj.b);// Static members across packages
						//Non static protected cannot be accessed
//		System.out.println(obj.c);// Cross package invisible
//		System.out.println(obj.d);// Cross class invisible
		
		System.out.println(e);
		System.out.println(f);
//		System.out.println(g);// Cross package invisible
//		System.out.println(h);// Cross class invisible
	}
	
	public void fun(){
		System.out.println(a);
		System.out.println(b);
//		System.out.println(c);// Cross package invisible
//		System.out.println(d);// Cross class invisible
		
		System.out.println(e);
		System.out.println(f);
//		System.out.println(g);// Cross package invisible
//		System.out.println(h);// Cross class invisible
	}
}

Example 3: default class
package com.atguigu.test01.access1;

class Mother {
	
}
package com.atguigu.test01.access1;

public class Daughter extends Mother{

}
package com.atguigu.test01.other;

//The Mother class is the default and cannot be used across packages
public class Daughter extends Mother{

}

Example 4: public classes, default constructors, cross package usage
package com.atguigu.test01.access1;

public class Fu {
	Fu(){
		
	}
}
package com.atguigu.test01.access1;

public class Zi extends Fu{

}
package com.atguigu.test01.other;

import com.atguigu.test01.access1.Fu;

public class Zi extends Fu{
	Zi() {
		super();
	}
}
package com.atguigu.test01.access1;

public class Neighbor {
	public static void main(String[] args) {
		Fu f = new Fu();
	}
}
package com.atguigu.test01.other;

import com.atguigu.test01.access1.Fu;

public class AnotherNeighbor {
	public static void main(String[] args) {
		Fu f = new Fu();
	}
}

1.2 privatization of member variables / attributes

  • When we define a member variable of a class, we often set it as a private attribute. Prevent the external directly assigning arbitrary values to attributes, because the external assignment only needs to meet the syntax. In actual project development, not only syntax but also business logic should be satisfied.

  • After the privatization of the member variable (field), a standard get/set method is provided. We also call this member variable as a property. In other words, as long as it can be operated through get/set, it is the property of the thing, even if it has no corresponding member variable.

1. Purpose of member variable encapsulation

  • Hide class implementation details
  • Users can only access data through a predetermined method, so that control logic can be added to the method to limit unreasonable access to member variables. Data checking can also be carried out to ensure the integrity of object information.
  • It is easy to modify and improve the maintainability of the code. It mainly refers to the hidden part, which is modified internally. If the external access method remains unchanged, the external will not feel its modification at all. For example, java8 - > java9, String is implemented internally from char [] to byte [] and the external method remains unchanged, so our users will not feel its internal modification at all.

2. Implementation steps

  1. Modify member variables with private
private Data type variable name;

The code is as follows:

public class Chinese {
    private static String country;
    private String name;
  	private int age;
    private boolean marry;
}
  1. Provide getXxx method / setXxx method to access member variables. The code is as follows:
public class Chinese {
  	private static String country;
    private String name;
  	private int age;
    private boolean marry;
    
    public static void setCountry(String c){
        country = c;
    }
    
    public static String getCountry(){
        return country;
    }

	public void setName(String n) {
		name = n;
    }

    public String getName() {
        return name;
	}

    public void setAge(int a) {
        age = a;
    }

    public int getAge() {
        return age;
    }
    
    public void setMarry(boolean m){
        marry = m;
    }
    
    public boolean isMarry(){
        return marry;
    }
}

3. How to solve the problem of local variable and member variable with the same name

When the local variable has the same name as the class variable (static member variable), add "class name." before the class variable;

When the local variable has the same name as the instance variable (non static member variable), "this." is added before the instance variable

public class Chinese {
  	private static String country;
    private String name;
  	private int age;
    
    public static void setCountry(String country){
        Chinese.country = country;
    }
    
    public static String getCountry(){
        return country;
    }

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

    public String getName() {
        return name;
	}

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }
}

4. Practice

(1) Define the rectangular class Rectangle,

Declare the static variable sides, which is initialized to 4, indicating the total number of rectangular side lengths;

Declare instance variable length and width

All are privatized and corresponding get/set methods are provided

(2) Create a Rectangle object in the test class and call the corresponding test method

Implement the definition of Rectangle class:

package com.oy.object-oriented.encapsulation;

public class Rectangle {
    public static int sides = 4;
    private int length;
    private int width;
    
    public void setLength(int length){
        this.length = length;
    }
    public int getLength(){
        return this.length;
    }
    
    public void setWidth(int width){
        this.width = width;
    }
    
    public int getWidth(){
        return this.width;
    }
}

Create a Rectangle object in the test class and call the corresponding test method

package com.oy.object-oriented.encapsulation;

public class Demotest1 {
    public static void main(String[] args) {
        Rectangle rectangle = new Rectangle();
        rectangle.setLength(8);
        System.out.println("Rectangle length:"+rectangle.getLength());
        rectangle.setWidth(10);
        System.out.println("The width of the rectangle is:"+rectangle.getWidth());
    }
}

The operation results are as follows:

Rectangle length: 8
 Width of rectangle: 10

2, Constructor or construction method

We found that when we new the object, all member variables are default values. If we need to assign other values, we need to assign values to them one by one, which is too troublesome. Can we directly assign values to one or all member variables of the current object when we new the object.

Yes, Java provides us with constructors.

2.1 function of constructor

Assign initial values to instance variables when creating objects.

Note: the constructor initializes only instance variables, not static class variables

2.2. Syntax format of constructor

Constructors are also called construction methods because they look like methods, but they are different from methods.

[Modifier constructor name(){
    // Instance initialization code
}
[Modifier constructor name(parameter list){
	// Instance initialization code
}

The code is as follows:

public class Student {
	private String name;
	private int age;
	// Nonparametric structure
  	public Student() {} 
 	// Parametric structure
  	public Student(String name,int age) {
		this.name = name;
    	this.age = age; 
	}
  	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

matters needing attention:

  1. The constructor name must be the same as the class name in which it resides.
  2. It doesn't have a return value, so it doesn't need a return value type, or even void
  3. If you do not provide a constructor, the system will give a parameterless constructor, and the modifier of the constructor is the same as that of the class by default
  4. If you provide a constructor, the system will no longer provide a parameterless constructor unless you define it yourself.
  5. Constructors can be overloaded, either defining parameters or not, or defining some parameters
  6. The modifier of a constructor can only be a permission modifier and cannot be modified by any other modifier

2.3 practice

(1) Declare an employee class,

  • Including attributes: number, name, salary and gender. It is required to privatize the attributes and provide get/set,
  • Provide parameterless constructors and parameterless constructors
  • Provide getInfo()

(2) In the main of the test class, create employee class objects with nonparametric construction and parametric construction respectively, and call getInfo

public class TestEmployee {
	public static void main(String[] args){
		//Create objects with nonparametric construction and parametric construction respectively, and call getInfo
		Employee e1 = new Employee();
		System.out.println(e1.getInfo());
		
		Employee e2 = new Employee("1001","Zhang San",110000,'male');
		System.out.println(e2.getInfo());
		
		e2.setSalary(120000);
		System.out.println(e2.getInfo());
		
		System.out.println("e1 Salary:" + e1.getSalary());
	}
}
class Employee{
	private String id;
	private String name;
	private double salary;
	private char gender;
	
	//Provide parameterless constructors and parameterless constructors
	public Employee(){
		
	}
	public Employee(String id, String name){
		this.id = id;
		this.name = name;
	}
	public Employee(String id, String name, double salary, char gender){
		this.id = id;
		this.name = name;
		this.salary = salary;
		this.gender = gender;
	}
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	public char getGender() {
		return gender;
	}
	public void setGender(char gender) {
		this.gender = gender;
	}
	
	//Provide getInfo()
	public String getInfo(){
		return "No.:" + id + ",full name:" + name + ",Salary:" + salary + ",Gender:" +gender;
	}
}

3, Standard JavaBean s

JavaBean is a standard specification for classes written in Java language. Classes conforming to JavaBean, requirements:

(1) Classes must be concrete and public,

(2) And has a parameterless construction method,

(3) Privatize member variables and provide set and get methods for manipulating member variables.

public class ClassName{
  //Member variable
    
  //Construction method
  	//Nonparametric construction method [required]
  	//Parametric construction method [suggestion]
  	
  //getXxx()
  //setXxx()
  //Other member methods
}

Write classes that conform to JavaBean specifications. Take student classes as an example. The standard code is as follows:

public class Student {
	// Member variable
	private String name;
	private int age;

	// Construction method
	public Student() {
	}

	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}

	// get/set member method
	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getAge() {
		return age;
	}
    
    //List of other member methods
    public String getInfo(){
        return "full name:" + name + ",Age:" + age;
    }
}

Test class, code as follows:

public class TestStudent {
	public static void main(String[] args) {
		// Use of parameterless construction
		Student s = new Student();
		s.setName("Liuyan");
		s.setAge(18);
		System.out.println(s.getName() + "---" + s.getAge());
        System.out.println(s.getInfo());

		// Use of structure with parameters
		Student s2 = new Student("Zhao Liying", 18);
		System.out.println(s2.getName() + "---" + s2.getAge());
        System.out.println(s2.getInfo());
	}
}

4, Inherit

4.1 overview of succession

Inheritance in life

  • Property: rich second generation

  • Appearance: as shown in the figure:


Origin of inheritance

As shown in the figure:

When the same attributes and behaviors exist in multiple classes, these contents are extracted into a single class, so there is no need to define these attributes and behaviors in multiple classes, but only need to form a relationship with the extracted classes, as shown in the figure:

Among them, multiple classes can be called subclasses or derived classes; the class extracted from multiple classes is called parent class, superclass or base class.

Inheritance describes the ownership relationship between things. This relationship is the relationship of is-a. for example, in the figure, cats belong to animals and dogs belong to animals. It can be seen that parent classes are more general and subclasses are more specific. Through inheritance, we can form a relationship system between a variety of things.

Benefits of inheritance

  • Improve code reusability.

  • Improve code scalability.

  • The relationship between classes is the premise of learning polymorphism.

4.2 format of inheritance

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

[Modifier] class Parent class {
	...
}

[Modifier] class Subclass extends Parent class {
	...
}

Inheritance demonstration, the code is as follows:

/*
 * Define Animal as the parent class
 */
class Animal {
    // Define the name attribute
	String name; 
    // Define age attribute
    int age;
	// Define how animals eat
	public void eat() {
		System.out.println(age + "Year old" + name + "I'm eating");
	}
}

/*
 * Define Cat cat inherits Animal Animal
 */
class Cat extends Animal {
	// Define a method of cat catching mouse
	public void catchMouse() {
		System.out.println("Catch a mouse");
	}
}

/*
 * Define test class
 */
public class ExtendDemo01 {
	public static void main(String[] args) {
        // Create a cat object
		Cat cat = new Cat();
      
        // Assign a value to the name attribute of the cat object
		cat.name = "Tom";
      
      	// Assign a value to the age attribute of the cat object
		cat.age = 2;
        
        // Call the catchMouse() method of the cat
		cat.catchMouse();
		
      	// Call the eat() method inherited from the cat
      	cat.eat();
	}
}

Presentation results:
Catch a mouse
2 Year old Tom I'm eating

4.3 inheritance feature 1: member variables

1. Parent class member variable Privatization (private)

  • Members in the parent class, whether public or private, will be inherited by the child class.
  • Although the subclass inherits the private members of the parent class, the subclass cannot directly access the inherited private members, which can be accessed through the inherited get/set method, as shown in the figure:

The code is as follows:

/*
 * Define Animal as the parent class
 */
class Animal {
    // Define the name attribute
	private String name; 
    // Define age attribute
    public int age;
	// Define how animals eat
	public void eat() {
		System.out.println(age + "Year old" + name + "I'm eating");
	}
}

/*
 * Define Cat cat inherits Animal Animal
 */
class Cat extends Animal {
	// Define a method of cat catching mouse
	public void catchMouse() {
		System.out.println("Catch a mouse");
	}
}

/*
 * Define test class
 */
public class ExtendDemo01 {
	public static void main(String[] args) {
        // Create a cat object
		Cat cat = new Cat();
      
        // Assign a value to the name attribute of the cat object
		//cat.name = "Tom"; / / compilation error
      
      	// Assign a value to the age attribute of the cat object
		cat.age = 2;
        
        // Call the catchMouse() method of the cat
		cat.catchMouse();
		
      	// Call the eat() method inherited from the cat
      	cat.eat();
	}
}

As shown in the figure:

The screenshot of checking object member variable values by Debug in eclipse is as follows:

The screenshot of checking object member variable values by Debug in idea is as follows:

2. Duplicate name of parent-child class member variable

We say that all member variables of the parent class will inherit into the child class. What happens if the child class has a member variable with the same name as the parent class?

Parent class code:

public class Father {
	public int i=1;
	private int j=1;
	public int k=1;
	public int getJ() {
		return j;
	}
	public void setJ(int j) {
		this.j = j;
	}
}

Subclass Code:

public class Son extends Father{
	public int i=2;
	private int j=2;
	public int m=2;
}	

Now, how do you want to declare a test() method in the subclass Son and print the values of all these variables?

public class Son extends Father{
	public int i=2;
	private int j=2;
	public int m=2;
	
	public void test() {
		System.out.println("Inherited by parent class i: " + super.i);
		System.out.println("Subclass i: " +i);
//		System.out.println(super.j);
		System.out.println("Inherited by parent class j: " +getJ());
		System.out.println("Subclass j: " +j);
		System.out.println("Inherited by parent class k: " +k);
		System.out.println("Subclass m: " +m);
	}	
}	

Conclusion:

(1) When the member variable of the parent class is privatized, it cannot be accessed directly in the child class, so whether the name is duplicated does not affect it. If you want to access the private member variable of the parent class, you can only access it through the get/set method of the parent class;

(2) When the member variable of the parent class is not private, it can be accessed directly in the child class, so if there is a duplicate name, you need to add "super." to distinguish.

Use format:

super.Parent member variable name

The above test() call result:

public class TestSon{
	public static void main(String[] args){
		Son s = new Son();
		s.test();
	}
}
Inherited by parent class i: 1
 Subclass i: 2
 Inherited by parent class j: 1
 Subclass j: 2
 Inherited by parent class k: 1
 Subclass m: 2

The screenshot of the value of the member variable of the Debug view object in eclipse is as follows:

The screenshot of the value of the member variable of the Debug view object in idea is as follows:

Note: Although we can distinguish between parent and child classes with duplicate member variables, we do not recommend this in actual development.

4.4 characteristic 2 of inheritance: member method

We say that all method subclasses of the parent class will inherit, but when a method is inherited to a subclass, the subclass feels that the original implementation of the parent class is not suitable for the subclass. What should we do? We can override the method

1. Method rewrite

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

class Phone {
	public void sendMessage(){
		System.out.println("send message");
	}
	public void call(){
		System.out.println("phone");
	}
	public void showNum(){
		System.out.println("Caller ID number");
	}
}

//Smart phones
class NewPhone extends Phone {
	
	//Override the caller ID number function of the parent class, and add its own display name and picture function
	@Override
	public void showNum(){
		//Call the function whose parent class already exists and use super
		super.showNum();
		//Add your own unique function of displaying names and pictures
		System.out.println("Show caller name");
		System.out.println("Show Faces ");
	}
}

public class ExtendsDemo06 {
	public static void main(String[] args) {
      	// Create subclass objects
      	NewPhone np = new NewPhone();
        
        // Call the method inherited from the parent class
        np.call();
      
      	// Call the method overridden by the subclass
      	np.showNum();

	}
}

Tip: when overriding here, the super. Parent class member method is used to call the member method of the parent class.

matters needing attention:

1.@Override: it is written on the method to detect whether it is valid and correct override. Even if this annotation is not written, as long as it meets the requirements, it is also the correct method to overwrite it. Recommended retention

2. It must be ensured that the method names and parameter lists between parent and child classes are the same.
3. The return value type of the subclass method must be less than or equal to the return value type of the parent method (less than is actually its subclass, for example: Student < person).

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

4. The permission of the subclass method must be greater than or equal to the permission modifier of the parent method.
Tips for small extension: public > protected > Default > private

5. Several special methods cannot be rewritten

  • Static methods cannot be overridden
  • Private methods that are not visible in subclasses cannot be overridden
  • The final method cannot be overridden
    6. When a subclass throws an exception, it cannot throw an exception larger than the parent class (test the exception)

2. Method overload

(1) In the same class

class Test{
	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 parent-child classes

class Father{
	public void print(int i){
		System.out.println("i = " + i);
	}
}
class Son extends Father{
	public void print(int i,int j){
		System.out.println("i = " + i  ",j = " + j);
	}
}

For the Son class, it is equivalent to having two print methods. One parameter list is (int i) and one parameter list is (int i, int j)

4.5 inheritance feature 3: construction method

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

First, we need to recall two things, the definition, format and function of construction methods.

  1. The constructor name is consistent with the class name.

    Therefore, a subclass cannot inherit the constructor of its parent class.

  2. The constructor is used to initialize instance variables, and the subclass will inherit all member variables from the parent class

    Therefore, during the initialization of a subclass, the initialization of the parent class must be performed first. By default, there is a super() in the construction method of the subclass, which means that the instance initialization method of the parent class is called. Only after the parent class member variable is initialized can it be used by the subclass. The code is as follows:

class Fu {
  private int n;
  Fu(){
    System.out.println("Fu()");
  }
}
class Zi extends Fu {
  Zi(){
    // super(), call the parent class constructor
    super();
    System.out.println("Zi()");
  }  
}
public class ExtendsDemo07{
  public static void main (String args[]){
    Zi zi = new Zi();
  }
}
Output results:
Fu()
Zi()

What if the parent class does not have a parameterless construct?

public class Person {
	private String name;
	private int age;
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	//Other member methods omitted
}
public class Student extends Person{
	private int score;
}

At this time, the subclass code reports an error.

Solution: in the subclass constructor, use super (argument list) to display the parameterized constructor of the calling 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;
	}
	
	//Other member methods omitted
}

Conclusion:

In the process of subclass object instantiation, the instance initialization of member variables inherited from the parent class must be completed first. This process is completed by calling the instance initialization method of the parent class.

  • super(): it means to call the parameterless instance initialization method of the parent class. It is required that the parent class must have a parameterless structure and can be omitted without writing;
  • Super (argument list): it means to call the parameterized instance initialization method of the parent class. When the parent class has no parameterless construction, the constructor of the subclass must write Super (argument list) in the first line to specify which parameterized construction of the parent class is called (actually calling the instance initialization method corresponding to the constructor)
  • Both super() and super (argument list) can only appear in the first line of the subclass constructor

Form I:

class A{

}
class B extends A{

}

class Test{
    public static void main(String[] args){
        B b = new B();
        //Both class A and class B have a parameterless structure by default. The default parameterless structure of class a will also be called by default in the default parameterless structure of class B
        //But because they are all default, there are no printed statements, so it can't be seen
    }
}

Form 2:

class A{
	A(){
		System.out.println("A Class parameterless constructor");
	}
}
class B extends A{

}
class Test{
    public static void main(String[] args){
        B b = new B();
        //Class A displays declare A parameterless construct,
		//Class B has a parameterless structure by default,
		//In the default parameterless construction of class B, the parameterless construction of class A will be called by default
        //You can see that the class A parameterless constructor will be output“
    }
}

Form 3:

class A{
	A(){
		System.out.println("A Class parameterless constructor");
	}
}
class B extends A{
	B(){
		System.out.println("B Class parameterless constructor");
	}
}
class Test{
    public static void main(String[] args){
        B b = new B();
        //Class A displays declare A parameterless construct,
		//Class B displays and declares a parameterless construct,        
		//Although super() is not written in the parameterless construction of class B, the parameterless construction of class A will still be called by default
        //You can see that "class A parameterless constructor" and "class B parameterless constructor") will be output
    }
}

Form IV:

class A{
	A(){
		System.out.println("A Class parameterless constructor");
	}
}
class B extends A{
	B(){
        super();
		System.out.println("B Class parameterless constructor");
	}
}
class Test{
    public static void main(String[] args){
        B b = new B();
        //Class A displays declare A parameterless construct,
		//Class B displays and declares a parameterless construct,        
		//super() is explicitly written in the parameterless construction of class B, indicating that the parameterless construction of class A is called
        //You can see that "class A parameterless constructor" and "class B parameterless constructor") will be output
    }
}

Form V:

class A{
	A(int a){
		System.out.println("A Class parameterized constructor");
	}
}
class B extends A{
	B(){
		System.out.println("B Class parameterless constructor");
	}
}
class Test05{
    public static void main(String[] args){
        B b = new B();
        //Class a display declares a parameterized structure and does not write a parameterless structure, so class A has no parameterless structure
		//Class B displays and declares a parameterless construct,        
		//The parameterless construction of class B does not write super(...), which means that the parameterless construction of class A is called by default
        //An error is reported during compilation because class A does not have a parameterless structure
    }
}

Form 6:

class A{
	A(int a){
		System.out.println("A Class parameterized constructor");
	}
}
class B extends A{
	B(){
		super();
		System.out.println("B Class parameterless constructor");
	}
}
class Test06{
    public static void main(String[] args){
        B b = new B();
        //Class a display declares a parameterized structure and does not write a parameterless structure, so class A has no parameterless structure
		//Class B displays and declares a parameterless construct,        
		//The parameterless construction of class B explicitly writes super(), indicating that the parameterless construction of class A is called
        //An error is reported during compilation because class A does not have a parameterless structure
    }
}

Form 7:

class A{
	A(int a){
		System.out.println("A Class parameterized constructor");
	}
}
class B extends A{
	B(int a){
		super(a);
		System.out.println("B Class parameterized constructor");
	}
}
class Test07{
    public static void main(String[] args){
        B b = new B(10);
        //Class a display declares a parameterized structure and does not write a parameterless structure, so class A has no parameterless structure
		//Class B displays and declares a parameterized construct,        
		//The parameterized construction of class B explicitly writes super(a), indicating that the parameterized construction of class A is called
        //Will print "class A parameterized constructor" and "class B parameterized constructor"“
    }
}

Form 8:

class A{
    A(){
        System.out.println("A Class parameterless constructor");
    }
	A(int a){
		System.out.println("A Class parameterized constructor");
	}
}
class B extends A{
    B(){
        super();//It can be omitted to call the parameterless construction of the parent class
        System.out.println("B Class parameterless constructor");
    }
	B(int a){
		super(a);//Call parent class parameterized construction
		System.out.println("B Class parameterized constructor");
	}
}
class Test8{
    public static void main(String[] args){
        B b1 = new B();
        B b2 = new B(10);
    }
}

4.6 characteristics of inheritance 4: single inheritance restriction

  1. Java only supports single inheritance, not multiple inheritance.
//A class can only have one parent class and cannot have more than one parent class.
class C extends A{} 	//ok
class C extends A,B...	//error
  1. Java supports multi-layer 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. Subclasses and superclasses are relative concepts.

    For example, class B is a child of class A, but it is a parent of class C

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

4.7 inheritance exercise

Exercise 1

(1) Parent Graphic
Include attribute: name (drawing name). The attribute is privatized. No parameterless structure is provided, only parameterless structure is provided
Include area getArea(): return 0.0
getPerimeter() method: return 0.0
Display information getInfo() method: returns the drawing name, area and perimeter

(2) Subclass Circle circle inherits Graphic graphics
Include attribute: radius
Rewrite the getArea() and getPerimeter() methods to display information getInfo() plus radius information

(3) Subclass rectangle inherits Graphic graphics
Include attributes: length, width
Override the getArea() and getPerimeter() methods

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;
	}

	public double getArea() {
		return 0.0;
	}

	public double getPerimeter() {
		return 0.0;
	}

	/*
	 * this Object: the object that calls the current method. If it is a Graphic object, getArea() and getPerimeter() of Graphic will be executed
	 * this Object: the object that calls the current method. If it is a Circle object, the getArea() and getPerimeter() of the Circle will be executed
	 * this Object: the object that calls the current method. If it is a Rectangle object, getArea() and getPerimeter() of Rectangle will be executed
	 */
	public String getInfo() {
		return "graphical:" + name + ",the measure of area:" + getArea() + ",Perimeter:" + 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//Indicates that this method is an overridden method
	public double getArea() {
		return Math.PI * radius * radius;
	}

	@Override//Indicates that this method is an overridden method
	public double getPerimeter() {
		return Math.PI * radius * 2;
	}

	/*@Override//Indicates that this method is an overridden method
	public String getInfo() {
		return super.getInfo() + ",Radius: "+ 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("General graphics");
		System.out.println(g.getInfo());
		
		Circle c = new Circle("circular", 1.2);
		System.out.println(c.getInfo());//The object that calls the getInfo() method is c
		
		Rectangle r = new Rectangle("rectangle", 3, 5);
		System.out.println(r.getInfo());
	}
}

Exercise 2

1. Declare parent class: Person class
Include attributes: name, age, gender
Property privatization, get/set
Including getInfo() methods: for example: Name: Zhang San, age: 23, gender: Male

2. Declaration subclass: Student class, inheriting Person class
New attribute: score score
Property privatization, get/set
Including getInfo() method: for example: Name: Zhang San, age: 23, gender: male, grade: 89

3. Declare subclass: Teacher class, inheriting Person class
New attribute: salary
Property privatization, get/set
Including 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;
	}
	
	//Including getInfo() methods: for example: Name: Zhang San, age: 23, gender: Male
	public String getInfo(){
		return "full name:" + name + ",Age:" + age +",Gender:" + 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;
	}
	//Including getInfo() method: for example: Name: Zhang San, age: 23, gender: male, grade: 89
	public String getInfo(){
		//Mode 1:
//		return "Name:" + getName() + ", age:" + getAge() + ", score:" + score;
		
		//Method 2:
		return super.getInfo() + ",Achievement:" + 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;
	}
	
	//Including getInfo() method: for example: Name: Zhang San, age: 23, gender: male, salary: 10000
	public String getInfo(){
		return super.getInfo() + ",Salary:" + salary;
	}
}

public class TestPersonExer2 {
	public static void main(String[] args) {
		Person p = new Person("Zhang San", 23, 'male');
		System.out.println(p.getInfo());
		
		Student s = new Student("Chen Qi", 25, 'male', 89);
		System.out.println(s.getInfo());
		
		Teacher t = new Teacher("Chai Linyan", 18, 'female', 11111);
		System.out.println(t.getInfo());
	}
}

4.8 viewing inheritance tree

When the inheritance relationship of a class is long, how to view the inheritance relationship graphically??



5, this and super keywords

5.1 this keyword

1. The meaning of this

this represents the current object

2. this usage location

  • This is in the code block and constructor related to instance initialization: it represents the instance object being created, that is, who is new, this represents who
  • This in non static instance method: represents the object calling the method, that is, who is calling, this represents who.
  • this cannot appear in static code blocks and static methods

3. this uses the format

(1) this. Member variable name

  • When the local variable of the method has the same name as the member variable of the current object, you can add this. If there is no problem of duplicate name, you can omit this
  • This. The member variable will be found from the list of member variables declared by this class. If it is not found, it will be found from the list of member variables inherited from the parent class and still visible in the child class

(2) this. Member method

  • When calling the member method of the current object, you can add "this." or omit it. It is omitted in actual development
  • The member method of the current object is first searched from the member method list declared by this class. If it is not found, it will be searched from the member method list inherited from the parent class and still visible in the child class

(3) this() or this (argument list)

  • Only other constructors of this class can be called

  • Must be on the first line of the constructor

  • If n constructors are declared in a class, "this([argument list])" is used in up to n - 1 constructors, otherwise a recursive call loop will occur

give an example:

package com.oy.object-oriented.encapsulation.testDemo;

public class Person {
    public String name;
    public int age;
    public int salary;
    //Constructor that defines two parameters
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }
    
    // Constructor that defines three parameters
    public Person(String name,int age,int salary){
        // Contains a lot of repetitive code, which can be optimized
        //this.name = name;
        //this.age = age;
        //this.salary = salary;
        
        // After optimization
        this(name,age);
        this.salary = salary;
    }
}

5.2 super keyword

1. Meaning of super

super represents the reference from the parent class in the current object

2. Prerequisites for super use

  • The xx of the parent class referenced by super is still visible in the child class
  • super cannot be used in static code blocks and static methods

3. super usage format

(1) super. Member variable

Access the member variable of the parent class in the subclass, especially when the member variable of the subclass has the same name as the member variable of the parent class.

public class Person {
	private String name;
	private int age;
	//Other codes are omitted
}
public class Student extends Person{
	private int score;
	//Other member methods omitted
}
public class Test{
    public static void main(String[] args){
    	Student stu = new Student();
    }
}

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

Invokes the member method of the parent class in a subclass, especially when the child class overrides the member method of the parent class.

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 (argument list)

In the first line of the constructor of the subclass, it is used to indicate which instance of the parent class is called to initialize the method

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

5.3 principle of proximity and principle of traceability

1. Find variable

  • No super and this

    • If a variable is used in constructors, code blocks and methods, first check whether it is a local variable declared by the current block,
    • If it is not a local variable, first find the member variable from this class of the currently executing code
    • If it is not found in this class of the currently executed code, the parent class will be found upward (non private, cross package cannot be the default)
  • this: represents the current object

    • When finding member variables through this, first find them from this class of the currently executing code. If there is no one, you will find the parent class (non private, cross package cannot be the default).
  • super: represents the parent class

    • Find the member variable through super, and directly find the member variable from the parent class of the class where the code is currently executed
    • super() or super (argument list) can only be found from the direct parent class
    • Through super, you can only access the visible of the parent class in the child class (non private, cross package can not be the default)

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

2. Find a way

  • No super and this

    • First find the class of the current object (the object calling the method). If not, then find the direct parent class. If not, continue to trace up
  • this

    • First find the method from the class of the current object (the object calling the method). If not, then find it from the list of visible methods inherited by the parent class
  • super

    • Find directly from the visible list of methods inherited by the parent class of the current object (the object calling the method)

3. Find constructor

  • this() or this (argument list): only from this class, and will not be traced back
  • super() or super (argument list): only find from the direct parent class and will not be traced back

4. Practice

(1) Case 1
class Father{
	int a = 10;
	int b = 11;
}
class Son extends Father{
	int a = 20;
	
	public void test(){
		//The subclass has the same name as the property of the parent class, and there are two a's in the subclass object
		System.out.println("Parent class a: " + super.a);//10. Find the local variables directly from the parent class
		System.out.println("Subclass a: " + this.a);//20 find the member variables of this class first
		System.out.println("Subclass a: " + a);//20 find the local variable first, and no more from the member variable of this class
		
		//The attribute names of the child class and the parent class are different, and they are the same b
		System.out.println("b = " + b);//11 find the local variable first, but not from the member variable of this class, and not from the parent class
		System.out.println("b = " + this.b);//11 first find the member variable of this class, and then find the parent class
		System.out.println("b = " + super.b);//11. Find the local variables directly from the parent class
	}
	
	public void method(int a){
		//The subclass has the same name as the attribute of the parent class. There are two member variables A in the subclass object. At this time, there is a local variable a in the method
		System.out.println("Parent class a: " + super.a);//10. Find the local variables directly from the parent class
		System.out.println("Subclass a: " + this.a);//20 find the member variables of this class first
		System.out.println("Local variable a: " + a);//30 find local variables first
	}
    
    public void fun(int b){
        System.out.println("b = " + b);//13 find local variables first
		System.out.println("b = " + this.b);//11. Find the member variables of this class first
		System.out.println("b = " + super.b);//11. Find the local variables directly from the parent class
    }
}
public class TestInherite2 {
	public static void main(String[] args) {
		Son son = new Son();
		System.out.println(son.a);//20
		System.out.println(son.b);//11
		
		son.test();
		
		son.method(30);
        
        son.fun(13);
	}
}
(2) Case 2
public class Test{
    public static void main(String[] args){
    	Son s = new Son();
    	System.out.println(s.getNum());//10. If it is not rewritten, find this class first. If not, find the parent class
    	
    	Daughter d = new Daughter();
    	System.out.println(d.getNum());//20 override, find this class first
    }
}
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;
	}
}
(3) Case 3
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 no parent class found for this class
		System.out.println(this.getNum());//10 no parent class found for this class
		System.out.println(super.getNum());//10 no parent class found for this class
	}
}
class Daughter extends Father{
	private int num = 20;
	public int getNum(){
		return num;
	}
	public void test(){
		System.out.println(getNum());//20 find this class first
		System.out.println(this.getNum());//20 find this class first
		System.out.println(super.getNum());//10 find parent class directly
	}
}

6, Member variable initialization

6.1 member variable initialization method

1. Member variables have default values

categorySpecific typeDefault value
Basic typeInteger (byte, short, int, long)0
float, double0.0
Character (char)'\u0000'
booleanfalse
data typeDefault value
reference typeArray, class, interfacenull

We know that all member variables in a class have default values, but now we want to assign values other than the default values to member variables. What should we do?

2. Explicit assignment

public class Student{
    public static final String COUNTRY = "The People's Republic of China";
	private static String school = "Shang Silicon Valley";
	private String name;
	private char gender = 'male';
}

Explicit assignment is generally a constant value

3. Code block

What if the value that the member variable wants to initialize is not a hard coded constant value, but some values that can be obtained by complex calculation, reading files, or reading runtime environment information?

  • Static initialization block: initializing static variables
[Modifier] class Class name{
    static{
		initiate static
	}
}

  • Instance initialization: initializes the instance variable
[Modifier] class Class name{
    {
		Instance initialization block
	}
}

Static initialization block: it is called and executed by the class loader during class initialization. The static initialization of each class will only be executed once, which is earlier than the creation of the instance object.

Instance initialization block: it is automatically executed every time a new instance object is created. It is executed once for every new object.

public class Student{
	private static String school;
	private String name;
	private char gender;
	
	static{
		//Get system properties. This is just to explain that the initialization process of school may be complex
		school = System.getProperty("school");
		if(school==null) {
			school = "Shang Silicon Valley";
		}
	}
	{
		String info = System.getProperty("gender");
		if(info==null) {
			gender = 'male';
		}else {
			gender = info.charAt(0);
		}
	}
	public static String getSchool() {
		return school;
	}
	public static void setSchool(String school) {
		Student.school = school;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public char getGender() {
		return gender;
	}
	public void setGender(char gender) {
		this.gender = gender;
	}

}

4. Constructor

We found that the explicit assignment and instance initialization block initialize the instance variables of each instance object with the same value. What should we do if we want different instance objects to be initialized with different values? At this point, we can consider using a constructor. When creating a new object, the creator of the object decides what value to assign to the instance variable of the current object.

Note: the constructor initializes only instance variables, not static class variables

When initializing an instance variable and creating a new object, the creator of the object decides what value to assign to the instance variable of the current object.

6.2 class initialization

1. The purpose of class initialization is to assign values to static variables in the class.

2. In fact, the class initialization process calls a () method, which is automatically generated by the compiler. The compiler will merge all the code of the following two parts into the body of the class initialization () method in order.
clinit are the static initialization blocks for the class, and static field initialization

(1) Explicit assignment statement for static class member variables

(2) Statements in static code blocks

3. The whole class is initialized only once. If the parent class is not initialized when the child class is initialized, the parent class will be initialized first.

Example code 1: single class

public class Test{
    public static void main(String[] args){
    	Father.test();
    }
}
class Father{
	private static int a = getNumber();//The purpose of calling the method to explicitly assign a value to the a variable here is to see this process
	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()");
	}
}
Operation results:
getNumber()
Father(1)
getNumber()
Father(2)
Father:test()

Example 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()");
	}	
}
Operation results:
Father:getNumber()
Father(1)
Father:getNumber()
Father(2)
Son:getNumber()
Son(1)
Son:getNumber()
Son(2)
Son:test()
-----------------------------
Son:test()

Conclusion:

Each class has a class initialization method () method. When a child class is initialized, if the parent class is found to be loaded and uninitialized, the parent class will be loaded and initialized first, and then the child class will be loaded and initialized. A class is initialized only once.

6.3 instance initialization

1. The purpose of instance initialization is to assign values to non static member variables in a class

2. In fact, when the code we write is compiled, it will automatically process the code, sort out a () class initialization method, and sort out one or more (...) instance initialization methods. A class has several instance initialization methods, which are determined by several constructors of the class.

init is the (or one of the) constructor(s) for the instance, and non-static field initialization.

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

(1) super() or super (argument list) which one to choose here depends on the first line of the original constructor. If it is not written, it is super() by default

(2) Display assignment statement of non static instance variable

(3) Non static code block

(4) Corresponds to the code in the constructor

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

3. Execution features:

  • Is executed only when the object is created
  • For each new object, the instance initialization of the object will be completed
  • Which constructor is called is to execute 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 (argument list) is used

Example 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()Nonparametric structure");
	}
	Father(String info){
		this.info = info;
		System.out.println("Father(info)Parametric structure");
	}
	private int b = getNumber();
	{
		System.out.println("Father(2)");
	}
	
	public int getNumber(){
		System.out.println("Father:getNumber()");
		return 1;
	}
}
Operation results:
Father:getNumber()
Father(1)
Father:getNumber()
Father(2)
Father()Nonparametric structure
Father:getNumber()
Father(1)
Father:getNumber()
Father(2)
Father(info)Parametric structure

Example 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()Nonparametric structure");
	}
	Father(String info){
		this.info = info;
		System.out.println("Father(info)Parametric structure");
	}
	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(): Nonparametric structure");
	}
	public Son(String info){
		super(info);
		System.out.println("Son(info): Parametric structure");
	}
	public static int getNumber(){
		System.out.println("Son:getNumber()");
		return 1;
	}
}
Operation results:
Father:getNumber()
Father(1)
Father:getNumber()
Father(2)
Father()Nonparametric structure
Son:getNumber()
Son(1)
Son:getNumber()
Son(2)
Son(): Nonparametric structure
-----------------------------
Father:getNumber()
Father(1)
Father:getNumber()
Father(2)
Father(info)Parametric structure
Son:getNumber()
Son(1)
Son:getNumber()
Son(2)
Son(info): Parametric structure

Example code 3: parent and child classes, methods with overrides

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()Nonparametric structure");
	}
	Father(String info){
		this.info = info;
		System.out.println("Father(info)Parametric structure");
	}
	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(): Nonparametric structure");
	}
	public Son(String info){
		super(info);
		System.out.println("Son(info): Parametric structure");
	}
	public int getNumber(){
		System.out.println("Son:getNumber()");
		return 1;
	}
}
Operation results:
Son:getNumber()  //If the subclass overrides the getNumber() method, the object that creates the subclass is to call the getNumber() method of the subclass, because the current object this is the object of the subclass.
Father(1)
Son:getNumber()
Father(2)
Father()Nonparametric structure
Son:getNumber()
Son(1)
Son:getNumber()
Son(2)
Son(): Nonparametric structure
-----------------------------
Son:getNumber()
Father(1)
Son:getNumber()
Father(2)
Father(info)Parametric structure
Son:getNumber()
Son(1)
Son:getNumber()
Son(2)
Son(info): Parametric structure

6.4 class initialization and instance initialization

Class initialization must take precedence over instance initialization.

Class initialization is done only once.

Instance initialization is performed every time an object is created.

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()Nonparametric structure");
	}
}
class Son extends Father{
	static{
		System.out.println("Son:static");
	}
	{
		System.out.println("Son:not_static");
	}
	Son(){
		System.out.println("Son()Nonparametric structure");
	}
}
Operation results:
Father:static
Son:static
Father:not_static
Father()Nonparametric structure
Son:not_static
Son()Nonparametric structure
----------------------------
Father:not_static
Father()Nonparametric structure
Son:not_static
Son()Nonparametric structure

7, Polymorphism

7.1 introduction

Polymorphism is the third feature of object-oriented after encapsulation and inheritance.

In life, for example, the function of seeking area is different for circles, rectangles and triangles. The movements of running, kittens, dogs and elephants, are different. Another example is the action of flying. Insects, birds and planes fly differently. It can be seen that the same behavior can reflect different forms through different things. Then the types of each seed class will appear.

However, Java is a strongly typed static language, that is, each variable must declare its exact type before use, and then the subsequent assignment and operation are handled in strict accordance with this data type. For example:

int num = 10;
String str = "hello";
Student stu = new Student();

However, sometimes, when designing an array, or the formal parameter and return value type of a method, we can't determine its specific type, but can only determine that it is the type of a series.

For example, if you want to design an array to store the objects of various graphics and sort them according to the area of various graphics, but the specific stored objects may be circles, rectangles, triangles, etc., then the area calculation methods of various graphics are different.

For example, if you want to design a method, its function is to compare the area of two graphics and return the graphics object with a larger area. At this time, the formal parameter and return value types are graph types, but we don't know which graph type it is.

Circle[] arr = new Circle[length]; //Only round objects can be loaded
Rectangle[] arr = new Rectangle[length]; //Only rectangular objects can be loaded
//Various drawing objects cannot be managed uniformly, for example, sorting various drawing objects by area


//Many methods need to be overloaded. To add a specific graph, you need to add a method
public static Circle maxArea(Circle c1, Circle c2){//Only two circle objects can be compared
    
}
public static Rectangle maxArea(Rectangle r1, Rectangle r2){//Only two rectangular objects can be compared
    
}

At this time, Java introduces polymorphism.

7.2 definitions

1. Format

Parent type variable name = Subclass objects;

Parent class type: refers to the parent class type inherited by the child class object or the implemented parent interface type.

For example:

class Person{
	private String name;
	private int age;
	
    Person(String name, int age){
        this.name = name;
        this.age = age;
    }
    
	public void speak(){
		System.out.println(name + "Say: I'm going to be here this year" + age);
	}
}
class Man extends Person{
    Man(String name, int age){
        super(name,age);
    }
}
class Woman extends Person{
    Woman(String name, int age){
        super(name,age);
    }
}
class Test{
	public static void main(String[] args){
		Person[] arr = new Person[2];
		arr[0] = new Man("Zhang San",23);
		arr[1] = new Woman("Like flowers",18);
		
		for(int i=0; i<arr.length; i++){
			arr[i].speak();
		}
		System.out.println("------------------------");
		
		show(new Man("Zhang San",23));
		show(new Woman("Like flowers",18));
	}
	
	public static void show(Person p){
		p.speak();
	}
}

The operation results are as follows:

Zhang San said: I'm 23 this year
 Ruhua said: I'm 18 this year
------------------------
Zhang San said: I'm 23 this year
 Ruhua said: I'm 18 this year

2. Inconsistency between compile time type and runtime type

  • When compiling, look at the "parent class". You can only call the methods declared by the parent class, not the methods extended by the child class;

  • When you look at a subclass at runtime, it must be the method body that performs subclass rewriting;

The code is as follows:

Define parent class:

public class Animal {  
    public void eat(){
        System.out.println("eat~~~");
    }
}  

Define subclasses:

class Cat extends Animal {  
    public void eat() {  
        System.out.println("Eat fish");  
    }  
    public void catchMouse(){
        System.out.println("Catch a mouse"); 
    }
}  

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

Define test class:

public class Test {
    public static void main(String[] args) {
        // Polymorphic forms, creating objects
        Animal a1 = new Cat();  
        // Cat eat is called
        a1.eat();    
        //a1.catchMouse();// Error, catchmouse() is a method of subclass extension, and there is no method in the parent class
        /*
        For polymorphic references, when compiling, you can only call the methods declared by the parent class by looking at the "parent class";
        	    When you look at a subclass at runtime, it must be the method body that performs subclass rewriting;
        */

        // Polymorphic forms, creating objects
        Animal a2 = new Dog(); 
        // Dog's eat is called
        a2.eat();               
    }  
}

Operation results:

Eat fish
 Eat bones

7.3 application of polymorphism

1. Application of polymorphism in formal parameter argument

The parent class type is used as the formal parameter of the method, and the child class object is the argument.

The code is as follows:

public class Test01 {
	public static void main(String[] args) {
		showAnimalEat(new Dog()); //Formal parameter Animal a, actual parameter new Dog() 
								//The argument assigns an Animal a = new Dog() polymorphic reference to the formal parameter
		showAnimalEat(new Cat());//Formal parameter Animal a, actual parameter new Cat() 
								//The argument assigns an Animal a = new Cat() polymorphic reference to the formal parameter
	}
	
	/*
	 * Design a method to view the eating behavior of all animals
	 * Focus on the common characteristics of all animals: eat()
	 * So the formal parameter is designed as the type of the parent class
	 * 	At this time, it is not related to the methods specific to subclasses
	 */
	public static void showAnimalEat (Animal a){
        a.eat();
//        a.catchMouse();// Error, because a's compile time type is Animal, and only the methods in the parent class can be seen
    }

}

2. Polymorphism is applied to arrays

The array element type is declared as the parent type, and the actual storage is the subclass object

public class Test02 {
	public static void main(String[] args) {
		/*
		 * Declare an array that can hold objects of various animals and see how they eat
		 */
		Animal[] arr = new Animal[2]; //At this time, it is not the object of new Animal, but the array object of new Animal []
									//An array space of length 5 is opened up in the heap to hold the address of Animal or its subclass objects
		arr[0] = new Cat();//On the left arr[0] of the polymorphic reference is the Animal type, and on the right is new Cat()
							//Assign a Cat object to a variable of type Animal
		arr[1] = new Dog();
		
		for (int i = 0; i < arr.length; i++) {
			arr[i].eat();
//			arr[i].catchMouse(); Error, because arr [i] now the compile time type is Animal, and only some methods in the parent class can be seen
		}
	}
}

3. Polymorphic application in return value

The return value type of the method is declared as the type of the parent class, and the actual return value is the child class object

public class Test03 {
	public static void main(String[] args) {
		Animal c = buy("Kitty");
		System.out.println(c.getClass());
		c.eat();
	}
	/*
	 * Design a method that can buy objects of various animals. At this time, it is not sure what kind of specific animals it is
	 * 
	 * The return value type is the object of the parent class
	 * 
	 * Polymorphism is reflected in the return value type Animal. The actual returned object is new Cat() or new Dog() of the subclass
	 */
	public static Animal buy(String name){
        if("Kitty".equals(name)){
            return new Cat();
        }else if("puppy".equals(name)){
            return new Dog();
        }
        return null;
    }
}

7.4 practice

Exercise 1:

(1) Declare the parent class Traffic, including the method public void drive()
(2) Declare subclasses Car,Bicycle, etc., and override the drive method
(3) Create an array in the main of the test class. There are various vehicles. Traverse and call the drive() method
Simulate various vehicles running on the road

public class Traffic {
	public void drive(){
        System.out.println("~~~~");
    }
}
public class Car extends Traffic {
	@Override
	public void drive() {
		System.out.println("Didi...");
	}
}
public class Bicycle extends Traffic {
	@Override
	public void drive() {
		System.out.println("Kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick kick...");
	}
}
public class TestExer1 {
	public static void main(String[] args) {
		//These on the right initialize the array with anonymous objects
		Traffic[] arr = {new Car(),new Bicycle(),new Car(),new Bicycle()};
		for (int i = 0; i < arr.length; i++) {
			arr[i].drive();
		}
	}
}

Exercise 2:

(1) Declare a parent class, Person class, public void toilet()

(2) Declare a subclass, the Woman class, and override the method
(3) Declare a subclass Man class and override the method
(4) Declare a method in the test class,
public static void goToToilet(Person p){
p.toilet();
}
In main, create different subclass objects and call goToToilet method to test

public class Person {
	public void toilet(){
        System.out.println("~~~");
    }
}
public class Man extends Person {
	@Override
	public void toilet() {
		System.out.println("stand..");
	}
}
public class Woman extends Person {
	@Override
	public void toilet() {
		System.out.println("Sit..");
	}
}
public class TestPerson {
	public static void main(String[] args) {
		goToToilet(new Woman());//Implied Person p = new Woman();
		goToToilet(new Man());//Implied Person p = new Man();
	}
	
	public static void goToToilet(Person p){
		p.toilet();
	}
}

Exercise 3:

1. Declare a parent Employee employee type with attributes and name (String)
There are methods. public double earning() is used to return the paid salary. 0 is returned by default
public String getInfo(): displays name and paid salary

2. Declare a subclass SalaryEmployee formal worker, inherit the parent class Employee, add attributes, salary, working days and leave days
Rewrite the method. Public double listening() returns the paid salary. Paid salary = salary - salary / working days * leave days,

3. Declare a subclass houreemployee hourly worker and inherit the parent class Employee
There are attributes, working hours and how much is it per hour
Rewrite the method, and public double earning() returns the paid salary. Paid salary = how much per hour * hours

4. Declare a subclass Manager, inherit SalaryEmployee, and add the attribute: bonus proportion
Rewrite the method. Public double listening() returns the paid salary. Paid salary = (salary - salary / working days * leave days) * (1 + bonus ratio)

5. You are now a financial. You need to view everyone's actual salary and view the total salary.
Declare an employee array, store various employees, traverse and display their names and actual wages, and calculate the total wages of all employees

public class Employee {
	private String name;

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

	public Employee() {
		super();
	}

	public String getName() {
		return name;
	}

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

	public double earning(){
        return 0.0;
    }

	public String getInfo() {
		return "full name:" + name + ",Paid salary:" + earning();
	}
}
public class SalaryEmployee extends Employee {
	private double salary;
	private int workingDays;//Number of working days,
	private double offDays;//Leave days

	public SalaryEmployee() {
		super();
	}

	public SalaryEmployee(String name,  double salary, int workingDays, double offDays) {
		super(name);
		this.salary = salary;
		this.workingDays = workingDays;
		this.offDays = offDays;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public int getWorkingDays() {
		return workingDays;
	}

	public void setWorkingDays(int workingDays) {
		this.workingDays = workingDays;
	}

	public double getOffDays() {
		return offDays;
	}

	public void setOffDays(double offDays) {
		this.offDays = offDays;
	}

	/*
	 * Rewrite the method, and public double earning() returns the paid salary, 
		Paid salary = salary - salary / working days * leave days
	 */
	@Override
	public double earning() {
		return salary - salary/workingDays * offDays;
	}

}
public class HourEmployee extends Employee {
	private double moneyPerHour;
	private double hours;
	
	public HourEmployee() {
		super();
	}

	public HourEmployee(String name, double moneyPerHour, double hours) {
		super(name);
		this.moneyPerHour = moneyPerHour;
		this.hours = hours;
	}

	public double getMoneyPerHour() {
		return moneyPerHour;
	}

	public void setMoneyPerHour(double moneyPerHour) {
		this.moneyPerHour = moneyPerHour;
	}

	public double getHours() {
		return hours;
	}

	public void setHours(double hours) {
		this.hours = hours;
	}

	/*
	 * Rewrite the method, and public double earning() returns the paid salary, 
		Paid salary = how much per hour * hours	
	 */
	@Override
	public double earning() {
		return moneyPerHour * hours;
	}

}

public class Manager extends SalaryEmployee {
	private double commisionPer;

	public Manager() {
		super();
	}

	public Manager(String name,  double salary, int workingDays, double offDays, double commisionPer) {
		super(name, salary, workingDays, offDays);
		this.commisionPer = commisionPer;
	}

	public double getCommisionPer() {
		return commisionPer;
	}

	public void setCommisionPer(double commisionPer) {
		this.commisionPer = commisionPer;
	}

	@Override
	public double earning() {
		return super.earning() * (1+commisionPer);
	}
}
public class TestEmployee {
	public static void main(String[] args) {
		Employee[] all = new Employee[3];
		
		all[0] = new HourEmployee("Zhang San", 50, 50);
		all[1] = new SalaryEmployee("Li Si", 10000, 22, 1);
		all[2] = new Manager("Lao Wang", 20000, 22, 0, 0.3);
		
		double sum = 0;
		for (int i = 0; i < all.length; i++) {
			System.out.println(all[i].getInfo());
			sum += all[i].earning();
		}
		System.out.println("total:" + sum);
	}
}

7.5 upward and downward transformation

First, when an object is created in new, it will not change from beginning to end. That is, the runtime type of this object. The essential type will not change. This is different from the conversion of basic data types.

However, when this object is assigned to different types of variables, these variables have different compile time types.

class Animal {  
    void eat(){
        System.out.println("~~~"); 
    } 
}  

class Cat extends Animal {  
    public void eat() {  
        System.out.println("Eat fish");  
    }  
    public void catchMouse() {  
        System.out.println("Catch a mouse");  
    }  
}  
class Dog extends Animal {  
    public void eat() {  
        System.out.println("Eat bones");  
    }  
    public void watchHouse() {  
        System.out.println("Housekeeping");  
    }  
}

class Test{
    public static void main(String[] args){
        Cat a = new Cat();//a compile time type is Cat
        Animal b = a;//b compile time type is Animal
        Object c = a;//c compile time type is Object
        
        //Runtime type
        System.out.println(a.getClass());
        System.out.println(b.getClass());
        System.out.println(c.getClass());
        //The above outputs are all the same, all Cat type
        
       	//a. B and C have different compile time types
    	//Through a, you can call all methods in Cat, including those inherited from the parent class and those extended by yourself
    	//Through b, you can only call the methods of Animal class and its parent class, not the methods of Cat extension
    	//Through c, only methods of the Object class can be called
    }
}

Why type conversion?

Because of polymorphism, there must be a time when the subclass object is assigned to the parent variable. At this time, type conversion will occur during compilation.

However, after receiving the subclass object with the parent variable, we can't call the methods owned by the subclass but not by the parent. This is also a little "little trouble" brought to us by polymorphism. Therefore, to call subclass specific methods, you must do type conversion.

  • Upward Transformation: when the type (parent class) of the variable on the left > the type (child class) of the object / variable on the right, we call it upward transformation

    • At this time, when compiling, it is handled according to the type of the variable on the left. You can only call the variables and methods in the parent class, not the variables and methods unique to the child class
    • However, at runtime, it is still the type of the object itself
    • At this time, it must be safe and automatic
  • Downward Transformation: when the type (subclass) of the variable on the left < the type (parent) of the object / variable on the right, we call it downward transformation

    • At this point, when compiling, you can call variables and methods specific to subclasses by processing according to the type of variables on the left
    • However, at runtime, it is still the type of the object itself
    • At this time, it is not necessarily safe. You need to use (type) for cast
    • Not all downward transformations through compilation are correct, and classcastexceptions may occur. For safety, you can judge through isInstanceof keyword

Example code:

public class Test {
    public static void main(String[] args) {
        // Upward transformation  
        Animal a = new Cat();  
        a.eat(); 				// Cat eat is called

        // Downward transformation  
        Cat c = (Cat)a;       
        c.catchMouse(); 		// Cat's catchMouse is called
        
        // Downward transformation  
        //Dog d = (Dog)a;     // This code can be compiled, but ClassCastException is reported at runtime 
        //This is because Cat type objects are clearly created. Of course, they cannot be converted into Dog objects at run time. These two types do not have any inheritance relationship, 		// The definition of type conversion is not met.
        //d.watchHouse();        //  The call is Dog's watchhouse 
        
        Animal a2 = new Animal();
       // Dog d2 = (Dog)a2;// This code can be compiled, but ClassCastException is reported at runtime 
       // d2.watchHouse(); //  The call is Dog's watchhouse
    }  
}

In order to avoid the occurrence of ClassCastException, Java provides the instanceof keyword to verify the type of reference variables. As long as instanceof returns true, it must be safe to forcibly convert to this type and ClassCastException exceptions will not be reported.

Variable name/object instanceof data type 

Therefore, we'd better make a judgment before conversion. The code is as follows:

public class Test {
    public static void main(String[] args) {
        // Upward transformation  
        Animal a = new Cat();  
        a.eat();               // Cat eat is called

        // Downward transformation  
        if (a instanceof Cat){
            Cat c = (Cat)a;       
            c.catchMouse();        // Cat's catchMouse is called
        } else if (a instanceof Dog){
            Dog d = (Dog)a;       
            d.watchHouse();       // The call is Dog's watchHouse
        }
    }  
}

So, which instanceof judgments will return true?

  • Only when the compile time type of the object / variable is directly related to the data type after instanceof can it be compared
  • Only when the runtime type of the object / variable < = the data type after instanceof is true

Example code:

class Person{
	//Method code omitted
}
class Woman extends Person{
    //Method code omitted
}
class ChineseWoman extends Woman{
	//Method code omitted
}
class Man extends Person{
    
}
/*
 * 1,instanceof Are there any requirements for the preceding object and the following type
 * 	instanceof The compile time type of the preceding object must be directly related to the type after instanceof
 
 * 2,instanceof When to return true
 * 	instanceof The runtime type of the previous object is indeed < = instanceof, and the type after it is directly related
 * 
 */
public class TestInstanceof {
	public static void main(String[] args) {
		Man m = new Man();
//		System.out.println(m instanceof Woman);// The compile time type of error m is Man, which is not directly related to woman
		
		Person p1 = new Man();
		System.out.println(p1 instanceof Woman);
        //Yes, the compile time type of p1 is Person, which is directly related to Woman
		//However, the runtime type of p1 is Man and returns false
        
		Person p2 = new Woman();
		System.out.println(p2 instanceof Woman);
        //The compile time type of p2 is Person, which is directly related to Woman
		//The runtime type of p2 is Woman and returns true
        
		Person p3 = new ChineseWoman();
		System.out.println(p2 instanceof Woman);
        //The compile time type of p3 is Person, which is directly related to Woman
        //However, the runtime type of p3 is chinesewoman, and chinesewoman < = woman, so it returns true
	}
}
 public class Test{
     public static void main(String[] args){
        Person p1 = new Person();
        Person p2 = new Woman();
        Person p3 = new ChineseWoman();
        Person p4 = new Man();
        Object p5 = new Woman();
        ChineseWoman p6 = new ChineseWoman();
        
        //Because the runtime type of p1 is Person and the compile time type is Person
        System.out.println(p1 instanceof Object);//True person < object type
        System.out.println(p1 instanceof Person);//True person = person type
        System.out.println(p1 instanceof Woman);//false 	  Person > woman type
        System.out.println(p1 instanceof ChineseWoman);//False person > chinesewoman type
        System.out.println(p1 instanceof Man);//False person > man type
        System.out.println("------------------------");
        
      //Because the runtime type of p2 is the Woman type and the compile time type is Person
        System.out.println(p2 instanceof Object);//True woman < object type
        System.out.println(p2 instanceof Person);//True woman < person type
        System.out.println(p2 instanceof Woman);//true Woman = Woman type
        System.out.println(p2 instanceof ChineseWoman);//False Woman > chinesewoman type
        System.out.println(p2 instanceof Man);//false Woman and Man are peer relationships and have no parent-child relationship
        System.out.println("------------------------");
        
        //Because the runtime type of p3 is ChineseWoman and the compile time type is Person
        System.out.println(p3 instanceof Object);//True chinesewoman < object type
        System.out.println(p3 instanceof Person);//True chinesewoman < person type
        System.out.println(p3 instanceof Woman);//True chinesewoman < woman type
        System.out.println(p3 instanceof ChineseWoman);//true ChineseWoman = ChineseWoman type
        System.out.println(p3 instanceof Man);//False Chinese woman and Man are concerned about uncles and nephews, not father son relationships
        System.out.println("------------------------");
        
        //Because the runtime type of p4 is Man and the compile time type is Person
        System.out.println(p4 instanceof Object);//True man < object type
        System.out.println(p4 instanceof Person);//True man < person type
        System.out.println(p4 instanceof Woman);//false Woman and Man are peer relationships and have no parent-child relationship
        System.out.println(p4 instanceof ChineseWoman);//False Chinese woman and Man are concerned about uncles and nephews, not father son relationships
        System.out.println(p4 instanceof Man);//true Man = Man type
        System.out.println("------------------------");
        
        //Because the runtime type of p5 is the Woman type and the compile time type is Object
        System.out.println(p5 instanceof Object);//True woman < object type
        System.out.println(p5 instanceof Person);//True woman < person type
        System.out.println(p5 instanceof Woman);//true Woman = Woman type
        System.out.println(p5 instanceof ChineseWoman);//False Woman > chinesewoman type
        System.out.println(p5 instanceof Man);//false Woman and Man are peer relationships and have no parent-child relationship
        System.out.println("------------------------");
 
        //Because the runtime type of p6 is ChineseWoman and the compile time type is ChineseWoman
        System.out.println(p6 instanceof Object);//True chinesewoman < object type
        System.out.println(p6 instanceof Person);//True chinesewoman < person type
        System.out.println(p6 instanceof Woman);//True chinesewoman < woman type
        System.out.println(p6 instanceof ChineseWoman);//true ChineseWoman = ChineseWoman type
//        System.out.println(p6 instanceof Man);// The compilation failed because the compile time type of P6 is ChineseWoman and is not directly related to man
        System.out.println("------------------------");
    }
 }

Exercises

1. Declare a parent Employee employee type,
There are attributes, name (String), date of birth (MyDate type, also a user-defined date type including year, month and day attributes)
Yes, public abstract double heading()
public String getInfo(): displays name and paid salary

2. Declare a subclass SalaryEmployee formal worker and inherit the parent class Employee
Add attribute, salary, working days and leave days
Rewrite the method. Public double listening() returns the paid salary. Paid salary = salary - salary / working days * leave days,
Rewriting method, public String getInfo(): display name and paid salary, monthly salary, working days and leave days

3. Declare a subclass houreemployee hourly worker and inherit the parent class Employee
There are attributes, working hours and how much is it per hour
Rewrite the method, and public double earning() returns the paid salary. Paid salary = how much per hour * hours
Rewrite method, public String getInfo(): display name and actual salary, hourly salary and working hours
Add a method, public void leave(): print to check whether the tool is damaged and needs compensation

4. Declare a subclass Manager, which inherits SalaryEmployee
Add attribute: bonus, bonus proportion
Rewrite the method. Public double listening() returns the paid salary. Paid salary = (salary - salary / working days * leave days) * (1 + bonus ratio)
Rewrite method, public String getInfo(): display name and actual salary, monthly salary, working days, leave days and bonus proportion

5. Declare an employee array to store various employees,
You are now a personnel. Enter the current month from the keyboard and need to view everyone's details.
If he is a regular worker (including SalaryEmployee and Manager) and his birthday is this month, wish him a happy birthday and inform him to receive birthday gifts. If houreemployee displays hourly workers, the completion check is performed, that is, the leave method is called

public abstract class Employee {
	private String name;
	private MyDate birthday;
	public Employee(String name, MyDate birthday) {
		super();
		this.name = name;
		this.birthday = birthday;
	}
	public Employee(String name, int year, int month, int day) {
		super();
		this.name = name;
		this.birthday = new MyDate(year, month, day);
	}
	public Employee() {
		super();
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public MyDate getBirthday() {
		return birthday;
	}
	public void setBirthday(MyDate birthday) {
		this.birthday = birthday;
	}
	
	public abstract double earning();
	
	public String getInfo(){
		return "full name:" + name + ",birthday:" + birthday.getInfo() +",Paid salary:" + earning();
	}
}
public class SalaryEmployee extends Employee {
	private double salary;
	private int workingDays;//Number of working days,
	private double offDays;//Leave days

	public SalaryEmployee() {
		super();
	}

	public SalaryEmployee(String name, int year, int month, int day, double salary, int workingDays, double offDays) {
		super(name, year, month, day);
		this.salary = salary;
		this.workingDays = workingDays;
		this.offDays = offDays;
	}

	public SalaryEmployee(String name, MyDate birthday, double salary, int workingDays, double offDays) {
		super(name, birthday);
		this.salary = salary;
		this.workingDays = workingDays;
		this.offDays = offDays;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public int getWorkingDays() {
		return workingDays;
	}

	public void setWorkingDays(int workingDays) {
		this.workingDays = workingDays;
	}

	public double getOffDays() {
		return offDays;
	}

	public void setOffDays(double offDays) {
		this.offDays = offDays;
	}

	/*
	 * Rewrite the method, and public double earning() returns the paid salary, 
		Paid salary = salary - salary / working days * leave days
	 */
	@Override
	public double earning() {
		return salary - salary/workingDays * offDays;
	}
	
	@Override
	public String getInfo() {
		return super.getInfo() + ",a monthly salary:" + salary + ",working day:" + workingDays +",Leave days:" + offDays;
	}
}
public class HourEmployee extends Employee {
	private double moneyPerHour;
	private double hours;
	
	public HourEmployee() {
		super();
	}

	public HourEmployee(String name, int year, int month, int day, double moneyPerHour, double hours) {
		super(name, year, month, day);
		this.moneyPerHour = moneyPerHour;
		this.hours = hours;
	}

	public HourEmployee(String name, MyDate birthday, double moneyPerHour, double hours) {
		super(name, birthday);
		this.moneyPerHour = moneyPerHour;
		this.hours = hours;
	}

	public double getMoneyPerHour() {
		return moneyPerHour;
	}

	public void setMoneyPerHour(double moneyPerHour) {
		this.moneyPerHour = moneyPerHour;
	}

	public double getHours() {
		return hours;
	}

	public void setHours(double hours) {
		this.hours = hours;
	}

	/*
	 * Rewrite the method, and public double earning() returns the paid salary, 
		Paid salary = how much per hour * hours	
	 */
	@Override
	public double earning() {
		return moneyPerHour * hours;
	}

	@Override
	public String getInfo() {
		return super.getInfo() + ",Hourly rate:" + moneyPerHour + ",Hours:" + hours;
	}

	public void leave(){
		System.out.println("Hourly worker, check whether the tools used are damaged and need compensation, and then take the money and leave");
	}
}

public class Manager extends SalaryEmployee {
	private double commisionPer;

	public Manager() {
		super();
	}

	public Manager(String name, int year, int month, int day, double salary, int workingDays, double offDays,
			double commisionPer) {
		super(name, year, month, day, salary, workingDays, offDays);
		this.commisionPer = commisionPer;
	}

	public Manager(String name, MyDate birthday, double salary, int workingDays, double offDays, double commisionPer) {
		super(name, birthday, salary, workingDays, offDays);
		this.commisionPer = commisionPer;
	}

	public double getCommisionPer() {
		return commisionPer;
	}

	public void setCommisionPer(double commisionPer) {
		this.commisionPer = commisionPer;
	}

	@Override
	public double earning() {
		return super.earning() * (1+commisionPer);
	}
	@Override
	public String getInfo() {
		return super.getInfo() + ",Bonus ratio:" + commisionPer;
	}
}

public class TestEmployee {
	public static void main(String[] args) {
		Employee[] all = new Employee[3];
		/*all[0] = new HourEmployee("Zhang San ", new MyDate(1990, 5, 1), 50, 50);
		all[1] = new SalaryEmployee("Li Si ", new MyDate(1991, 1, 1), 10000, 22, 1);
		all[2] = new Manager("Lao Wang ", new MyDate(1987, 12, 8), 20000, 22, 0, 0.3);*/
		
		all[0] = new HourEmployee("Zhang San", 1990, 5, 1, 50, 50);
		all[1] = new SalaryEmployee("Li Si", 1991, 1, 1, 10000, 22, 1);
		all[2] = new Manager("Lao Wang", 1987, 12, 8, 20000, 22, 0, 0.3);
		
		//Enter the current month from the keyboard
		Scanner input = new Scanner(System.in);
		System.out.print("Please enter the current month:");
		int month;
		while(true){
			month = input.nextInt();
			if(month>=1 && month<=12){
				break;
			}
		}
		input.close();
		
		for (int i = 0; i < all.length; i++) {
			System.out.println(all[i].getInfo());
			if(all[i] instanceof SalaryEmployee){
				if(month == all[i].getBirthday().getMonth()){
					System.out.println(all[i].getName() +"Happy birthday, get birthday subsidy shopping card");
				}
			}else{
				HourEmployee he = (HourEmployee) all[i];
				he.leave();
			}
		}
	}
}

7.6 principles on member variable and member method reference in polymorphic reference

1. Member variables: only look at compile time types

If you access member variables directly, you only look at compile time types

package com.atguigu.test05;

/*
 * The member variable is not overridden. It only depends on the compile time type
 */
public class TestExtends {
	public static void main(String[] args) {
		Son s = new Son();
		System.out.println(s.a);//2. Because the compile time type of son is son
		System.out.println(((Father)s).a);//1 ((Father) son) compile time type, which is Father
		
		Father s2 = new Son();
		System.out.println(s2.a);//The compile time type of 1 son2 is Father
		System.out.println(((Son)s2).a);//2 ((Son) Son2) compile time type, that is, Son
	}
}
class Father{
	int a = 1;
}
class Son extends Father{
	int a = 2;
}

2. Non virtual methods: only look at compile time types

There are three non virtual methods in Java:

1. The static method called by the invokestatic instruction, which is determined at compile time that it will not change at run time.

javap -v .\Test.class

2. Methods called by invokespecial instruction, including private methods, instance construction methods and parent class methods, which have been determined at compile time and will not be changed at run time

3. The method modified by the final keyword. Although the final method is called by the invokevirtual instruction, the final modified method cannot be overridden in subclasses, so the final modified method cannot be dynamically changed at run time. The java language specification clearly stipulates that the final method is a non virtual method.

package com.atguigu.test09;

public class Test {

	public static void main(String[] args) {
		Father f = new Son();
		f.test();//Just look at compile time types
        f.method();
	}
}
class Father{
	public static void test(){
		System.out.println("Father.test");
	}
    public void method(){
        System.out.println("Father.method");
        fun();//Look at the runtime type
        other();//Look at the compile time type
    }
    public void fun(){
        System.out.println("Father.fun");
    }
    private void other(){
        System.out.println("Father.other");
    }
}
class Son extends Father{
	public static void test(){
		System.out.println("son");
	}
    public void fun(){
        System.out.println("Son.fun");
    }
    private void other(){
        System.out.println("Son.other");
    }
}

Tips:

Static methods cannot be overridden

It is best to use "class name" when calling static methods

Operation results:

Father.test
Father.method
Son.fun
Father.other

3. Virtual methods: static dispatch and dynamic binding

In Java, virtual method refers to a method whose call entry address can not be determined in the compilation stage and class loading stage, but can only be determined in the running stage, that is, a method that may be rewritten.

When we call a virtual method in the form of "object. Method", how do we determine which method it executes?

(1) Static dispatch: first look at the compile time type of this object and find the most matching method in the compile time type of this object

The best match means that the compile time type of the argument best matches the type of the formal parameter

(2) Dynamic binding: look at the runtime type of the object. If the runtime class of the object overrides the most matching method just found, the overridden method will be executed. Otherwise, the method in the compile time type will still be executed

(1) Example 1: there is no overload and rewriting
abstract class Animal {  
    public abstract void eat();  
}  
class Cat extends Animal {  
    public void eat() {  
        System.out.println("Eat fish");  
    }  
}  

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

public class Test{
    public static void main(String[] args){
        Animal a = new Cat();
        a.eat();
    }
}

The above code performs static dispatch during compilation: at this time, the compile time type of a is Animal class, so search for the eat() method in the Animal class. If there is no such method in the Animal class or its parent class, an error will be reported.

During runtime, dynamic binding is performed dynamically: the runtime type of a is Cat class, and the subclass overrides the eat() method, so the eat method of Cat class is executed. If it is not overridden, the eat() method of Animal class is executed

(2) Example 2: overloaded but not overridden
class MyClass{
	public void method(Father f) {
		System.out.println("father");
	}
	public void method(Son s) {
		System.out.println("son");
	}
	public void method(Daughter f) {
		System.out.println("daughter");
	}
}
class Father{
	
}
class Son extends Father{
	
}
class Daughter extends Father{
	
}
public class TestOverload {
	public static void main(String[] args) {
		Father f = new Father();
		Father s = new Son();
		Father d = new Daughter();
        
        MyClass my = new MyClass();
		my.method(f);//father
		my.method(s);//father
		my.method(d);//father
	}
}

The operation results are as follows:

father
father
father

The above code performs static dispatch during compilation: because my is MyClass type, find the most matching method method in MyClass type.

During runtime, dynamic binding is performed dynamically: that is, it is determined that the method(Father f) method in MyClass class is executed, because the runtime type of my object is still MyClass type.

Some students will ask, shouldn't you execute method(Father f), method(Son s) and method (daught d) respectively?

Because the compile time types of arguments F, s and D are all Father types, method(Father f) is the most appropriate.

(3) Example 3: overloaded or not overridden
class MyClass{
	public void method(Father f) {
		System.out.println("father");
	}
	public void method(Son s) {
		System.out.println("son");
	}
}
class Father{
	
}
class Son extends Father{
	
}
class Daughter extends Father{
	
}
public class TestOverload {
	public static void main(String[] args) {
		MyClass my = new MyClass();
		Father f = new Father();
		Son s = new Son();
		Daughter d = new Daughter();
		my.method(f);//father
		my.method(s);//son
		my.method(d);//father
	}
}

The above code performs static dispatch during compilation: because my is MyClass type, find the most matching method method in MyClass type.

During runtime, dynamic binding is performed dynamically: that is, it is determined that the method(Father f) method in MyClass class is executed, because the runtime type of my object is still MyClass type.

Some students may wonder why method(Father f) and method(Son s) are implemented respectively this time?

At this time, the compile time types of arguments F, s and D are Father, Son and daugher respectively, and daugher can only match the type of Father parameter

(4) Example 4: overloaded or not overridden
class MyClass{
	public void method(Father f) {
		System.out.println("father");
	}
	public void method(Son s) {
		System.out.println("son");
	}
}
class MySub extends MyClass{
	public void method(Daughter d) {
		System.out.println("daughter");
	}
}
class Father{
	
}
class Son extends Father{
	
}
class Daughter extends Father{
	
}
public class TestOverload {
	public static void main(String[] args) {
		MyClass my = new MySub();
		Father f = new Father();
		Son s = new Son();
		Daughter d = new Daughter();
		my.method(f);//father
		my.method(s);//son
		my.method(d);//father
	}
}

The above code performs static dispatch during compilation: because my is MyClass type, find the most matching method method in MyClass type.

During runtime, dynamic binding is performed dynamically: that is, it is determined that the method(Father f) method in MyClass class is executed, because the runtime type of my object is still MyClass type.

Some students will ask, isn't the my object of MySub type and there is a method (daught d) method in the MySub type, then should the my.method(d) statement execute the method (daught d) method in the MySub type?

  • If the type of my variable is MyClass at compile time, there are only method(Father f) and method(Son s) methods in MyClass,

  • f. The compile time types of S and D variables are Father, Son and daugher respectively, and daugher can only match the type of Father parameter

  • The method(Father f) method in the MySub class is not overridden, so the method(Father f) method in the MyClass class class is still executed

(5) Example 5: overloading and rewriting
class MyClass{
	public void method(Father f) {
		System.out.println("father");
	}
	public void method(Son s) {
		System.out.println("son");
	}
}
class MySub extends MyClass{
	public void method(Father d) {
		System.out.println("sub--");
	}
    public void method(Daughter d) {
		System.out.println("daughter");
	}
}
class Father{
	
}
class Son extends Father{
	
}
class Daughter extends Father{
	
}
public class TestOverloadOverride {
	public static void main(String[] args) {
		MyClass my = new MySub();
		Father f = new Father();
		Son s = new Son();
		Daughter d = new Daughter();
		my.method(f);//sub--
		my.method(s);//son
		my.method(d);//sub--
	}
}

The above code performs static dispatch during compilation: because my is MyClass type, find the most matching method method in MyClass type.

During runtime, dynamic binding is performed dynamically: that is, it is determined that the method(Father f) method in MyClass class is executed, because the runtime type of my object is still MyClass type.

Some students will ask, isn't the my object of MySub type and there is a method (daught d) method in the MySub type, then should the my.method(d) statement execute the method (daught d) method in the MySub type?

  • If the type of my variable is MyClass at compile time, there are only method(Father f) and method(Son s) methods in MyClass,

  • f. The compile time types of S and D variables are Father, Son and daugher respectively, and daugher can only match the type of Father parameter

  • The method(Father f) method in the MySub class is overridden, so the method(Father f) method in the MySub class is executed

8, native keyword

native: native
Usage:

Can only modify methods

The method body code representing this method is not implemented in Java language, but written in C/C + + language.

However, for Java programmers, they can call it normally as Java methods, or subclass rewrite it.

JVM memory management:

Area nameeffect
Program counterThe program counter is a register in the CPU, which contains the address of the next instruction to be executed by each thread
Native Method Stack When the local method of native is invoked in the program, the memory area during the execution of the local method
Method areaStore class information, constants, static variables, code compiled by the real-time compiler and other data that have been loaded by the virtual machine.
Heap memoryStorage objects (including array objects), created by new, are stored in heap memory.
VM Stack It is used to store the local variable table of each Java method being executed, etc. The local variable table stores various basic data types and object references of known length during compilation. After the method is executed, it is automatically released.

Modifier used together?

External classMember variableCode blockconstructor methodlocal variable
public××
protected×××
private×××
static×××
final××
abstract××××
native×××××

Modifier that cannot be used with abstract?

(1) abstract and final cannot modify methods and classes together

(2) abstract and static cannot modify methods together

(3) abstract and native cannot modify methods together

(4) abstract and private cannot modify methods together

static and final are used together:

(1) Modification method: Yes, because none can be overridden

(2) Decorated member variable: Yes, it represents a static constant

(3) Modify local variables: No, static cannot modify local variables

(4) Modify code block: No, final cannot modify code block

(5) Modify internal classes: member internal classes can be modified together, but local internal classes cannot be modified together (described later)

9, final keyword

Final: final and unchangeable. Its usage includes:

1. Modifier class

Indicates that this class cannot be inherited and has no subclasses

final class Eunuch{//Eunuchs
	
}
class Son extends Eunuch{//error
	
}

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(){//error
		System.out.println("son");
	}
}

3. Declaration constant

final modifies a variable (member variable or local variable) to indicate that its value cannot be modified, that is, constant. It is recommended to use uppercase letters for constant names.

If a member variable is decorated with final, there is no set method, and it must be initialized (it can be explicitly assigned, or assigned in the initialization block, and the instance variable can also be assigned in the constructor)

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 = "The People's Republic of China";	
	private String name;
	public Chinese( String name) {
		super();
		this.name = name;
	}
	public Chinese() {
		super();
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	//The final modifier has no set method
	public static String getCountry() {
		return COUNTRY;
	}
}

10, Object root parent class

6.10.1 how to understand root parent class

Class java.lang.Object is the root class of the class hierarchy, that is, the parent class of all classes. Each class uses Object as its superclass.

  • Variables of type Object and objects of any reference data type other than Object are polymorphic references
  • 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 MyClass /*extends Object*/ {
  	// ...
}

6.10.2 API of object class

API(Application Programming Interface). Java API is a programmer's dictionary and a description document of the classes provided to us in JDK. So we can learn the classes provided by Java and know how to use them by querying the API. You can't know how these classes are implemented in the API document. If you want to view the specific implementation code, you need to view the src source code.

According to the JDK source code and the API documents of the Object class, the Object class contains 11 methods. Today we mainly learn five of them:

(1)toString()

public String toString()

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

② It is usually recommended to rewrite. In eclipse, you can use Alt +Shift + S – > generate tostring()

③ If we directly system. Out. Println (object), the toString() of this object will be called automatically by default

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

For example, the custom Person class:

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

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

    // Omit constructor and Getter Setter
}

(2)getClass()

public final Class<?> Getclass(): get the runtime type of the object

Because Java is polymorphic, the compile time type of a variable that references a data type may be inconsistent with the runtime type. Therefore, if you need to view the type of the object actually pointed to by this variable, you need to use the getClass() method

	public static void main(String[] args) {
		Object obj = new String();
		System.out.println(obj.getClass());//Runtime type
	}

(3)finalize()

protected void finalize(): the method used to finally clean up memory

public class TestFinalize {
	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			MyData my = new MyData();
		}
		
		System.gc();//Notify the garbage collector to recycle garbage
		
		try {
			Thread.sleep(2000);//Wait 2 seconds before ending main, in order to see the effect
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
class MyData{

	@Override
	protected void finalize() throws Throwable {
		System.out.println("Gently I left...");
	}
	
}

Interview question: what is your understanding of finalize?

  • When the object is determined by GC as garbage to be recycled, GC will call this method for you before recycling, not by programmers manually.

  • This method is different from the destructor of C language. If the destructor of C language is called, the object must be destroyed and the memory will be recycled. However, the call of finalize method does not necessarily destroy the current object, because there may be code to "revive" the current object in finalize()

  • The finalize method of each object is called only once.

  • Subclasses can be rewritten. They are generally used to completely release some resource objects, and these resource objects often use the resource memory applied for through codes such as C/C + +

(4)hashCode()

public int hashCode(): returns the hash value of each object.

General agreement of hashCode:

  • ① If the hash values of two objects are different, the two objects must not be equal;
  • ② If the hash values of two objects are the same, the two objects are not necessarily equal.

It is mainly used to improve storage and query performance when objects are stored in containers such as hash tables.

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

(5)equals()

public boolean equals(Object obj): used to judge whether the current object this is equal to the specified object obj

① By default, the implementation of the equals method is equivalent to "= =", comparing the address value of the object

② We can choose to rewrite some requirements:

A: If equals is overridden, the hashCode() method must be overridden together, because it stipulates:

a: if two objects call equals and return true, the hashCode values of the two objects must be equal;

b: if the hashCode values of two objects are different, it must be false for the two objects to call the equals method;

c: if the hashCode values of two objects are the same, the two objects calling equals may be true or false

B: If you rewrite equals, you must follow the following principles:

a: Reflexivity: x.equals(x) returns true

b: transitivity: x.equals(y) is true, y.equals(z) is true, and then x.equals(z) should also be true

c: consistency: as long as the attribute values involved in the equals comparison are not modified, the call results should be consistent at any time

d: symmetry: the results of x.equals(y) and y.equals(x) should be the same

e: non empty objects and null equals must be false

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 int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((host == null) ? 0 : host.hashCode());
		result = prime * result + ((password == null) ? 0 : password.hashCode());
		result = prime * result + ((username == null) ? 0 : username.hashCode());
		return result;
	}
	@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;
	}
	
}

Posted by RealDrift on Wed, 08 Sep 2021 15:16:20 -0700