Some thoughts on object-oriented

Knowledge points

  • Polymorphism
  • Inner class (mainly anonymous inner class writing and understanding)
  • Understanding the difficulties of object-oriented
  • Do you really understand the callback of the interface

One, polymorphism

Polymorphism, as the name implies, "one form, multiple states" is nothing more than saying nothing. In fact, what is polymorphism? It may be said that the subclass object holds a reference to the parent class or interface type and changes dynamically during the method call. Next is my understanding of polymorphism. . .

1. Occurrence conditions

1. Existence
2. Existence method rewriting
3. Parent class/interface refers to subclass object
ps: only methods are discussed, and there is no polymorphism in member variables.

2. Polymorphism

1. There is no polymorphism in the call of member fields.
2. The parent method A is private, and the subclass also has method A (regardless of any access rights). When the parent class refers to the call, the parent method A cannot be accessed (error at compile time), and At this time, the method A of the subclass is also not accessible. (Combined with the understanding of variable reference types)
3. The static method of the parent class is'hidden' to the subclass (refer to the following)

Can the static method of the parent class be overridden by the child class?
No:
1. Static methods and properties belong to the class. When calling them, they are done directly through the class name and method name, without the inheritance mechanism and can be called. If static methods and properties are defined in the subclass, then the static methods or properties of the parent class are called "hidden" (even if the static members and methods of the parent class are not private, the subclass also has the same static methods, the parent The class object reference cannot be called, and polymorphism cannot occur. Therefore, the static method of the parent class cannot be overridden by the child class. This is called hiding). If you want to call the static methods and properties of the parent class, directly pass the parent class name, method or variable name. As for whether to inherit, the subclass has inherited static methods and properties, but it is not the same as instance methods and properties. , There is a "hidden" situation.
2. Rewriting refers to deciding which method to call based on the type of the object at runtime, not based on the type at compile time.

3. Reference type of variable

Java reference variables have two types:
1. Compile-time type: determined by the type used when declaring the variable
2. Run-time type: determined by the object actually assigned to the variable

  Animal animal = new Fish();

As above:
1. Animal animal is a compile-time type. At this time, animal can only call accessible method fields in the Animal class.
2. Animal animal = new Fish. During the operation, the animal becomes the Fish type. At this time, when the overloaded method is called, polymorphism occurs, that is, the method of the subclass is called.

4. The call tree of the construction method

When a user uses a structure that calls a subclass, the system always calls the structure of the parent class first. And the first call is the structure of the java.lang.Object class (with no parameters by default)

Insert picture description here

As above, the construction of the top-level parent class will always be executed first, and then executed next (if the parent class contains constructions that call other parameter constructions, these constructions will be executed once, and finally initialized until the construction of the subclass.)

5. Method call tree in the case of polymorphism

Insert picture description here

6, perception

1. The initialization (construction) of the class is initialized from top to bottom.
2. When the parent class or interface refers to the calling method, it is called from bottom to top. Until the Object class is found.
3. The parent class or interface reference can only call the method covered by itself or the subclass, otherwise an error will be reported during compilation. (You can skip compile-time detection through reflection)

7. Simulate a question

Portal:
Answer: At the end of this article

2. Do you really understand the callback of the interface?

1. Preparation
public abstract class Animal {
    
    
    abstract void run();
}
-------------------------------------------
public class People extends Animal {
    
    
    @Override
    public void run() {
    
    
        System.out.println("我是people");
    }
}
----------------------------------------
public class Person extends People {
    
    

}
2. Chestnuts
package test1.interfacedemo;

/**
 * Create by SunnyDay on 2020/02/18 
 * ps:今天回顾整理与此
 */
