Java Review Notes - Object-Oriented Advanced


One, Static

(1) Overview of Static

In Java, staticis a keyword used to declare static members. Static members belong to a class rather than an instance and can be accessed directly by the class name without creating an instance of the class.

Within a class, statickeywords can be used in the following places:

  1. Static variables (class variables): staticVariables declared using keywords belong to the class rather than the instance, have only one copy, and can be directly accessed through the class name.
public class MyClass {
    
    
    static int count;

    public static void main(String[] args) {
    
    
        MyClass.count = 10;
        System.out.println(MyClass.count);
    }
}
  1. Static method: staticThe method declared with keywords belongs to the class rather than the instance, and can be called directly through the class name without creating an instance of the class.
public class MyClass {
    
    
    public static void myStaticMethod() {
    
    
        System.out.println("This is a static method.");
    }

    public static void main(String[] args) {
    
    
        MyClass.myStaticMethod();
    }
}
  1. Static code block: staticThe code block declared with keywords is executed when the class is loaded, only once.
public class MyClass {
    
    
    static {
    
    
        System.out.println("This is a static code block.");
    }

    public static void main(String[] args) {
    
    
        // 输出:This is a static code block.
    }
}
  1. Static inner class: staticThe inner class declared with keywords can be accessed directly through the outer class name without creating an instance of the outer class.
public class OuterClass {
    
    
    static class InnerClass {
    
    
        public void printMessage() {
    
    
            System.out.println("This is an inner static class.");
        }
    }

    public static void main(String[] args) {
    
    
        OuterClass.InnerClass inner = new OuterClass.InnerClass();
        inner.printMessage();
    }
}

It should be noted that static members cannot directly access non-static members, because non-static members belong to the instance of the class, and static members belong to the class. If you need to access non-static members, you must first create an instance of the class.

(2) Static variables

In Java, static variables (also known as class variables) are staticvariables declared using keywords. A static variable belongs to the class not the instance of the class, there is only one copy and all instances of the class share the variable.

Static variables are created when the class is loaded and remain constant throughout the program. They can be accessed directly by class name without creating an instance of the class.

Here is an example of declaring and using static variables:

public class MyClass {
    
    
    static int count; // 声明一个静态变量

    public static void main(String[] args) {
    
    
        MyClass.count = 10; // 通过类名直接访问静态变量
        System.out.println(MyClass.count); // 输出:10

        MyClass obj1 = new MyClass();
        obj1.count = 20; // 也可以通过实例访问静态变量,但不推荐这样做
        System.out.println(obj1.count); // 输出:20

        MyClass obj2 = new MyClass();
        System.out.println(obj2.count); // 输出:20(因为静态变量被所有实例共享)
    }
}

Note the following points:

  1. Static variables are created when the class is loaded, so they can be accessed without creating an instance of the class.
  2. Static variables are shared by all instances of a class, so changes to static variables affect all instances.
  3. The life cycle of a static variable is the same as the running cycle of the program, and there is only one copy.
  4. Static variables are usually used with static methods, static variables can be accessed in static methods.

Static variables are often used to store globally shared data or constants, such as representing global counters, configuration information, etc. However, static variables need to be used with caution, because they can be modified anywhere, which may lead to unpredictable results.

(3) Static method

In Java, static methods (also known as class methods) are staticmethods declared using keywords. Static methods belong to the class rather than the instance of the class, and can be called directly through the class name without creating an instance of the class.

Static methods are similar to static variables in that they are class-level operations that do not depend on class instances. Static methods are usually used to perform class-related operations, such as tool methods, calculation methods, etc., without the need to manipulate the state of the instance.

Here is an example of declaring and using a static method:

public class MyClass {
    
    
    static int add(int a, int b) {
    
     // 声明一个静态方法
        return a + b;
    }

    public static void main(String[] args) {
    
    
        int sum = MyClass.add(5, 10); // 直接通过类名调用静态方法
        System.out.println(sum); // 输出:15
    }
}

Note the following points:

  1. Static methods are created when the class is loaded, so they can be invoked without creating an instance of the class.
  2. Static methods can only access static variables and call other static methods, but cannot access non-static variables and call non-static methods. Because non-static variables and methods depend on the instance of the class, and static methods do not have a reference to the instance.
  3. Static methods are often used to perform operations that do not require manipulation of instance state, such as mathematical operations, string manipulation, utility methods, and so on.
  4. Static methods cannot be overridden by subclasses because they belong to the class and not the instance. But it is possible to define a static method with the same signature in a subclass, which will be considered as hiding the static method of the superclass.

Use cases for static methods include:

  1. Create a utility class, which contains some common static methods, such as mathematical operations, date processing, and so on.
  2. When you need to call a static method in an instance method, you can directly access it through the class name to avoid creating an instance.
  3. If a method does not depend on the state of the instance or needs to operate on globally shared data, it can be defined as a static method.

It should be noted that excessive use of static methods and static variables may lead to increased code coupling, making unit testing and extension difficult. Therefore, when designing and using static methods, you need to weigh the pros and cons and choose the appropriate method.

(4) Tools

In Java, Utility Class (Utility Class) is a common class design pattern, which is used to encapsulate some general static methods and utility functions. These methods are usually not related to specific functions or operations and can be shared by multiple classes and modules. and reuse.

The following are the general steps to create a utility class:

  1. Create a class and finaldecorate it with keywords to prevent it from being inherited.
  2. Make the constructor private to prevent instantiation.
  3. Declare all methods as public static, making them static methods.
  4. Provide some common functional methods, such as mathematical operations, string processing, date conversion, etc.

Here is an example of a simple utility class:

public final class MathUtils {
    
    
    private MathUtils() {
    
    
        // 防止实例化
    }

    public static int add(int a, int b) {
    
    
        return a + b;
    }

