java之面向对象学习

            
OOP: 面向对象编程
    O 1-2年时间
    O 2-4年时间
    P 5年以上 架构师
AOP:面向切面编程


1.面向对象思想
    面向对象其实还是基于面向过程的编程思想
    
2.面向对象和面向过程的区别
    面向过程:需要具体的强调每一个功能步骤实现
    面向对象:强调的是对象,然后由对象进行功能的实现
    
3.面向对象的思想特点
    a.是一种更加符合我们思想的思想
    b.可以将复杂的事变成简单化
    c.我们从执行者变成了指挥者
    
    买电脑:
        面向过程:需要了解自己的需求-->了解电脑的配置-->去岗顶买电脑-->讨价还价-->买回电脑
        面向对象:我需要买电脑-->找班长-->给钱-->班长买回来
    洗衣服:
        面向过程:先脱衣服-->找一个盆-->放点洗衣服-->加点水-->把衣服扔进去-->踩一踩-->清水洗一洗-->拧干-->晾起来
        面向对象:先脱衣服-->打开全自动智能化滚筒洗衣机-->按一下-->拿出来-->
    吃饭:
        面向过程:去菜市场买菜-->摘菜-->洗菜-->切菜-->炒菜(调味)-->盛起来-->吃
        面向对象:点外卖-->吃
        
        家常事务,洗衣服和点外卖都不划算,所以赶紧找个对象
    
把大象装进冰箱需要几步?
    面向过程:
        动作有哪些?
            a.打开冰箱门
            b.装进大象
            c.关闭冰箱门
            
            public class Demo {
                public static void main(String[] args) {
                
                    open();
                    in();
                    close();
                    
                }
                public static void open() {
                    System.out.println("打开冰箱门");
                }
                public static void in() {
                    System.out.println("把班长塞进去");
                }
                public static void close() {

                    System.out.println("关闭冰箱门");
                }
            }
            
    面向对象:
        我们要怎么样才能写出符合面向对象的程序
            a.有哪些类
            b.每一个类里面有什么东西
            c.类与类最直接的关系是什么
        
        把大象关进冰箱需要几步进行分析(你们有时间可以去看下名词提取法,UML)
            a.有哪些类?    
                大象
                冰箱
                测试类(启动类,Demo)
            b.每个类有什么东西?
                大象:
                    进去冰箱
                冰箱:
                    开门
                    关门
                Demo:
                    main方法
            c.每个类之间最直接的关系
                Demo使用冰箱类来调用大象进去
                
        class 班长{
            public static void in(){
                System.out.println("把班长塞进去");
            }
        }
        
        class 冰箱{
            public static void open(){
                System.out.println("打开冰箱门");
            }
            public static void close() {
                System.out.println("关闭冰箱门");
            }
        }
        
        class Demo{
            //调用冰箱去开门
            //把班长塞进去
            //关闭冰箱门
        }
        
        
面向对象的开发,设计,特征
    面向对象开发?
        其实就是不断的创建对象,使用对象,指挥对象干活
    面向对象设计?
        其实就是管理和维护对象之间的关系
    面向对象的特点?
        封装(encapsulation)
        继承(inheritance)
        多态(polymorphism)
        
面向对象编程:
    怎么去描述一个人?
        属性:
            姓名:刘飞龙
            性别:男
            身高:189cm
            长相:.....
        行为:
            培育人才
            匡扶正义
            敬老爱幼
            
    怎么去描述一条狗?
        属性:
            姓名:旺财
            性别:公
            种类:土狗
            体长:100cm
            体重:30kg
        功能:
            汪汪汪
            吃饭
            睡觉
            摇尾巴
            
    面向对象的概念就是对现实事物中存在和不存在的事物的抽象体,通过这种抽象摆脱计算机的思维,用现实世界的人的
    思维去开发和维护程序。
    我们学习 编程语言,是为了模拟现实的事物,而我们学习编程语言的Java的最基本的单位是:类
    所以,我们就应该讲分析好的现实世界的事物用类来进行体现
    由此,我们就应该对比现实事物和类的对应关系:
    
    事物:                            类:
      属性                                成员变量
      行为                                成员方法
            
