• 纯虚函数和抽象类


    纯虚函数和抽象类

    定义

    注意抽象类不能创建对象,但是可以定义一个指针

    注意抽象类不能有任何成员结构, 成员函数必须协成纯虚函数,

    virtual 返回值  函数名(参数列表)=0

     注意

      含有纯虚函数的类被称为抽象类。抽象类只能作为派生类的基类,不能定义对象,但可以定义指针。在派生类实现该纯虚函数后,定义抽象类对象的指针,并指向或引用子类对象。

    1)在定义纯虚函数时,不能定义虚函数的实现部分;

    2)在没有重新定义这种纯虚函数之前,是不能调用这种函数的。

      抽象类的唯一用途是为派生类提供基类,纯虚函数的作用是作为派生类中的成员函数的基础,并实现动态多态性。继承于抽象类的派生类如果不能实现基类中所有的纯虚函数,那么这个派生类也就成了抽象类。因为它继承了基类的抽象函数,只要含有纯虚函数的类就是抽象类。纯虚函数已经在抽象类中定义了这个方法的声明,其它类中只能按照这个接口去实现。

    抽象类实例

    计算图形面积

    #include <iostream>
    
    using namespace std;
    
    // 重点
    // 面向抽象类编程(面向一套预先定义好的接口编程)
    // 解耦合。。模块的划分
    class Figure // 抽象类
    {
    public:
        // 约定一个统一的界面(接口) 让子类使用,让子类必须去实现
        virtual void getArea() = 0; // 纯虚函数
    protected:
    private:
    };
    
    class Circle : public Figure {
    public:
        Circle(int a, int b) {
            this->a = a;
            this->b = b;
        }
    
        virtual void getArea() {
            cout << "圆的面积	" << 3.14 * a * a << endl;
        }
    
    protected:
    private:
        int a;
        int b;
    };
    
    class Sanjiao : public Figure {
    public:
        Sanjiao(int a, int b) {
            this->a = a;
            this->b = b;
        }
    
        virtual void getArea() {
            cout << "三角形的面积	" << a * b / 2 << endl;
        }
    
    protected:
    private:
        int a;
        int b;
    };
    
    class Squre : public Figure {
    public:
        Squre(int a, int b) {
            this->a = a;
            this->b = b;
        }
    
        virtual void getArea() {
            cout << "四边形的面积	" << a * b << endl;
        }
    
    protected:
    private:
        int a;
        int b;
    };
    
    void PlayObj(Figure *base) {
        base->getArea(); // 会发生多态
    }
    
    int main() {
        // Figure f1; // 抽象类不能被实例化
        Figure *base = NULL;
        Circle c1(1, 2);
        Squre sq(1, 2);
        Sanjiao s1(2, 4);
    
    
        PlayObj(&c1);
        PlayObj(&s1);
        PlayObj(&sq);
    
        return 0;
    }
    抽象类编程例子一

    计算程序员工资

    忘记了手动调用delete,让其调用析构函数比较好

    第二个有点错误, 不能说是抽象类

    #include <iostream>
    using namespace std;
    
    /*
     编写一个c++程序 计算程序员工资(programer)
            1要求:能计算出初级程序员工资(junior_programer),中级程序员(mid_programer),高级程序员(Adv_progreamer)
            2要求利用抽象类统一界面(方便程序拓展),比如新增 计算架构师architect的工资
    */
    
    // 程序员抽象类
    class programer
    {
    public:
        virtual void getSal() = 0; //  抽象类接口
    };
    
    // 初级程序员
    class junior_programer: public programer
    {
    public:
        junior_programer(char *name, char *job, int sal) // 浅拷贝
        {
            this->name = name;
            this->job = job;
            this->sal = sal;
        }
        virtual void getSal() // 接口类实现
        {
            cout << "name = " << name << "	job = " << job << "	sal = " << sal << endl;
        }
    private:
        char *name;
        char *job;
        int sal;
    };
    
    // 中级程序员
    class mid_programer: public programer
    {
    public:
        mid_programer(char *name, char *job, int sal) // 浅拷贝
        {
            this->name = name;
            this->job = job;
            this->sal = sal;
        }
        virtual void getSal() // 接口类实现
        {
            cout << "name = " << name << "	job = " << job << "	sal = " << sal << endl;
        }
    private:
        char *name;
        char *job;
        int sal;
    };
    
    // 高级程序员
    class Adv_programer: public programer
    {
    public:
        Adv_programer(char *name, char *job, int sal) // 浅拷贝
        {
            this->name = name;
            this->job = job;
            this->sal = sal;
        }
        virtual void getSal() // 接口类实现
        {
            cout << "name = " << name << "	job = " << job << "	sal = " << sal << endl;
        }
    private:
        char *name;
        char *job;
        int sal;
    };
    
    // 后来增加的 架构师类
    class architect: public programer
    {
    public:
        architect(char *name, char *job, int sal) // 浅拷贝
        {
            this->name = name;
            this->job = job;
            this->sal = sal;
        }
        virtual void getSal() // 接口类实现
        {
            cout << "name = " << name << "	job = " << job << "	sal = " << sal << endl;
        }
    private:
        char *name;
        char *job;
        int sal;
    };
    
    // 计算函数,简单框架
    void jisuan(programer *base)
    {
        base->getSal();
    }
    
    // 引用
    void jisuan(programer &base)
    {
        base.getSal();
    }
    int main()
    {
        junior_programer junior("张三", "初级", 5000);
        mid_programer    mid("李四",    "中级", 10000);
        Adv_programer    adv("王五",    "高级", 15000);
    
        // 系统扩展 增加代码 架构师工资
        architect arc("康总", "架构师", 30000);
    
    
        jisuan(&junior);
        jisuan(&mid);
        jisuan(&adv);
    
        jisuan(&arc);
    
        cout << endl;
    
    
        // 引用类型
        auto &i = junior;
        auto &j = mid;
        auto &k = adv;
        auto &l = arc;
    
        jisuan(i);
        jisuan(j);
        jisuan(k);
        jisuan(l);
    
        return 0;
    }
    别人的的方式
    //编写一个c++程序 计算程序员工资(programer)
    //1要求:能计算出初级程序员工资(junior_programer),中级程序员(mid_programer),高级程序员(Adv_progreamer)
    //2要求利用抽象类统一界面(方便程序拓展),比如新增 计算架构师architect的工资
    
    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    // 定义程序员类, 抽象类
    class Programer {
        virtual double getSal() = 0;
    };
    
    class Junior : Programer {
    public:
        Junior(char *name = NULL, char *job = NULL, double sal = 7000) {
    
            auto len = strlen(name);
            this->name = new char[len + 1];
            strcpy(this->name, name);
    
            len = strlen(job);
            this->job = new char[len + 1];
            strcpy(this->job, job);
            this->sal = sal;
    
        }
    
        virtual ~Junior() {
            delete[]name;
            delete[]job;
            sal = 0;
            name = NULL;
            job = NULL;
            cout << "j" << endl;
        }
    
        virtual double getSal() {
            cout << this->name << " : " << this->job << ": " << this->sal << endl;
        }
    
    public:
        char *name;
        char *job;
        double sal;
    };
    
    class Mid : public Junior {
    public:
        Mid(char *name = NULL, char *job = NULL, double sal = 10000)
                : Junior(name, job, sal) {
    
        }
    
        virtual ~Mid()  // 会默认调用父类的析构函数
        {
            cout << "m" << endl;
        }
    };
    
    // 高级的
    class Adv : public Junior {
    public:
        Adv(char *name = NULL, char *job = NULL, double sal = 10000)
                : Junior(name, job, sal) {
    
        }
    
        virtual ~Adv()  // 会默认调用父类的析构函数
        {
            cout << "Adv" << endl;
        }
    };
    
    void print(Junior &obj) {
        obj.getSal();
    }
    
    
    int main() {
        Junior j("张三", "初级", 5000);
        Mid m("李四", "中级", 10000);
        Adv a("王五", "高级", 15000);
        print(j);
        print(m);
        print(a);
    
        return 0;
    }
    自己的另一种写法

    抽象类编程

    动物园类

    #if 0
    // main.cpp
    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    #include "Animal.h"
    #include "Dog.h"
    #include "Cat.h"
    #include "Dog.cpp"
    #include "Cat.cpp"
    #include "Animal.cpp"
    
    
    using namespace std;
    
    int main(void)
    {
        letAnimalCry(new Dog);
    
        letAnimalCry(new Cat);
    
    #if 0
        Animal *dog = new Dog;
        letAnimalCry(dog);
        delete Dog;
    #endif
    
        return 0;
    }
    #endif
    
    // --  Animal.h
    #if 0
    #pragma once
    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    using namespace std;
    
    class Animal
    {
    public:
        //纯虚函数,让子类继承并且实现
        virtual void voice() = 0;
        Animal();
        virtual ~Animal();
    };
    //架构函数
    //让动物叫
    void letAnimalCry(Animal *animal);
    #endif
    // Animal.cpp
    #if 0
    #include "Animal.h"
    
    inline
    Animal::Animal()
    {
        cout << "animal().." << endl;
    }
    inline
    Animal::~Animal()
    {
        cout << "~Animal()..." << endl;
    }
    inline
    void letAnimalCry(Animal *animal)
    {
        animal->voice();
    
        // 需要手动调用delete 让其调用析构函数
        if (animal != NULL) {
            delete animal;
        }
    }
    #endif
    
    // Dog.h------------------------
    #if 0
    #pragma once
    #include "Animal.h"
    class Dog : public Animal
    {
    public:
        Dog();
        ~Dog();
    
        virtual void voice();
    };
    #endif
    
    // Dog.cpp
    #if 0
    #include "Dog.h"
    
    inline
    Dog::Dog()
    {
        cout << "Dog().." << endl;
    }
    
    inline
    Dog::~Dog()
    {
        cout << "~Dog().." << endl;
    }
    inline
    void Dog::voice()
    {
        cout << "狗开始哭了, 555" << endl;
    }
    #endif
    
    // Cat.h
    #if 0
    #pragma once
    #include "Animal.h"
    
    
    class Cat : public Animal
    {
    public:
        Cat();
        ~Cat();
    
        virtual void voice();
    };
    #endif
    // Cat.cpp
    #if 0
    #include "Cat.h"
    
    inline
    Cat::Cat()
    {
        cout << "cat().." << endl;
    
    }
    
    inline
    Cat::~Cat()
    {
        cout << "~cat().." << endl;
    
    }
    inline
    void Cat::voice()
    {
        cout << "小猫开始哭了,66666" << endl;
    }
    #endif
    动物园

    电脑类实例:

    #define _CRT_SECURE_NO_WARNINGS
    
    #include <iostream>
    
    
    using namespace std;
    
    //--------  抽象层---------
    //抽象CPU类
    class CPU {
    public:
    //    CPU();
    
        virtual void caculate() = 0;
    };
    
    //抽象的card类
    class Card {
    public:
        virtual void display() = 0;
    };
    
    //抽象的内存类
    class Memory {
    public:
        virtual void storage() = 0;
    };
    
    //架构类
    class Computer {
    public:
        Computer(CPU *cpu, Card *card, Memory *mem) {
            this->cpu = cpu;
            this->card = card;
            this->mem = mem;
        }
    
        void work() {
            this->cpu->caculate();
            this->card->display();
            this->mem->storage();
        }
    
        ~Computer() {
            if (this->cpu != NULL) {
                cout << "~cpu" << endl;
                delete this->cpu;
            }
            if (this->card != NULL) {
                cout << "~card"<<endl;
                delete this->card;
            }
            if (this->mem != NULL) {
                cout << "~mem"<<endl;
                delete this->mem;
            }
        }
    
    private:
        CPU *cpu;
        Card *card;
        Memory *mem;
    };
    // --------------------------
    
    //-----------实现层----------
    //具体的IntelCPU
    class IntelCPU : public CPU {
    public:
        virtual void caculate() {
            cout << "Intel CPU开始计算了" << endl;
        }
    };
    
    class IntelCard : public Card {
    public:
        virtual void display() {
            cout << "Intel Card开始显示了" << endl;
    
        }
    };
    
    class IntelMem : public Memory {
    public:
        virtual void storage() {
            cout << "Intel mem开始存储了" << endl;
    
        }
    };
    
    class NvidiaCard : public Card {
    public:
        virtual void display() {
            cout << "Nvidia 显卡开始显示了" << endl;
        }
    };
    
    class KingstonMem : public Memory {
    public:
        virtual void storage() {
            cout << "KingstonMem 开始存储了" << endl;
        }
    };
    
    //--------------------------
    
    void test()
    {
        Computer *com1 = new Computer(new IntelCPU, new IntelCard, new IntelMem);
        com1->work();
        delete com1;    // 如果定义一个指针不要忘记释放
    
    }
    
    //--------业务层-------------------
    int main() {
        //1 组装第一台intel系列的电脑
    #if 0
        CPU *intelCpu = new IntelCPU;
        Card *intelCard = new IntelCard;
        Memory *intelMem = new IntelMem;
    
        Computer *com1 = new Computer(intelCpu, intelCard, intelMem);
    
        com1->work();
    
        Card *nCard = new NvidiaCard;
        Memory* kMem = new KingstonMem;
    
        Computer *com2 = new Computer(intelCpu, nCard, kMem);
    
        com2->work();
    
        delete intelCpu;
    #endif
    //    Computer *com1 = new Computer(new IntelCPU, new IntelCard, new IntelMem);
    //    com1->work();
    //    delete com1;   // 这里不要忘记释放
        test();
        return 0;
    }
    这个好好看看

     圆类

    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    
    
    using namespace std;
    
    
    //抽象的图形类
    class Shape
    {
    public:
        //打印出图形的基本你属性
        virtual void show() = 0;
        //得到图形的面积
        virtual double getArea() = 0;
    
        virtual ~Shape() {
    
        }
    };
    
    //圆类
    class Circle :public Shape
    {
    public:
        Circle(double r) {
            this->r = r;
        }
    
        //打印出图形的基本你属性
        virtual void show()  {
            cout << "圆的半径是 " << r << endl;
        }
        //得到图形的面积
        virtual double getArea()  {
            cout << "获取圆的面积" << endl;
            return this->r*this->r *3.14;
        }
        ~Circle() {
            cout << "圆的析构函数。。" << endl;
        }
    private:
        double r;
    };
    
    class Square :public Shape
    {
    public:
        Square(double a) {
            this->a = a;
        }
    
        //打印出图形的基本你属性
        virtual void show() {
            cout << "正方形的边长是" << this->a << endl;
        }
        //得到图形的面积
        virtual double getArea() {
            cout << "得到正方形的面积" << endl;
            return a*a;
        }
    
    
        ~Square() {
            cout << "正方形的析构函数" << endl;
        }
    private:
        double a;
    };
    
    
    
    int main(void)
    {
        Shape *array[2] = { 0 };
    
        for (int i = 0; i < 2; i++) {
            //生成一个圆
            if (i == 0) {
                double r;
                cout << "请输入圆的半径" << endl;
                cin >> r;
                array[i] = new Circle(r);
            }
            //生成一个正方形
            else {
                double a;
                cout << "请输入正方形的边长" << endl;
                cin >> a;
                array[i] = new Square(a);
            }
        }
    
    
        //遍历这个array数组
        for (int i = 0; i < 2; i++) {
            array[i]->show();
            cout << array[i]->getArea() << endl;
    
            delete array[i];
        }
    
        return 0;
    }
    圆类

    比较大的例子,推荐看看

    多态练习, 企业信息管理

    https://i.cnblogs.com/Files.aspx 

     函数指针与多态

    函数指针基础

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    
    // 数组类型, 基本语法知识梳理
    
    // 定义一个数组类型
    // int arr[10];
    
    // 定义一个指针数组类型
    
    // 定义一个指向 数组类型的指针, 数组类的指针
    int main() {
        int a[10];  // a代表数组首元素地址, &a 代表整个数组的地址
        // a+1 代表步长加4个单元,就是a[1]的地址,
        // &a+1 代表步长加40个单元后的地址
    
        //
        {
            // 定义数组类型
            typedef int (myTypeArr)[10];
            myTypeArr myArr;
            myArr[0] = 10;
            printf("%d
    ", myArr[0]);
        }
    
        {
            // 定义一个指针数组类型
            typedef int (*PTypeArray)[10]; // int * p
            PTypeArray myPArray;  // sizeof(int) * 10; 步长, myPArray 是一个二级指针
    
            myPArray = &a;
            // 相当于
            // int b = 10;
            // int *c = NULL;
            // c = &b;
    
            (*myPArray)[0] = 20;  // 注意这里
            printf("%d
    ", a[0]);
        }
    
        {
            // 定义一个指向 数组类型的指针, 数组类的指针
    
            int (*MyPoint)[10]; // 告诉c编译器给我分配内存
            MyPoint = &a;
    
            (*MyPoint)[0] = 40;
    
            printf("%d
    ", a[0]);
    
        }
        return 0;
    }
    
    // 函数指针语法知识梳理
    // 如何定义一个函数类型
    // 如何定义一个函数指针类型
    // 如何定义一个函数指针(指向一个函数入口地址)
    
    int add(int a, int b) {
        printf("func add...
    ");
        return a + b;
    }
    
    int main01() {
        add(1, 2); // 直接调用// 函数名就是函数入口地址
    
        // 如何定义一个函数类型
        {
            typedef int (myFuncType)(int a, int b); // 定义一个类型
            myFuncType *myFuncTypePoint = NULL; // 定义了一个指针,指向某一种类的函数
    
            myFuncTypePoint = &add; // 细节,这里的&add &可以不加
            myFuncTypePoint(1, 2);  // 间接调用
        }
    
        // 定义一个函数指针类型
        {
            typedef int (*MyPointFuncType)(int a, int b); // int *a = NULL;
            MyPointFuncType myPointFunc = NULL; // 定义一个指针
            myPointFunc = add;
            myPointFunc(1, 2);
        }
    
        // 函数指针
        {
            int (*myPointFunc)(int a, int b); // 定义一个变量
            myPointFunc = add;
            myPointFunc(1, 2);
        }
    
    }
    函数指针基础
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int myAdd(int a, int b)
    {
        printf("func myAdd...
    ");
        return a + b;
    }
    int myAdd2(int a, int b)   // 相当于虚函数表
    {
        printf("func myAdd2...
    ");
        return a + b;
    }
    
    // 定义了一个类型
    typedef int (*myTypeFuncAdd)(int a, int b);
    
    
    // mainop都是函数指针做函数参数
    int mainop(myTypeFuncAdd myFuncAdd)
    {
        int c = myFuncAdd(1, 2); // 间接调用
        printf("mainop
    ");
    
        return c;
    }
    // int (*myTypeFuncAdd)(int a, int b);  定义一个指向某种函数的指针
    int mainop2(int (*myTypeFuncAdd)(int a, int b))
    {
        int c = myTypeFuncAdd(1, 2);  // 间接调用
        printf("mainop2
    ");
    
        return c;
    }
    
    // 间接调用
    // 任务的调用,和任务的编写可以分开
    int main()
    {
        /*
        myTypeFuncAdd myfuncAdd = myAdd;
    
        myfuncAdd(1, 3);  // 直接调用
    
        mainop(myAdd);
        mainop2(myAdd);
        */
    
        mainop(myAdd);
        mainop(myAdd2);  // 相当于发生了多态,函数指针做函数参数
        return 0;
    }
    函数指针做函数参数思想
    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    
    
    using namespace std;
    
    int func(int a, int b)
    {
        cout << " 1999 年写的 func" << endl;
    
        return 0;
    }
    
    int func2(int a, int b)
    {
        cout << "1999 写的 func2" << endl;
        return 0;
    }
    
    int func3(int a, int b) 
    {
        cout << "1999年 写的 func3 " << endl;
        return 0;
    }
    
    //2018想添加一个新的子业务
    int new_func4(int a, int b)
    {
        cout << "2018 新写的子业务" << endl;
        cout << "a = " << a << ", b = " << b << endl;
        return 0;
    }
    
    //方法一:  函数的返回值, 函数的参数列表(形参的个数,类型,顺序)
    //定义一个函数类型。
    
    typedef int(FUNC)(int, int);
    
    //方法二:   定义一个函数指针
    typedef int(*FUNC_P)(int, int);
    
    
    //定义一个统一的接口 将他们全部调用起来。
    
    void my_funtion(int(*fp)(int, int), int a, int b)
    {
        cout << "1999年实现这个架构业务" << endl;
        cout << "固定业务1" << endl;
        cout << "固定业务2" << endl;
    
        fp(a, b);//可变的业务
    
        cout << "固定业务3" << endl;
    
    }
    
    int main(void)
    {
    #if 0
        //方法一:
        FUNC *fp = NULL;
    
        fp = func;
        fp(10, 20);
    
        FUNC_P fp2 = NULL;
    
        fp2 = func;
    
        fp2(100, 200);
    
        //方法三:
        int(*fp3)(int, int)   = NULL;
        fp3 = func;
        fp3(1000, 3000);
    #endif
        my_funtion(func, 10, 20);
        my_funtion(func2, 100, 200);
        my_funtion(func3, 1000, 2000);
    
        my_funtion(new_func4, 2000, 3000);
        
        return 0;
    }
    函数指针的工程意义
    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    
    
    using namespace std;
    //-------------抽象层------------
    //定义拆开锦囊方法的类型。
    typedef void(TIPS)(void);
    
    //定义锦囊
    struct tip
    {
        char from[64]; //谁写的
        char to[64];//写给谁的。
        //锦囊的内容
        TIPS *tp;//相当于抽象类的 纯虚函数.
    };
    
    //需要一个打开锦囊的架构函数
    void open_tips(struct tip *tip_p)
    {
        cout << "打开了锦囊" << endl;
        cout << "此锦囊是由" << tip_p->from << "写给 " << tip_p->to << "的。" << endl;
        cout << "内容是" << endl;
        tip_p->tp(); //此时就发生了多态现象。
    }
    
    //提供一个创建一个锦囊的方法
    struct tip* create_tip(char*from, char *to, TIPS*tp)
    {
        struct tip *temp = (struct tip*)malloc(sizeof(struct tip));
        if (temp == NULL) {
            return NULL;
        }
        strcpy(temp->from, from);
        strcpy(temp->to, to);
        //给一个回调函数赋值, 一般称 注册回调函数
        temp->tp = tp;
    
        return temp;
    }
    
    //提供一个销毁锦囊的方法
    void destory_tip(struct tip *tp)
    {
        if (tp != NULL) {
            free(tp);
            tp = NULL;
        }
    }
    
    
    // ------------- 实现层------------
    //诸葛亮写了3个锦囊
    void tip1_func(void)
    {
        cout << "一到东吴就拜会乔国老" << endl;
    }
    
    void tip2_func(void)
    {
        cout << "如果主公乐不思蜀,就谎称曹贼来袭。赶紧回来 " << endl;
    }
    
    void tip3_func(void)
    {
        cout << "如果被孙权追杀,向孙尚香求救" << endl;
    }
    
    void tip4_func(void)
    {
        cout << "如果求救孙尚香都不灵,  你们去死了, 我是蜀国老大了" << endl;
    }
    
    
    //---------------  业务层-----------------
    int main(void)
    {
        //创建出3个锦囊
        struct tip *tip1 = create_tip("孔明", "赵云", tip1_func);
        struct tip *tip2 = create_tip("孔明", "赵云", tip2_func);
        struct tip *tip3 = create_tip("孔明", "赵云", tip3_func);
        struct tip *tip4 = create_tip("庞统", "赵云", tip4_func);
    
        //由赵云进行拆锦囊。
        cout << "刚刚来到东吴, 赵云打开第一个锦囊" << endl;
        open_tips(tip1);
        cout << "-----------" << endl;
    
        cout << "刘备乐不思蜀, 赵云打开第二个锦囊" << endl;
        open_tips(tip2);
        cout << "-----------" << endl;
    
        cout << "孙权大军追杀,赵云打开第三个锦囊" << endl;
        open_tips(tip3);
        cout << "-----------" << endl;
    
        cout << "赵云发现,实在是杀不动了, 打开了第四个锦囊" << endl;
        open_tips(tip4);
    
        destory_tip(tip1);
        destory_tip(tip2);
        destory_tip(tip3);
        destory_tip(tip4);
        
        return 0;
    }
    诸葛亮锦囊妙计

    未完待续....

  • 相关阅读:
    Java equals compareTo()的区别
    Java getClass() VS instanceof VS ==
    HashMap与LinkedHashMap
    位运算的一些用例
    常见字符集和编码方式
    spring 打印所有创建的beans
    ApplicationContext之getBean方法详解
    多线程时Autowired自动注入问题
    使用Nexus创建Maven私服
    MYSQL timestamp用法
  • 原文地址:https://www.cnblogs.com/xiaokang01/p/9170248.html
Copyright © 2020-2023  润新知