    public static int subtract(int a, int b) {
    
    
        return a - b;
    }

    public static int multiply(int a, int b) {
    
    
        return a * b;
    }

    public static double divide(int a, int b) {
    
    
        if (b == 0) {
    
    
            throw new IllegalArgumentException("除数不能为零");
        }
        return (double) a / b;
    }
}

In other classes, static methods can be called directly by the name of the tool class without creating an instance:

public class Main {
    
    
    public static void main(String[] args) {
    
    
        int sum = MathUtils.add(5, 10);
        System.out.println(sum); // 输出:15

        int difference = MathUtils.subtract(10, 5);
        System.out.println(difference); // 输出:5
    }
}

The usage scenarios of tools include:

  1. Encapsulate common static methods for use and reuse across multiple classes and modules.
  2. Provide some convenient methods to simplify operations and improve code readability and simplicity.
  3. Perform some functional operations without maintaining state, such as math operations, string processing, date conversion, etc.

It should be noted that although tool classes can conveniently use and reuse static methods, excessive use of tool classes may lead to increased code coupling. Therefore, when designing and using utility classes, you need to carefully weigh the pros and cons, and consider whether you need to create an instance and whether you need to rely on the instance state.

(5) Precautions for static

In Java, staticstatic members can be defined using keywords, including static variables and static methods. Static members are associated with the class, not with an instance of the class. Here are staticsome notes on usage:

  1. static variable:

    • Static variables belong to the class, not the instance of the class. They have only one copy in memory.
    • Static variables are initialized when the class is loaded and can be used in any method or constructor of the class.
    • Static variables can be accessed directly through the class name without creating an instance of the class.
  2. static method:

    • Static methods belong to the class, not to the instance of the class. They cannot access non-static members, only static members.
    • Static methods can be called directly by the class name without creating an instance of the class.
    • Static methods cannot be overridden by subclasses, but can be hidden by subclasses.
  3. static block:

    • A static block is statica block of code declared with a keyword that is used for initialization of static members of a class.
    • Static blocks are executed when the class is loaded, and only once.

Here are some considerations when using static members:

  • Static members can be used in both static and non-static methods, but non-static members can only be used in non-static methods.
  • Static methods cannot access non-static members, because static methods exist before the object is created, and non-static members are allocated memory after the object is created.
  • Keywords cannot be used in static methods this, because thiskeywords point to the current object, and static methods do not have a reference to the current object.
  • Static methods cannot be declared as abstract, because abstractmethods are methods that need to be implemented by subclasses, and static methods cannot be overridden by subclasses.

In short, using static members and static methods can conveniently access and call members of a class without creating an instance. However, you need to pay attention to the usage scenarios of static members and static methods, and ensure that they are used reasonably to avoid cluttering the code and unnecessary coupling.

Second, inheritance

(1) Overview of inheritance

Inheritance in Java is an important concept of object-oriented programming, which allows a class to inherit the properties and methods of another class. Inheritance relationship forms a parent-child relationship between classes, where one class is called the parent class or super class and the other class is called the child class or derived class.

The main purpose of inheritance is to achieve code reuse and hierarchical organization, which provides the following key features:

  1. Inheritance attributes: subclasses can inherit the attributes and methods of the parent class, including member variables and non-private methods. This means that subclasses can directly access the member variables and methods of the parent class without redefinition.

  2. Method Overriding: Subclasses can redefine or override methods inherited from parent classes. When a subclass overrides a method of the parent class, the method in the subclass overrides the method in the parent class. Through method rewriting, subclasses can modify or extend the implementation of parent class methods according to their own needs.

  3. Single inheritance: Java only supports single inheritance, that is, a class can only inherit from one parent class. Such a design can avoid the complexity and potential conflicts that multiple inheritance may bring.

  4. Multi-level inheritance: There can be a multi-level inheritance relationship between classes, that is, one class can be a subclass of another class, and it can also be the parent class of other classes. Multilevel inheritance allows building more complex class hierarchies.

Note the following points:

  • Private member variables and private methods cannot be inherited.
  • Subclasses can superaccess the constructors and members of the parent class by using keywords.
  • Subclasses can add new member variables and methods.
  • Subclass access modifiers cannot be more restrictive than parent classes.

Inheritance is one of the important tools for code reuse and organization in Java. Through inheritance, existing classes can be extended and customized without duplicating code, and code can be better organized and managed.

(2) Characteristics of inheritance

Java inheritance has the following characteristics:

  1. Single inheritance: A class in Java can only inherit from one parent class, that is to say, a class can only have one direct parent class. This is to avoid the complexity and conflicts that multiple inheritance can bring. However, a class can implement multiple interfaces, and the class that implements the interface can obtain the functions of multiple interfaces.

  2. Non-private members of the parent class can be accessed by subclasses: subclasses can inherit non-private member variables and non-private methods of the parent class, including attributes and methods. This means that subclasses can directly access the member variables and methods of the parent class without redefinition.

  3. Inheritance is a hierarchical relationship: through inheritance, a parent-child relationship between classes can be formed, where one class (subclass) inherits the properties and methods of another class (parent class). Such a hierarchical relationship can establish a complex class structure, which is convenient for code management and organization.

  4. Subclasses can override parent class methods: Subclasses can redefine or override methods inherited from parent classes. When a subclass overrides a method of the parent class, the method in the subclass overrides the method in the parent class. Through method rewriting, subclasses can modify or extend the implementation of parent class methods according to their own needs.

  5. Subclasses can add new member variables and methods: Subclasses can add their own member variables and methods on the basis of inheriting the parent class. This allows the child class to have more functionality and features than the parent class.

  6. Subclass access modifiers cannot be more restrictive than parent classes: subclasses can have access modifiers that are the same as or looser than those of the parent class, but cannot be stricter than those of the parent class. In other words, if a method is declared public in the parent class, when the method is overridden in the subclass, it can only be declared public, not private or protected.