类:应该是一组相关的属性和行为的集合,是一个非常抽象的概念
对象:是该类的事物的具体表现形式,具体存在的一个个体
    
举例:
    学生:类
    班长:对象
    
    类:人类
    对象:教师
    对象:开发工程师
    
4.匿名对象:就是没有名字的对象
     匿名对象的应用场景:
         A.调用方法,仅仅适合只调用一次的时候。
             注意:如果是调用多次,不合适
             那么,匿名对象有什么好处?
                 有,匿名对象使用完毕后就是垃圾,可以被垃圾回收器回收
             b.匿名对象可以作为实际的参数进行传递

5.成员变量和局部变量的区别:
    A.在类中的位置不同
        成员变量: 类中方法外
        局部变量: 方法内或者方法声明上

    B.在内存中的位置不同
        成员变量:堆内存
        局部变量:栈内存
    
    C.生命周期不同
        成员变量:随着对象的存在而存在,随着对象的消失而消失
        局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
    
    D.初始化值不同
        成员变量:有默认的初始化值
        局部变量:没有默认的初始化值,必须先定义,赋值,才能使用。

    注意:
        局部变量和成员变量的名字一致时,在方法中使用的时候采用的是就近原则
        
6.private:
         是一个权限修饰符
         可以修饰成员变量和成员方法
         被其修饰的话,就只能在本类中进行方法
        
7.定义一个学生类:
         成员变量:name age
         成员方法:show()
         
     我们在使用这个案例的时候,发现了一个问题
         通过这个对象进行 变量的赋值,可以赋值一些非法的数据。
         这个是不合理的。
         应该是这个样子,在赋值之前,我需要先对数据进行合法性的校验
         判断到底放在哪里会比较合适。
         StudentDemo只是一个测试类,测试类一般只用于创建对象和调用方法
         所以,我们校验的数据应该放在Student类里面。
         
        按照我们之前的分析,我们给出了一个方法进行校验
        但是呢,有些人偏偏就不走你这个方法,还是进行直接的赋值。
        但是呢,我们又不能要求开发者或者用户强制的去使用你的校验方法。
        我们怎么能够要求用户必须要走正确的成员变量的赋值呢?
            针对这样的情况,Java提供了一个关键:private
        private:私有的,可以修饰成员变量和成员方法
        被private修饰的变量和方法,只能够在本类中进行方法。
        
        我们在开始的时候,就见过一个封装的思想。
        封装:是指隐藏对象的属性和实现的细节,仅对外提供公共的访问方式        
        


1.继承的注意事项:
         A.子类只能继承父类的非私有的成员变量和成员方法
         B.子类不能继承父类的构造方法,但是可以通过一个关键字去访问父类的构造方法:super(马上讲)
         C.OOP的编程语言,所有的类都应该会有一个继承关系,如果没有继承关系就默认extends Object
         D.千万不要了为了部分功能去实现继承
             class 鸟{
                 public void 飞{
                 
                 }
                 public void 下蛋{
                 
                 }
                 public void 吃虫子{
                 
                 }
             }
             
             class 企鹅{
                 public void 下蛋{
                 
                 }
             }
             
         那么我们应该什么时候去考虑使用继承?
             继承的实现应该体现一个"is a"的关系
             人类
                 教师
                 学生
             水果
                 苹果
                 香蕉
                 橘子
                 西瓜
             采用一个假设:
                 如果有A/B两个类.只有他们符合A/B的其中一种,或者B/A的一种就可以考虑使用继承。
                
2.继承中成员变量的关系:
         a.子类的成员变量和父类的成员变量的名字不一致时,太简单 不问
         b.子类的成员变量和父类的成员变量的名字一致时,这个怎么玩?
             在子类的方法中访问一个变量的顺序
                 a.在子类的局部范围内去查找。有就直接使用
                 b.在子类的成员范围内去查找,有就直接使用
                 c.去父类成员变量去查找,有就直接使用
                 d.如果还找不到,就去父类的父类。。 都没有就真的没有了 报错