public class MainTest {
    
    
    public static void main(String[] args) {
    
    
        // 接口回调栗子1:
        test(new Animal() {
    
    
            @Override
            void run() {
    
    
                System.out.println("接口回调栗子1:发送消息");
            }
        });
        /**
         * 栗子1解析:
         * 这种为常见的栗子:直接 new 接口或抽象类,实现要实现的方法。
         * 代码原理(相当于如下):
         *  Animal animal =  new Animal{
         *             @Override
         *             void run() {
         *                 System.out.println("接口回调栗子1:发送消息");
         *             }}
         *   1、代码左面Animal animal  就是test(Animal animal)
         *   2、代码右面相当于创建个Animal的子类,实现了run方法。
         *   3、test(Animal animal) 方法被调用时传入了个 Animal 子类对象
         *   4、这时开始执行 test()中的 animal.run(),根据多态机制。多态调用,去子类中寻找。
         *   5、由于我们传入的为new Animal{xxx}所以在这里寻找重写的方法加以调用
         * */

        // 接口回调栗子2:
        test(new Person() {
    
    
            @Override
            public void run() {
    
    
                System.out.println("接口回调栗子2:发送消息");
            }
        });
        /**
         * 栗子2解析:
         * 这种为常见的栗子:直接 new 接口或抽象类,实现要实现的方法。
         * 代码原理(相当于如下):
         *  Animal animal =  new Person{
         *             @Override
         *             void run() {
         *                 System.out.println("接口回调栗子2:发送消息");
         *             }}
         *   1、代码左面Animal animal  就是test(Animal animal)
         *   2、代码右面相当于创建个Person的子类,实现了run方法。
         *   3、test(Animal animal) 方法被调用时传入了个 Animal 子类对象(Person间接继承的Animal)
         *   4、这时开始执行 test()中的 animal.run(),根据多态机制。多态调用,去子类中寻找。
         *   5、由于我们传入的为new Person{xxx}所以在这里寻找重写的方法加以调用
         * */

        // 拓展栗子:
        /**
         * 拓展栗子解析:
         * 这种为常见的栗子:直接 new 接口或抽象类,实现要实现的方法。
         * 代码原理(相当于如下):
         *  Animal animal =  new Person(){
         *      
         *  }
         *
         *   1、代码左面Animal animal  就是test(Animal animal)
         *   2、代码右面相当于创建个Person的子类,实现了run方法。
         *   3、test(Animal animal) 方法被调用时传入了个 Animal 子类对象(Person间接继承的Animal)
         *   4、这时开始执行 test()中的 animal.run(),根据多态机制。多态调用,去子类中寻找重写的方法。
         *   5、由于我们传入的为new Person{}这个Person子类中没有重写所以,代用从父类中继承的run方法
         *   6、去Person类中寻找,一看没有。
         *   7、去People类中寻找,找到啦,调用。
         * */
        test(new Person(){
    
    });
    }

     /**
      * MainTest类的test方法
      * @param animal    超类接口引用
      * */
    public static void test(Animal animal) {
    
    
        animal.run();
        System.out.println("收到消息!!!");
    }
}


logcat:
接口回调栗子1:发送消息
收到消息!!!

接口回调栗子2:发送消息
收到消息!!!

我是people
收到消息!!!

Refer to the following for understanding:
1. Multi-station mechanism
2. Method invocation mechanism during polymorphic invocation
3. Use of anonymous internal classes

Two, internal class

1. Knowledge points

Insert picture description here

2. Code

Portal

2. Understanding of anonymous inner classes
/**
 * Created by sunnyDay on 2019/9/26 17:11
 * 匿名内部类栗子
 */
public class Test {
    
    
    public static void main(String[] args) {
    
    

         //1、 new 抽象类
        new Animal(){
    
    
            @Override
            void run() {
    
    
                System.out.println("1");
            }
        }.run();

        //2、 new 接口
        new MyInterface(){
    
    
            @Override
            public void doSome() {
    
    
                System.out.println("接口的实现");
            }
        }.doSome();

        //3、 new 普通类
       new Fish(){
    
    
           @Override
           void run() {
    
    
               System.out.println("2");
           }
       }.run();


       // demo
       class Person extends Animal{
    
    //继承方式
           @Override
           void run() {
    
    
               System.out.println("人可以走可以跑");
           }
       }

       Person person  = new Person();
    }
}

Writing method:
1. The new abstract class constructor implements abstract methods (directly with method body and realization in method body)
2. New interface, the method that realizes interface (directly with method body and realization in method body)
3. New of a common class Constructor, followed by method body.
The difference between the above three methods and inheritance (as in the above demo) or implementation of interface creation subclasses:
1. Both classes are local inner classes, but anonymous inner classes belong to "special local inner classes"
2. Local inner classes have class names, The anonymous inner class does not.

Reference article: Understanding JAVA internal classes

Third, the perception of object-oriented difficulties

1. Difficulties
  • Knowledge points of various internal classes.

Especially the new abstract class of the anonymous inner class, the understanding of the new interface form.

  • Polymorphism

    Combining with subclass and parent class, each member, method, code block (dynamic and static) initialization sequence understanding
    Combining with polymorphic concept understanding
    Combining with constructor call tree understanding
    Combining actual combat with interface callback understanding

Pay: answer
/**
 * Created by sunnyDay on 2019/9/20 16:03
 */
public class test {
    
    
    public static void main(String[] args) {
    
    
        Animal animal = new Fish();

        animal.test();
        animal.run(); // 访问成功,编译期间访问父类方法,发生多态,运行期间调用子类方法。
       // animal.te(); // 只会访问父类的,且访问失败(私有权限)
       //  animal.Bubble(); // 这里输出啥?-> // 调用不了 (对多态理解:编译器调用。即只能调用编译期间的成员,在运行期动态改变)

        try {
    
    

            Class clazz = animal.getClass();
            Method method = clazz.getMethod("Bubble", null);
            method.invoke(animal, null);   // 这里输出啥?-> // 反射 运行时 动态调用(相对上面跳过了编译期间的检测)

        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }
}

Guess you like

Origin blog.csdn.net/qq_38350635/article/details/101204524