Inheritance is one of the important features of Java object-oriented programming. Through inheritance, code reuse and hierarchical organization can be realized, which improves the flexibility and maintainability of the code.

(3) Design of inheritance system

Java's inheritance system is constructed through the inheritance relationship between classes and classes. In Java, all classes inherit directly or indirectly from the Object class, which is the root class of the Java inheritance system.

Java's inheritance system designs some basic classes, such as Object class, Number class, and Throwable class. These basic classes are the basis of other classes, and they provide some common functions and attributes for inheritance and use by other classes.

In Java, class inheritance can be achieved through the keyword "extends". A subclass can inherit the properties and methods of a parent class, and can be rewritten and extended as needed. In the inheritance system, a class can have one or more subclasses, and a parent class can have one or more subclasses, forming a hierarchical relationship.

Designing a good inheritance system should follow the following principles:

  1. Single Responsibility Principle: Each class should have its own responsibilities and functions, and is only responsible for completing its own responsibilities. Through inheritance, the common responsibilities and functions of the class can be extracted to the parent class to avoid duplication and redundancy of code.

  2. The principle of opening and closing: the inheritance system should be extensible, that is, new subclasses can be easily added without modifying the existing parent class. In this way, the function extension of the inheritance system can be realized without destroying the original code.

  3. Liskov Substitution Principle: Subclasses should be able to completely replace the parent class, and new functions can be added without affecting the original functions. When a subclass inherits from a parent class, it should maintain consistency and compatibility without changing the behavior of the parent class.

  4. Interface Segregation Principle: Interfaces should be independent, and each interface should meet specific requirements. Polymorphism can be achieved through interface inheritance, which improves the scalability and flexibility of the code.

The design of the inheritance system should be based on specific requirements and business logic. A reasonable inheritance relationship can improve the readability and maintainability of the code, and reduce the complexity and coupling of the code.

(4) Subclasses can inherit the contents of the parent class

In Java, a subclass can inherit the following from a parent class:

  1. Member variables: Subclasses can inherit the member variables of the parent class, and can use these member variables directly.

  2. Methods: Subclasses can inherit the methods of the parent class and can call these methods directly. If the subclass needs to modify or extend the method of the parent class, it can be achieved by rewriting the method.

  3. Construction method: The subclass can inherit the construction method of the parent class, and can call the construction method of the parent class through the super keyword to initialize the properties of the parent class.

  4. Inner class: Subclasses can inherit the inner class of the parent class, and can create objects of the inner class.

  5. Interface: Subclasses can implement the interface of the parent class and need to implement all the methods defined in the interface.

It should be noted that the subclass can only inherit the non-private members of the parent class, that is, the member variables and methods modified by private in the parent class cannot be inherited and accessed by the subclass.

In addition, subclasses can also use the super keyword to access member variables and methods in the parent class, and call the constructor of the parent class. The super keyword can be used in subclasses to refer to members of the parent class.

The purpose of inheritance is to achieve code reuse and extension. Through inheritance, you can avoid repeating the same code, and you can extend the function of the inheritance system without modifying the parent class.

(5) Access characteristics of member variables and member methods in inheritance

In Java, the access characteristics of member variables and member methods in inheritance are as follows:

  1. Access characteristics of member variables:

    • Subclasses can inherit the member variables of the parent class, including private, protected, default and public access member variables.
    • If there is a member variable with the same name as the parent class in the subclass, the subclass will hide the member variables of the parent class, and the subclass can only access its own member variables. You can use the super keyword to access member variables of the parent class.
    • Subclasses can use the member variables of the parent class through inheritance without redefinition.
  2. Access characteristics of member methods:

    • Subclasses can inherit the member methods of the parent class, including private, protected, default, and public access methods.
    • If there is a member method with the same name as the parent class in the subclass, the subclass will override the method of the parent class, and the method of the subclass will be called. You can use the super keyword to call the method of the parent class.
    • Subclasses can use the member methods of the parent class through inheritance without redefinition.

It should be noted that if the member variables or member methods in the parent class are declared as private, the subclass cannot directly access these members. This is because private members are only accessible within the class in which they are declared and are not inherited by subclasses.

The inherited access feature allows subclasses to directly use the member variables and member methods of the parent class, improving code reusability and maintainability. At the same time, subclasses can rewrite or extend the member methods of the parent class as needed to achieve their own specific functions.

(6) Constructors and this super keyword in inheritance

In Java, constructors and this, super keywords play an important role in inheritance.

Constructor inheritance:

  • By default, the subclass will call the no-argument constructor of the parent class. If the parent class does not have a no-argument constructor, the subclass must use the super keyword to explicitly call the constructor of the parent class.
  • Subclasses can use the super keyword to call a specific constructor of the parent class to pass parameters or perform specific initialization operations.
  • The first line of the construction method of the subclass must be a call to the construction method of the parent class. If there is no explicit call, the no-argument construction method of the parent class will be automatically called.

this keyword:

  • The this keyword represents the current object, and is often used in the construction method to distinguish the case where the member variable and the local variable have the same name.
  • If there is a member variable or member method with the same name as the parent class in the subclass, you can use the this keyword to distinguish and access the members of the subclass itself.
  • In the construction method of the subclass, you can use the this keyword to call other construction methods of this class to realize the overloading of the construction method.

super keyword:

  • The super keyword represents the parent class object, and the super keyword can be used in the subclass to access the member variables and member methods of the parent class.
  • In the construction method of the subclass, the super keyword can be used to call the construction method of the parent class to initialize the member variables inherited from the parent class.
  • The super keyword must be called on the first line of the constructor and can only be called once.