3.问题:
         我不仅仅要输出局部变量的num,还要输出本类成员范围内的num.怎么办?
         我还想要输出父类的num,怎么办?
             如果你有一个东西和this相似,但是可以直接访问父类的数据就好
             恭喜你,java提供了一个关键字叫做supre;
         this和super的区别
             分别是什么?
                 this代表本类对于对象的应用
                 super代表父类的存储空间的标识(可以理解为父类的引用,可以操作父类的方法和变量)
         怎么用?
                 a.调用成员变量
                     this.成员变量 调用的是当前对象的成员变量
                     super.成员变量 调用的是父类的成员变量
                 b.调用构造方法
                     this(..) 调用的是本对象的构造方法
                     super(..) 调用父类的构造方法
                 c.调用成员方法
                     this.成员方法 调用的是本对象的成员方法
                     super.成员方法 调用父类的成员方法
         
4.子类的创建的过程:
         创建子类的对象是,会调用子类的构造器,而在调用子类的构造器之前,会先调用父类的构造器
         先对父类做初始化,在对子类做初始化,因为子类需要使用到父类的东西,所以父类必须先初始。
         
     继承中构造方法的关系:
         a.子类中的所有的构造方法都会默认的执行父类的空参数构造
         b.子类的每一个构造方法的第一条语句默认的就是super();

5.如果父类没有无参构造,那么子类的构造方法会出现什么样的情况?
        报错。
    如何解决?
        a.在父类添加一个无参的构造器
        b.通过super关键字去显式的调用父类的带参构造器
    注意:
        this(..)和super(..)必须出现在第一条语句上面
        如果不是放在第一条语句,就可能对父类的数据进行
        
6.继承中成员方法的关系:
         a.子类中的方法和父类中的方法名字不一致时,各自走各自的
         b.子类中的方法和父类中方法声明的名字一致时
             通过子类对象调用的顺序:
                 a.先在子类中,看有没有这个方法 如果有就直接使用、
                 b.在看父类有没有,有就直接使用。
                 c.如果都没有就报错
                
7.方法的重写(方法覆盖):子类中出现了和父类方法声明一模一样的方法

     方法重载:
         本类中的方法名一样,参数列表不同,与返回值无关

    子类对象调用方法的时候;
        先找子类,在找父类

    方法重写的应用:
        当你的子类需要使用父类的功能,而功能的主体子类有持有自己特有的内容的时候,可以重写父类中的方法。
        这样就,不但沿用了父类的特有功能,还能直接定义子类的功能

    王道之概述:子类要覆盖父类的方法是,直接把方法的定义拷贝过来,重新编写到父类
    
8.final可以修饰类、方法、变量
     
     特点:
         final可以修饰类,该类就无法被继承
         final可以修饰方法,该方法就不能被重写(覆盖)
         final可以修饰变量,该变量就变成了常量。
     常量:
         a.字面值常量
             "龙爸爸" 10 true
         b.自定义常量
             final int x = 10;
            
9.final修饰局部变量的问题:
         基本数据类型:基本数据类型的值不能改变
         引用数据类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值是可以改变的
        
10.final修饰变量的初始化时机:
         a.被final修饰的变量只能赋值一次
         b.在构造方法完毕前(非静态)
         c.构造方法不能被final修饰