Through the inheritance of the construction method and the use of this and super keywords, the construction method of the parent class can be called in the subclass to realize the initialization of the members of the parent class. In this way, the initialization code of the parent class can be avoided from being repeatedly written in the subclass, and the reusability of the code is improved. At the same time, the this and super keywords can also easily solve the problem of member variable and method name conflicts.

Three, polymorphism

(1) Overview of polymorphism

Java polymorphism is an important feature of object-oriented programming, which allows us to refer to objects of its subclass through a reference of a parent class type. Polymorphism can improve code flexibility and maintainability.

In Java, polymorphism can be achieved in two ways:

  1. Inheritance and rewriting (method rewriting): When a subclass inherits from a parent class and rewrites the method of the parent class, we can use the reference of the parent class type to refer to the object of the subclass and call the overridden method . The advantage of this is that we can dynamically decide which subclass object to use at runtime without caring about the specific subclass type.

  2. Interface and Implementation: When a class implements an interface, we can refer to objects of that class using a reference of the interface type. The advantage of this is that we can call the methods defined in the interface through the interface type reference without caring about the specific class type.

The benefits of polymorphism include:

  1. Simplify code: By using polymorphism, we can use references of parent class type to refer to objects of different subclasses, thereby simplifying code and reducing duplication of code.

  2. Improve code maintainability: Using polymorphism can make code more flexible, easy to expand and maintain. When we need to add new subclasses, we only need to ensure that they implement the corresponding parent class or interface, and rewrite the methods in the parent class or interface.

  3. Implement code replaceability: Polymorphism makes code more replaceable, and different objects can be dynamically replaced at runtime to achieve different behaviors.

It should be noted that polymorphism is only applicable to methods defined in parent classes or interfaces, and methods or properties newly added in subclasses cannot be accessed through polymorphism. If we want to use subclass-specific methods or properties, we need to use downcasting (type conversion) to access. In addition, polymorphism is only applicable to instance methods (non-static methods), static methods and private methods do not support polymorphism.

(2) The characteristics of calling members in polymorphism

In Java's polymorphism, the invocation of members (methods and properties) has the following characteristics:

  1. Member calls are based on the reference type, not the actual object type. When an object calls a member through a parent class reference, Java determines the method or property to call at compile time based on the reference type, not the actual object type.

  2. For member method calls, the method to be executed will be determined according to the actual object type. If the method of the parent class is overridden in the subclass, when the method is called through the reference of the parent class, the method in the subclass will be executed. This process is called dynamic binding or runtime binding.

  3. For member attribute access, the attribute to be accessed will be determined according to the reference type. Regardless of whether the subclass overrides the properties of the parent class, only the properties of the parent class can be accessed through the parent class reference.

  4. For static members (methods or properties), regardless of the reference type and the actual object type, the reference type determines which static member to call or access. Static members are not polymorphic.

It should be noted that polymorphism calls to methods are determined dynamically at runtime, that is, which method to call is determined at runtime based on the object type. This dynamic binding feature makes polymorphism very flexible and powerful in practical applications.

(3) Advantages and disadvantages of polymorphism

Java polymorphism has the following advantages:

  1. Flexibility: Polymorphism allows an object to have multiple forms, and different types of objects can be used according to the needs of the context, thereby improving the flexibility and scalability of the code.

  2. Substitutability: Polymorphism enables objects to be replaced by their subclass objects, which enables code reuse and replacement, and simplifies code writing and maintenance.

  3. Extensibility: Through the mechanism of inheritance and polymorphism, new subclasses can be easily added to extend existing functions without modifying existing codes.

  4. Application of interfaces and abstract classes: Polymorphism is often used in combination with interfaces and abstract classes. Unified methods and properties can be defined through interfaces and abstract classes to achieve code modularization and decoupling.

However, polymorphism also has some disadvantages:

  1. Performance loss: Dynamic binding is required at runtime, which will bring a certain performance loss. Compared with directly calling the object's method, polymorphism requires a layer of indirection, resulting in a slight decrease in performance.

  2. Reduced readability: When using polymorphism in code, more thinking and understanding of the code is required, because the specific methods and properties are determined at runtime, which may increase the complexity and readability of the code reduce.

  3. Difficult to troubleshoot: Due to the polymorphic nature, when an error occurs, it may be necessary to trace the implementation code of multiple subclasses, which increases the difficulty of troubleshooting.

In general, polymorphism has great advantages in improving code flexibility and scalability, but may have some disadvantages in terms of performance and readability. In practical applications, it is necessary to weigh the pros and cons according to the specific situation and use polymorphism reasonably.

(4) Polymorphic comprehensive exercises

1. Requirements part

Complete the code as required

(1) Define the dog class

Attributes: age, color
Behavior: eat(String something) (something means something to eat), housekeeping lookHome method (no parameters)

(2) Define the cat class

Attributes: age, color
Behavior: eat(String something) method (something means something to eat), catch mouse catchMouse method (no parameters)

(3) Define the Person class//breeder

Attributes: name, age
Behavior: keepPet(Dog dog,String something) method
Function: feed the pet dog, something means the feeding thing

Behavior: keepPet(Cat cat, String something) method
Function: Feed the pet cat, something represents the feeding thing

Generate empty-parameter and parameter-constructed, set and get methods

(4) Define the test class (complete the following printing effects)

keepPet(Dog dog,String somethind)方法打印内容如下:
年龄为30岁的张三养了一只黑颜色的2岁的狗~
2岁黑颜色的狗前腿抱住骨头猛啃~

keepPet(Cat cat,String somethind)方法打印内容如下:
年龄为25岁的李四养了一只灰颜色的3岁的猫~
3岁灰颜色的猫眯侧着头吃鱼~

think

1. Both Dog and Cat are subclasses of Animal. In the above cases, different keepPet methods are defined for different animals, which is too cumbersome. Can you simplify it and experience the benefits of the simplification?

2. Although both Dog and Cat are subclasses of Animal, they both have their unique methods. Can you find a way to call the unique methods in keepPet?

2. Implementation part

(1) Write the dog class

The following is a sample code for defining a dog class in Java:

package net.army.java.jicheng;

/**
 * 功能:狗类
 * 日期:2023年09月03日
 * 作者:梁辰兴
 */
public class Dog {
    
    
    // 属性
    private int age;
    private String color;

    // 构造方法
    public Dog(int age, String color) {
    
    
        this.age = age;
        this.color = color;
    }

    // 行为:吃东西
    public void eat(String something) {
    
    
        System.out.println(getAge() + "岁"+ getColor() + "颜色的狗前腿抱住" + something + "猛啃~");
    }

    // 行为:看家
    public void lookHome() {
    
    
        System.out.println(getAge() + "岁"+ getColor() + "颜色的狗正在看家~");
    }

    // Getter和Setter方法
    public int getAge() {
    
    
        return age;
    }

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

    public String getColor() {
    
    
        return color;
    }

    public void setColor(String color) {
    
    
        this.color = color;
    }
}

In the above code, a dog class (Dog) is defined, which contains two attributes (age and color) and two behaviors (eating and housekeeping). The constructor is used to initialize the dog's age and color. The eat method accepts a parameter of type String indicating what to eat, and prints out what the dog is eating. The housekeeping method takes no parameters and just prints out that the dog is watching the house.

Additionally, in order to access and set dog properties, corresponding Getter and Setter methods are provided. This way the dog's age and color can be obtained and modified by calling these methods.

(2) Write the cat class

The following is a sample code for defining a cat class in Java:

package net.army.java.jicheng;

/**
 * 功能:猫类
 * 日期:2023年09月03日
 * 作者:梁辰兴
 */
public class Cat {
    
    
    // 属性
    private int age;
    private String color;

    // 构造方法
    public Cat(int age, String color) {
    
    
        this.age = age;
        this.color = color;
    }

    // 行为:吃东西
    public void eat(String something) {
    
    
        System.out.println(getAge() + "岁"+ getColor() +"颜色的猫眯侧着头吃" + something + "~");
    }

    // 行为:逮老鼠
    public void catchMouse() {
    
    
        System.out.println(getAge() + "岁"+ getColor() +"颜色的猫正在抓老鼠~");
    }

    // Getter和Setter方法
    public int getAge() {
    
    
        return age;
    }

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

    public String getColor() {
    
    
        return color;
    }

    public void setColor(String color) {
    
    
        this.color = color;
    }
}

In the above code, a cat class (Cat) is defined, which contains two attributes (age and color) and two behaviors (eating and catching mice). The constructor is used to initialize the age and color of the cat. The eat method accepts a parameter of type String indicating what to eat, and prints out what the cat is eating. The mouse method takes no arguments and just prints that the cat is catching a mouse.

In addition, in order to access and set the properties of cats, corresponding Getter and Setter methods are provided. This allows the cat's age and color to be obtained and modified by calling these methods.

(3) Write the Person class

The following is the sample code for defining the Person class in Java:

package net.army.java.jicheng;

/**
 * 功能:饲养员类
 * 日期:2023年09月03日
 * 作者:梁辰兴
 */
public class Person {
    
    
    // 属性
    private String name;
    private int age;

    // 空参构造方法
    public Person() {
    
    
    }

    // 有参构造方法
    public Person(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }

    // 行为:喂养狗
    public void keepPet(Dog dog, String something) {
    
    
        System.out.println("年龄为" + getAge() + "岁的" + getName() + "养了一只" + dog.getColor() + "颜色的" + dog.getAge() + "岁的狗~");
        dog.eat(something);
    }

    // 行为:喂养猫
    public void keepPet(Cat cat, String something) {
    
    
        System.out.println("年龄为" + getAge() + "岁的" + getName() + "养了一只" + cat.getColor() + "颜色的" + cat.getAge() + "岁的猫~");
        cat.eat(something);
    }

    // Getter和Setter方法
    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;
    }
}

In the above code, a Person class is defined to represent the breeder. The class contains two attributes (name and age) and two behaviors (feed the dog and feed the cat). The empty parameter construction method is used to pass in no parameters when creating a Person object, and the parameter construction method is used to pass in name and age when creating a Person object.

(4) Write the test class and output the result

The following is a sample code that defines a test class and achieves the above printing effect:

package net.army.java.jicheng;

/**
 * 功能:测试类
 * 日期:2023年09月03日
 * 作者:梁辰兴
 */
public class Test {
    
    
    public static void main(String[] args) {
    
    
        // 创建Person对象
        Person person1 = new Person("张三", 30);
        Person person2 = new Person("李四", 25);

        // 创建宠物狗
        Dog dog = new Dog(2, "黑");

        // 创建宠物猫
        Cat cat = new Cat(3, "灰");

        // 喂养狗
        person1.keepPet(dog, "骨头");
        //

        // 喂养猫
        person2.keepPet(cat, "鱼");
    }
}

In the above example, two Person objects are first created, namely "Zhang San" and "Li Si", and their ages are set respectively. Then create a pet dog and a pet cat. Then call the behavior methods of feeding the dog and feeding the cat of the two Person objects, and pass in the corresponding pets and food. According to the requirements, the relevant information of feeding dogs and feeding cats is printed separately. Running this test class will output the following:

insert image description here

Four, package and final

In Java, package and final keyword are two important concepts.

Package (Package):

  • Package is a mechanism for organizing and managing classes and interfaces. It can put related classes and interfaces together for easy management and use.
  • Packages are declared using the package keyword and exist as folders in the file system. The package name generally adopts the inverted domain name format to ensure uniqueness.
  • Packages can have a multi-level structure, use "." as the level separator.
  • The role of the package is to provide a namespace for classes to prevent conflicts between class names in different packages.
  • In Java, to use classes in other packages, you need to use the import keyword to introduce them.