11.我们在学习面向对象的继承思想的时候,说过,继承一种体现"is A"的关系,也就是子类是父类的一种特殊的情况
     狗是一种动物。猫也是一种动物。一条狗或者一只猫也是动物的这种类型
     class Animal{
         public void eat(){
             System.out.println("吃一般的食物");
         }
     }
     
     class Dog extends Animal{
         public void eat(){
             System.out.println("喝啤酒,吃炸鸡。");
         }
     }
     
     class Cat extends Animal{
         public void eat(){
             System.out.println("吃鱼摆摆..");
         }
     }
     
      创建了一个狗的对象,此时将子类对象赋值给父类对象
      Animal a = new Dog();
              a = new Cat();
      对象a应该是一个多态,有两种类型
      编译多态:把a的对象当做什么什么类型:Animal
      运行多态:对象a的真正类型
 
     多态:同一个对象(事务),在不同时刻体现出来的不同状态
     举例:
         酒--剑南春-XO-二锅头-白兰地
     多态的前提:
         a.必须存在继承的关系
         b.要有方法的重写
             其实你也是可以不重写方法,但是这样就没有任何意义
                 动物 d = new 猫();
                 d.eat();
                 动物 d = new 狗();
                 d.eat(); 
         c.要有父类的引用指向子类的对象
                 父 f = new 子();
                 
         多态中的成员访问的特点:
             a.成员变量
                 编译看左边,运行看左边
             b.构造方法
                 创建子类对象的时候,访问父类的构造方法,对父类数据进行初始化
             c.成员方法
                 编译看左边,运行看右边
             d.静态方法
                 编译看左边,运行看左边
                 (静态和类相关的,其实算不上重写,访问的都是左边)
             由于成员方法存在方法的重写,所以他的运行是看的你右边
            
12.多态的好处:
         从我们之前举的例子,可以得知多态的一部分的作用。当不同的子类对象都当成父类类型来看,可以屏蔽不同子类对象之间的差异,从而
         可以实现写出通用代码的编程,以适应不同的需求。
     a.提高了代码的维护性(继承)
     b.提高了代码的扩展性(多态)
    
13.多态的弊端:
         不能够使用子类的特有功能
        
14.多态的弊端:
         不能直接使用子类的特有的功能
     我就想使用,你有么有办法?
         有
     
     怎么用呢?
         a.创建子类对象的方法即可(跟我们的多态没毛线关系)、
         b.把父类的引用强制的转换为子类的引用(向下转型(造型))
         
     对象间的转型的问题:
         向上转型:
             Fu f = new Zi(); 
             把子类对象赋值给父类引用(系统默认转换)
         向下转型:
             Zi z = (Zi)f//要求f必须是能够转为Zi的
            
15.ClassCastException:类型转换异常
     一般都是在多态向下转型中引起的异常

1.抽象类的概述:
        动物不应该是一个具体的东西,而且动物中有吃、睡、玩呀等等也不应该是具体的
        我们应该把一个不是具体的功能称为抽象功能,而一个类中如果有抽象的功能,那么该类就应该是一个抽象类。

     抽象类的特点:
         a.抽象类和抽象方法必须用abstract关键字来进行修饰
         b.抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类
         c.抽象类不能实例化
             因为不是具体的存在
             抽象类中是有构造方法,但是也不能实例化,那么构造方法有啥作用?
             就用于子类访问父类的数据
         d.抽象类的子类
             a.如果不想重写抽象方法,该子类也是一个抽象类
             b.如果说你重写了父类的所有的抽象方法,那么该子类就是一个具体的类
             c.抽象的子类必须重写父类的抽象方法
             
         抽象类的实例化其实是靠具体的子类来实现的,也就是多态的方式
         Animal a = new Dog();
         
     抽象类的成员的特点:
         成员变量:既可以是变量也可以是常量
         成员方法:可以是抽象,也可是非抽象的
         构造方法:有
                 用于子类访问父类的初始化数据
                 
         抽象类的成员方法的特性:
             a.抽象方法:可以强制要求具体化的子类必须要做的什么事情
             b.非抽象方法:可以用于子类继承,提高代码的复用性
             
     如果说一个类没有抽象方法,可不可以定义为抽象类?如果可以 意义何在?
         A.可以
         B.不可以创建对象,实现多态
         
     abstract不能和哪些关键字共存?
         private  冲突
         final     冲突
         static 冲突
        
2.猫狗案例
        具体事物:猫,狗
        共性:姓名,年龄,吃饭

      分析:
          从具体到抽象
              猫:
                  成员变量:姓名,年龄
                  成员方法:吃饭(猫吃鱼)
                  构造方法:无参构造,带参构造
              狗:
                  成员变量:姓名,年龄
                  成员方法:吃饭(狗吃班长)
                  构造方法:无参构造,带参构造

          因为存在共性。所以我们需要提取出一个父类。动物类、
          但是有由于吃饭的行为不一致,所以吃饭应该是一个抽象的
          因为父类存在抽象的方法,所以父类就必须是一个抽象类

          抽象的动物类:
              成员变量:姓名,年龄
              成员方法:吃饭(猫吃鱼)
              构造方法:吃法()