final keyword:

  • The final keyword can be used to modify classes, methods, and variables, and has different effects.
  • When a class is decorated with final, the class cannot be inherited, that is, it is the final class.
  • When a method is decorated with final, the method cannot be overridden by subclasses, that is, it is a final method.
  • When a variable is modified with final, the variable is called a constant, and once assigned, it cannot be changed.
  • Final modified variables must be initialized at the time of declaration or in the constructor, and can only be assigned once.
  • The final keyword can also be used to modify parameters, indicating that the parameters are read-only and cannot be modified in the method.

Using packages and the final keyword can make the code more organized and stable. Packages can organize related classes and interfaces together for easy management and use. The final keyword can limit the use of classes, methods, and variables, improving program security and stability.

Five, abstract classes and abstract methods

In Java, abstract classes and abstract methods are important concepts used to implement abstraction and inheritance mechanisms in object-oriented programming.

Abstract class (Abstract Class):

  • An abstract class is a class that cannot be instantiated and is used as a base class or parent class for other classes.
  • An abstract class is declared using the abstract keyword and can contain both abstract and non-abstract methods.
  • An abstract class can have a constructor, but it cannot be instantiated directly, and can only be inherited and instantiated by its subclasses.
  • An abstract class can contain member variables and member methods, and can have access modifiers and other modifiers.
  • A subclass of an abstract class must implement all of its abstract methods, otherwise the subclass must also be declared as an abstract class.

Abstract Method:

  • An abstract method is a method without a method body, only the method's declaration and return type.
  • Abstract methods are declared using the abstract keyword and must be in an abstract class.
  • The concrete implementation of the abstract method is done by the subclass, and the subclass must implement all its abstract methods.
  • An abstract method can have parameters and a return type, but cannot have a method body.

The main purpose of abstract classes and abstract methods is to implement abstraction and inheritance mechanisms in object-oriented programming.

  • An abstract class defines a template of a base class or parent class, which specifies the methods that subclasses need to implement.
  • The abstract method defines the method that the subclass must implement, and the specific implementation is done by the subclass.
  • Abstract classes and abstract methods can provide a standardized interface and behavior, so that multiple subclasses can implement specific logic according to their own needs.

By using abstract classes and abstract methods, code reusability, flexibility, and scalability can be achieved, and code maintainability and readability can be improved.

Six, interface

(1) Overview of the interface

In Java, an interface (Interface) is a special reference type used to define a collection of abstract methods and constants. Interfaces can be implemented by classes (implements) or inherited by other interfaces (extends).

The characteristics and functions of the interface include:

  • An interface is an abstract data type that only defines the signature of a method and does not contain a concrete implementation.
  • Interfaces can define constants, and constants are public static final by default.
  • An interface can be implemented by multiple classes, and a class can implement multiple interfaces (multiple inheritance).
  • The relationship between an interface and a class is an implementation relationship. When a class implements an interface, it must implement all the methods in the interface.
  • Interfaces can inherit other interfaces, and the extension and hierarchical relationship of interfaces can be realized through interface inheritance.
  • Interfaces can be used as parameter types of methods, return value types, or used to instantiate objects.

The main role of the interface is to achieve polymorphism, decoupling and code maintainability.

  • Polymorphism: Through the interface, a group of methods with the same method signature can be defined. When different classes implement the interface, the specific implementation can be different, and the unified call to different objects can be realized.
  • Decoupling: Through the interface, the declaration and implementation of the method can be separated, which realizes the decoupling between classes and improves the flexibility and reusability of the code.
  • Maintainability: Standardized methods and behaviors can be defined through interfaces, making the code more standardized, easy to maintain and modify.

It should be noted that the methods in the interface are public and abstract by default, and these modifiers can be omitted. In Java 8 and later versions, default methods and static methods can also be defined in interfaces.

All in all, an interface is a specification and contract that defines a collection of methods and constants. By implementing interfaces, polymorphism and decoupling can be achieved, and code maintainability and scalability can be improved.

(2) Details of the interface: various relationships between member characteristics and interfaces

Member characteristics of a Java interface include:

  1. Method: A method in an interface is abstract and has no method body. The methods in the interface are public and abstract by default, and these modifiers can be omitted. In Java 8 and later versions, default methods (default method) and static methods (static method) can also be defined in the interface.

  2. Constants: Constants can be defined in the interface, and the constants are public static final by default. Constants in an interface must be initialized and can only be accessed within the interface.

  3. Default method (default method): The default method can be defined in the interface and modified with the default keyword. The default method has a method body and can be called directly or overridden in the implementing class. The purpose of the default method is that in the new version of the interface, new methods can be added to the interface without breaking the existing implementation class.

  4. Static method (static method): Static methods can be defined in the interface and modified with the static keyword. Static methods can only be called in interfaces and cannot be inherited or overridden by implementing classes.

The various relationships of a Java interface include:

  1. A class implements an interface: A class can implement one or more interfaces through the implements keyword. A class that implements an interface must implement all abstract methods in the interface, and can optionally override default methods.

  2. Interface inherits interface: An interface can inherit one or more interfaces through the extends keyword. When an interface inherits an interface, the subinterface inherits all the methods and constants of the parent interface, and new abstract methods can be added.

  3. The relationship between interfaces and classes: Interfaces cannot be instantiated directly, and a class needs to be used to implement the interface. A class can implement multiple interfaces, and the class implementing the interface must implement all the abstract methods in the interface.

  4. The relationship between interfaces and interfaces: an interface can inherit one or more interfaces, sub-interfaces inherit all the methods and constants of the parent interface, and can add new abstract methods.

  5. The relationship between classes and classes: Interfaces can establish associations between classes, and implementing classes implement the interfaces to have the behaviors defined in the interfaces. This relationship is called the implementation relationship between the interface and the class.

It should be noted that the relationship between interfaces and classes is an implementation relationship, not an inheritance relationship. Although interfaces can inherit other interfaces, interfaces do not inherit the implementation of the parent interface.

(3) Comprehensive case of interface and abstract class

The following is a comprehensive case of Java interface and abstract class, which demonstrates how to use interface and abstract class to define a simple car class and its subclasses.

First, we define an interface Vehicle, which contains an abstract method move():

public interface Vehicle {
    
    
    void move();
}

Next, we define an abstract class Carthat implements Vehiclethe interface and implements move()the methods in it:

public abstract class Car implements Vehicle {
    
    
    protected String brand;
    protected int speed;

    public Car(String brand, int speed) {
    
    
        this.brand = brand;
        this.speed = speed;
    }

    public void setBrand(String brand) {
    
    
        this.brand = brand;
    }

    public void setSpeed(int speed) {
    
    
        this.speed = speed;
    }

    public String getBrand() {
    
    
        return brand;
    }

    public int getSpeed() {
    
    
        return speed;
    }

    @Override
    public void move() {
    
    
        System.out.println(brand + " is moving at a speed of " + speed + " km/h.");
    }
}

In Carthe class, we define some properties and methods, including brand, speed, methods to set and get brand and speed. Additionally, we implemented move()methods to output the make and speed of the car. Note that Carthe class is an abstract class, so it cannot be instantiated directly.

Next, we define a concrete car class Benz, which inherits from Carthe class and implements move()the method:

public class Benz extends Car {
    
    
    public Benz(String brand, int speed) {
    
    
        super(brand, speed);
    }

    @Override
    public void move() {
    
    
        System.out.println("The Benz is moving at a speed of " + getSpeed() + " km/h.");
    }
}

In Benzthe class, we override move()the method and call getSpeed()the method of the parent class to get the speed information. Note that since Carthe class already implements the method Vehicleof the interface move(), we don't need to Benzimplement the method again in the class.

Finally, we write a test class to demonstrate how to use these classes:

public class Test {
    
    
    public static void main(String[] args) {
    
    
        Vehicle vehicle = new Benz("Benz", 120);
        vehicle.move();
    }
}

In the test class, we first create an Benzobject and assign it to a Vehiclevariable of type. We then call move()a method on that variable that outputs the make and speed of the car. Since Benza class inherits from Cara class and implements the methods Vehicleof the interface move(), we can Benzassign an object to a Vehiclevariable of a type and call its move()method.

(4) New methods in the interface, interface application and adapter design patterns

When a new method is added to a Java interface, it will have an impact on the class that has implemented the interface. Before Java 8, adding a new method to an interface would cause all classes implementing the interface to implement the new method, otherwise an error would be reported when compiling. This may cause existing code to need to be modified, which may cause some trouble.

However, the concept of default method (Default Method) was introduced in Java 8, so that when a new method is added to the interface, a default implementation can be provided, so that the implementation class only needs to focus on its own specific implementation logic, without forcing the implementation of the newly added method. If the implementing class requires a custom implementation, the default implementation can be overridden.

The application of the interface is related to the adapter design pattern. Adapter design pattern is a structural design pattern used to solve the problem of interface incompatibility. When a class needs to implement an interface, but only cares about some of its methods, the adapter pattern can be used. The adapter class implements the interface and provides a default implementation, and then this class can be inherited or used by other classes, so that only the methods of interest need to be implemented, instead of all methods.

For example, suppose there is an interface Animal, which defines a series of animal behavior methods, such as eat(), run(), and so on. Now we have added a method fly(), but not every animal can fly. We can define an adapter class AnimalAdapter, implement the Animal interface and provide a default implementation, where the default implementation of the fly() method is empty. Then, specific animal classes can selectively inherit the AnimalAdapter class, and only need to override the methods they care about.

In this way, when we need to use the flying behavior of animals, we can directly use the Animal interface and call the fly() method. For non-flying animals, since the adapter provides a default implementation, there is no need to implement this method.

To sum up, the new methods in the interface may have an impact on the existing code, but the compatibility problem of the interface can be solved to a certain extent through the default method and the adapter design pattern.

Seven, inner class

(1) Overview of inner classes

A Java inner class is a class defined inside a class. Inner classes can access member variables and methods of outer classes, including private members, while outer classes cannot directly access members of inner classes.

There are several types of Java inner classes:

  1. Member inner class (Member Inner Class): Defined inside a class, as a member of the class, you can access all members of the outer class. Member inner classes can use public, protected, default, and private modifiers.

  2. Static inner class (Static Inner Class): defined inside a class, using static modification. A static inner class cannot directly access the non-static members of the outer class, but it can access the static members of the outer class.

  3. Method inner class (Local Inner Class): Defined inside a method as a local variable of the method. The method inner class can only be accessed inside the method, and can only access the final modified method local variables.

  4. Anonymous Inner Class (Anonymous Inner Class): An inner class without a name, usually used to implement an interface or inherit a parent class and override a method. Anonymous inner classes must be instantiated at the time of declaration and can only be used once.

The main advantages of inner classes include:

  • The inner class can access the private members of the outer class, providing a more flexible access method.
  • Internal classes can encapsulate external classes, hide internal implementation details, and improve code readability and maintainability.
  • Inner classes can implement multiple inheritance, and a class can implement multiple interfaces or inherit multiple classes at the same time.
  • The inner class can access the reference of the outer class, which can be used to implement functions such as event monitoring.

It should be noted that since the inner class has a dependency relationship with the outer class, when creating an instance of the inner class, an instance of the outer class needs to be created first. For example, if you want to create an instance of a member inner class, you need to create an instance of the outer class first, and use the instance of the outer class to create an instance of the inner class.