3.单例设计模式:
         在某一个类中,且有一个实例(对象),一般在开发中,工具类都应该是单例的设计模式
     好处:
         被单例设计的类只能创建一次对象,避免了对象的重复创建和销毁
         节省内存空间
         
     单例设计模式的设计方法有N种,老师这种写法叫做饿汉式写法()
     单例的设计模式是最简单的设计模式,面试必问
     单例设计也是最常用的设计的模式,知道我们后面学到Spring。其实本质上也是采用单例(超级对象工厂)
 */
        public class SingletonDemo {
            //让对象无法创建
            private SingletonDemo() {}
            //保持对象能够创建一次
            private static final SingletonDemo instance = new SingletonDemo();


            //提供公共返回返回
            public static SingletonDemo getiInstance() {

                return instance;
            }

            public void show() {
                System.out.println("hello world");
            }

        }

        class Dmeo{
            public static void main(String[] args) {
                SingletonDemo.getiInstance().show();
            }
        }
        
4.    接口的特点:
         a.接口用interface来进行表示
             interface 接口名{}
         b.类实现接口使用implements 接口名
             class 类名 implements 接口名{}
         c.接口不能实例化
             那么,接口如何实例化?
             按照多态的方式就OK了
         d.接口的子类
             a.可以是抽象类,但是没必要
             b.可以是具体类,但是要重新接口所有抽象方法(一般都是这么用)

     由此可见:
         a.具体类的多态(几乎没有)
         b.抽象类多态(常用)
         c.接口多态(用的炒鸡多)
        
5.接口成员变量的特点:
         成员变量:只能是常量。并且是静态
             默认的修饰:public static final 
             建议自己手动给出,因为你太闲了
         构造方法:
             接口不是类,所以没有构造方法
         成员方法:只能是抽象方法
             默认的修饰:public abstract
             建议自己手动给出,因为你太闲了
            
7.    类与类:
         继承关系,只能单根继承 但是可以多层继承
     类与接口:
         实现关系,可以单实现,也可以多实现
     接口与接口:
         继承关系,可以单继承也可以多继承
         
         
     接口和抽象类的区别:
         相同点:
             a.都不能实例化
             b.都可以定义抽象方法,其子类也必须实现(重新)该抽象方法
             c.都位于继承层次的顶端,用于被继承或者实现
         成员:
             抽象类:
                 成员变量:可以是变量也可以是常量
                 成员方法:可以是抽象,也可以是非抽象
                 构造方法:有
             接口:
                 成员变量:没有变量,只有常量
                 成员方法:只能是抽象方法
                 构造方法:没有
                 
         设计理念的区别:
             抽象类其实是一个继承的体系:"is a"的关系。抽象类中的定义是该继承体系的共同特性
             接口 被实现的其实是:"like a"的关系。接口中定义的其实是该继承体系的扩展功能(其实定义的也是一种规范)
             
         二者的选用:
             优先选用的是接口。尽量少用抽象(因为的抽象继承关系存在耦合度过高的问题,也违背了单一原则)。若需要定义子类的功能,又要为子类提供共性的功能的时候
             就选用抽象,在选用抽象的时候,尽量判别你的业务是不是一个抽象的存在。
            
9.形参和返回值的深入讲解
        引用类型:
             类:要的其实是该类的具体的对象
             接口:要的其实是该接口的实现类的对象
             抽象类:其实要的是该抽象的子类的对象
             
         返回值:
             类:要的其实是该类的具体的对象
             接口:要的其实是该接口的实现类的对象
             抽象类:其实要的是该抽象的子类的对象
             


1.    字符串:就是由多个字符组成遗传字符,其实也可以看成一个字符串数组
    通过查看API,我们可以知道
    a.字符串字面值"abc"也可以看成是一个字符串对象
    b.字符串是常量,一旦赋值,就不能发生改变

你可能感兴趣的:(java之面向对象,java进阶之路)