(2) Member inner class

Member Inner Class (Member Inner Class) is a class defined inside a class and used as a member of that class. A member inner class can access all member variables and methods of the outer class, including private members. Member inner classes can use public, protected, default, and private modifiers.

The member inner class is defined like this:

public class OuterClass {
    
    
    // 外部类成员变量和方法

    class InnerClass {
    
    
        // 内部类成员变量和方法
    }
}

When creating an instance of a member inner class in an outer class, you need to use an instance of the outer class to create it. For example:

OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();

It can be seen that when creating an instance of an inner class, an instance of the outer class needs to be created first, and an instance of the inner class is created through an instance of the outer class.

Members of the inner class and the outer class can access each other's members, including private members. For example, member variables and methods of the outer class can be directly accessed in the inner class:

public class OuterClass {
    
    
    private int outerVariable = 10;

    class InnerClass {
    
    
        public void printOuterVariable() {
    
    
            System.out.println("Outer variable: " + outerVariable);
        }
    }
}

In the outer class, members of the inner class can be accessed by creating an instance of the inner class:

OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
inner.printOuterVariable();

It should be noted that static members cannot be declared in the member inner class, because the instance of the member inner class depends on the instance of the outer class. If you need to use static members in an inner class, you can declare the inner class as a static inner class.

(3) Static inner class and local inner class

A static inner class (Static Inner Class) is a class defined inside a class and decorated with static. The static inner class is different from the ordinary member inner class, it can be accessed directly through the class name of the outer class, without first creating an instance of the outer class.

A static inner class is defined like this:

public class OuterClass {
    
    
    // 外部类成员变量和方法

    static class StaticInnerClass {
    
    
        // 静态内部类成员变量和方法
    }
}

When you create an instance of a static inner class in an outer class, you don't need to use an instance of the outer class to create it. For example:

OuterClass.StaticInnerClass inner = new OuterClass.StaticInnerClass();

As you can see, when creating an instance of a static inner class, there is no need to create an instance of the outer class first.

Static inner classes and outer classes cannot directly access each other's members, including private members. If you need to access members of an external class, you can do so by creating an instance of the external class. For example, accessing members of an outer class in a static inner class:

public class OuterClass {
    
    
    private static int outerVariable = 10;

    static class StaticInnerClass {
    
    
        public void printOuterVariable() {
    
    
            System.out.println("Outer variable: " + OuterClass.outerVariable);
        }
    }
}

In the outer class, you can directly access the members of the static inner class through the class name of the static inner class:

OuterClass.StaticInnerClass inner = new OuterClass.StaticInnerClass();
inner.printOuterVariable();

It should be noted that non-static members of the outer class cannot be accessed in the static inner class, because the instance of the static inner class has nothing to do with the instance of the outer class. If you need to access non-static members of the outer class, you can declare the inner class as a member inner class.

Local Inner Class (Local Inner Class) is a class defined inside a method. The scope of the local inner class is limited to the inside of the method, and the outside cannot directly access the local inner class. A local inner class can access members of the outer class, including private members.

A local inner class is defined as follows:

public class OuterClass {
    
    
    // 外部类成员变量和方法

    public void method() {
    
    
        class LocalInnerClass {
    
    
            // 局部内部类成员变量和方法
        }
    }
}

When an instance of a local inner class is created inside a method, it can only be created inside the method. For example:

public class OuterClass {
    
    
    public void method() {
    
    
        class LocalInnerClass {
    
    
            public void printMessage() {
    
    
                System.out.println("Hello from local inner class!");
            }
        }

        LocalInnerClass inner = new LocalInnerClass();
        inner.printMessage();
    }
}

The local inner class cannot be directly accessed in the outer class, but its members can be accessed inside the method by creating an instance of the local inner class.

It should be noted that static members cannot be declared in the local inner class, because the instance of the local inner class depends on the invocation of the method. If you need to use static members in a local inner class, you can declare the inner class as a static inner class.

(4) Anonymous inner class

An anonymous inner class (Anonymous Inner Class) is an inner class without a class name. It has no independent definition and structure, and is defined and instantiated directly at the place where the object is created.

Anonymous inner classes are often used to create instances of classes that only need to be used once, such as implementing an interface or inheriting an abstract class. Using anonymous inner classes can save the process of writing independent classes and make the code more concise.

An anonymous inner class is defined like this:

  • Anonymous inner class when implementing an interface:
interface MyInterface {
    
    
    void doSomething();
}

MyInterface obj = new MyInterface() {
    
    
    public void doSomething() {
    
    
        System.out.println("Doing something...");
    }
};

In the above example, an instance of the MyInterface interface is implemented through an anonymous inner class. When creating an instance, use a pair of braces directly after the interface name, and then override the interface's methods within the braces.

  • Anonymous inner class when inheriting abstract class:
abstract class MyAbstractClass {
    
    
    abstract void doSomething();
}

MyAbstractClass obj = new MyAbstractClass() {
    
    
    void doSomething() {
    
    
        System.out.println("Doing something...");
    }
};

In the above example, an instance of an abstract class is inherited through an anonymous inner class. When creating an instance, use a pair of braces directly after the abstract class name, and then override the abstract method of the abstract class in the braces.

It should be noted that an anonymous inner class cannot have a constructor because it has no class name. Also, static members and static methods cannot be defined in anonymous inner classes.

The advantage of using anonymous inner classes is that objects can be defined and instantiated directly where they are used, eliminating the need to write independent classes. But it should also be noted that since the anonymous inner class does not have an independent class name, an instance of the class cannot be reused elsewhere. If you need to use an instance of this class in multiple places, it is recommended to use an ordinary inner class or an independent class to implement it.

Guess you like

Origin blog.csdn.net/m0_62617719/article/details/132711901