Java基础学习五 面向对象

2021-05-27  本文已影响0人  SimonLike

面向对象

采用面向对象的方式开发一个软件,生命周期当中【整个生命周期中贯穿使用OO面向对象方式】:
面向对象分析:OOA
面向对象设计:OOD
面向对象编程:OOP

类和对象的概念

 - 什么是类?
    - 类在现实世界当中是不存在的,是一个模板,是一个概念。是人大脑思考抽象的结果。
    - 类代表了一类事物
    - 在现实世界当中,对象A与对象B之间具有共同特征,进行抽象总结出一个模板,这个模板被称为类。
 - 什么事对象?
    - 对象是实际存在的个体。现实世界当中实际存在。
 - 描述一下整个软件开发的过程:
    - 程序员先观察现实世界,从现实世界当中寻找对象
    - 寻找了N多个对象之后,发现所有的对象都有共同特征。
    - 程序员在大脑中形成了一个模板【类】。
    - Java程序员可以通过java代码来描述一个类。
    - Java程序中有了类的定义。
    - 然后通过类就可以创建对象。
    - 有了对象之后,可以让对象直接协作起来形成一个系统。
 - 类 --【实例化】--> 对象
 - 对象又被称为:实例/instance
 - 对象 --【抽象】-->类

1. 面向过程和面向对象的区别

2. 面向对象的三大特征

2.1封装

   代码加注释讲解方式,其中Students类可以新建一个java类使用。
/**
 * 为什么要封装?封装有什么好处?
 * 封装的好处:
 *      1、封装之后,对于那个事物来说,看不到这个事物比较复杂的那一面,只能看到该事物简单的那一面。
 *      复杂性封装,对外提供简单的操作入口。照相机就是一个很好的封装案例,照相机的实现原理非常复杂,
 *      但是对于使用照相机的人来说,操作起来是非常方便的。
 *
 *      2、封装之后才会形成真正的"对象",真正的"独立体"。
 *
 *      3、封装就意味着以后的程序可以重复使用。并且这个事物适应性比较强,在任何场合都可以使用。
 *
 *      4、封装之后,对于事物本身,提高了安全性。【安全级别高】
 *
 */

public class HelloWorld {

    public static void main(String[] args) {//表示定义一个公开的静态的主方法 ps:程序执行入口

        Students peo = new Students();

        // 访问实例变量的语法格式:

        // 修改数据:引用.变量名 = 值
        peo.setName("张三");
        peo.setNoID(1233);
        peo.setAge(16);
        peo.setSex(true ? "男" : "女");
        peo.setAddr("深圳");

        // 读取数据:引用.变量名
        System.out.println(peo.getName());
        System.out.println(peo.getNoID());
        System.out.println(peo.getAge());
        System.out.println(peo.getSex());
        System.out.println(peo.getAddr());

    }
}

/**
 * 封装的步骤
 * 1,所以的属性私有化,使用private关键字进行修饰,private表示私有的,修饰所有数据只能在本类中访问。
 * 2,对外提供简单的操作入口,也就是说以后外部程序要想访问属性,必须通过这些简单的入口进行访问。
 *      - 对外提供两个公开的方法,分别是set方法和get方法
 *      - 修改这个属性的值,调用set方法
 *      - 读取这个属性的值,调用get方法
 * 3,set方法的命名规范
 *      public void set+属性首字母大写(形参){}
 * 4,get方法的命名规范
 *      public void get+属性首字母大写(){ return 属性;}
 *
 * 一种属性常访问的时候有几种访问形式?
 *  - 第一种方式:读取这个属性的值,读取get
 *  - 第二种方式:修改这个属性的值,读取set
 *
 *  setter和getter 方法没有static关键字
 *  有static关键字修饰的方法如何调用:类名.方法名(实参)
 *  没有static关键字修饰的方法如何调用:引用.方法名(实参)
 *
 */

class Students {

    int noID;// 学号
    String name; //姓名
    private int age; //年龄
    String sex; //性别
    String addr; // 地址

//=================setter=======================

    public void setAge(int age) {
        if (age<0|age>130) {
            System.out.println("年龄不合法");
            return ;
        }
        this.age = age;
    }
    public void setNoID(int noID) {
        this.noID = noID;
    }

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

    public void setSex(String sex) {
        this.sex = sex;
    }

    public void setAddr(String addr) {
        this.addr = addr;
    }

    //=================getter=======================

    public int getAge() {
        return age;
    }

    public int getNoID() {
        return noID;
    }

    public String getName() {
        return name;
    }

    public String getSex() {
        return sex;
    }

    public String getAddr() {
        return addr;
    }
}

2.2继承

    2.2.1 继承模块

   代码加注释讲解方式,其中CreditAccounts、Accounts、FF类可以新建java类使用。

/**
 * 关于java语言当中的继承:
 *      1、继承是面向对象三大特征之一
 *      2、继承基本作用:代码复用。但是继承最重要的作用是:有了继承才有以后的"方法覆盖"和"多态机制"。
 *      3、继承语法格式:
 *          [修饰符列表] class 类名 extends 父类名{
 *              类体 = 属性 + 方法
 *          }
 *      4、java语言当中的继承只支持单继承,一个类不能同时继承很多类,只能继承一个类。
 *      5、关于继承中的一些术语
 *          B类继承A类,其中
 *              A类称为:父类、基类、超类、superclass
 *              B类称为:子类、派生类、subclass
 *      6、在java语言当中子类继承父类都继承哪些数据?
 *          - 私有的不支持继承
 *          - 构造方法不支持继承
 *          - 其他数据都可以被继承
 *      7、虽然java语言当中只支持单继承,但是一个类也可以间接继承其他类,例如:
 *          C extends B{
 *          }
 *          B extends A{
 *          }
 *          A extends T{
 *          }
 *          C直接继承B类,但是C类间接继承 T A 类
 *      8、java语言中假如一个类没有显示继承任何类,该类默认继承JavaSE库当中提供的java.lang.Object类。
 *      java语言中任何一个类中都有Object类的特征。
 *
 */


public class HelloWorld {

    public static void main(String[] args) {//表示定义一个公开的静态的主方法 ps:程序执行入口

        // 对象继承 赋值 取值
        CreditAccounts ca = new CreditAccounts();
        ca.setActno("abc0001");
        ca.setBalance(20000.00);
        ca.setCredit(0.99);
        System.out.println(ca.getActno()+ "," + ca.getCredit() + "," + ca.getCredit() );

        // 间接继承 方法调用
        ca.doSome();
    }
}

class CreditAccounts extends Accounts{

    private double credit;

    public CreditAccounts() {
    }

    public CreditAccounts(double credit) {
        this.credit = credit;
    }

    public double getCredit() {
        return credit;
    }

    public void setCredit(double credit) {
        this.credit = credit;
    }
}

class Accounts extends FF{
    private String actno;
    private  double balance;

    public Accounts() {
    }
    public Accounts(String actno, double balance) {
        this.actno = actno;
        this.balance = balance;
    }

    public String getActno() {
        return actno;
    }

    public void setActno(String actno) {
        this.actno = actno;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }
}

class FF{
    public void doSome(){
        System.out.println("do Some");
    }
}
    2.2.2 方法的覆盖

   代码加注释讲解方式,其中Animal、Cat、Bird类可以新建java类使用。

/**
 * 关于java语言当中方法的覆盖:
 *      1,方法覆盖有被称为方法重写,英文:override[官方的]/overwrite。
 *      2、什么时候使用方法重新?
 *          当父类中的方法已经无法满足当前子类的业务需求,
 *          子类有必要将父类中继承的方法进行重新编写,
 *          这个重新编写的过程称为方法重写/方法覆盖。
 *      3,什么条件满足之后方法会发生重写?【代码满足什么条件后,就构成方法的覆盖?】
 *          方法重写发生在具有继承关系的父子类之间
 *          返回值类型相同,方法名相同,形参列表相同
 *          访问权限不能更低,可以更高。
 *          抛出异常不能更多,可以更少。
 *      4,注意:
 *          私有方法不能继承,所有不能覆盖。
 *          构造方法不能继承,所以不能覆盖。
 *          静态方法不存在覆盖。
 *          覆盖只针对方法,不谈属性。
 *
 *
 */

public class HelloWorld {

    public static void main(String[] args) {//表示定义一个公开的静态的主方法 ps:程序执行入口
        //创建动物对象
        Animal a = new Animal();
        a.move();

        Cat c = new Cat();
        c.move();

        Bird b = new Bird();
        b.move();
    }
}

class Bird extends Animal{

    public void move(){
        System.out.println("鸟儿在飞翔");
    }
}

class Cat extends Animal{
    public void move(){
        System.out.println("猫在走猫步");
    }
}

class Animal{
    public void move(){
        System.out.println("动物在移动");
    }
}

2.3多态

关于java语言当中的多态语法机制(概念):
代码加注释讲解方式,其中Animal、Cat、Bird类可以新建java类使用。
public class HelloWorld {

    public static void main(String[] args) {//表示定义一个公开的静态的主方法 ps:程序执行入口

        //使用多态语法机制
        // =====父类引用指向子类型对象【多态】 向上转型 =============================================
        /**
         * Animal和Cat之间存在继承关系,Animal是父类,Cat是子类。
         * Cat is a Animal
         *
         * new Cat()创建对象的类型是Cat,a2这个引用的数据类型是Animal,进行了类型转换。
         * 子类型转换成父类型,称为向上转型/upcasting。
         *
         * java语言允许:父类型引用指向子类型对象。
         *
         */
        Animal a2 = new Cat();
        /**
         * java语言是先分析编译阶段,在分析运行阶段,编译无法通过,是无法运行的。
         *
         * 编译阶段编译器检查a2这个引用的数据类型为Animal,由于Animal.class字节码当中有
         * move()方法,所以编译通过了。这个过程我们成为静态绑定,编译阶段绑定。只有静态绑定
         * 成功之后才有后续的运行。
         *
         * 在程序运行阶段,jvm堆内存当中真实创建的对象是Cat对象,那么以下程序在运行阶段一定会
         * 调用Cat对象的move()方法,此时发生了程序的动态绑定,运行阶段绑定。
         *
         * 无论Cat类有没有重写move()方法,运行阶段一定调用的是Cat对象的move()方法,因为底层
         * 真实对象就是Cat对象。
         *
         * 父类型引用指向子类型对象,这种机制导致程序存在"编译阶段绑定"和"运行阶段绑定"两种不同的形态/状态,
         * 这种机制称为:多态语法机制。
         *
         */
         a2.move();// 输出:猫在走猫步

        /**
         * 分析以下程序为啥不能调用?
         *
         *      因为编辑阶段编译器检查到a2的类型是Animal类型,从Animal.class字节码文件当中查找catchMouse()
         *      方法,最终没找到该方法,导致静态绑定失败,也就是说编译失败了。别谈运行了。。
         */
         //a2.catchMouse();

        //===== 父类引用指向子类型对象【多态】  向下转型【只有当访问子类对象当中的特有方法】===================================
        Animal a3 = new Bird();

        /**
         * 以下程序编译时没问题的,因为编译器检查到a3的数据类型是Animal, Animal和Cat是存在继承关系,并且Animal
         * 是父类,Cat是子类型,父类装换成子类型叫做向下转型,语法合格。
         *
         * 程序虽然编译通过了,但是程序运行阶段会出现异常,因为jvm堆内存当中真实存在的对象是Bird类型,Bird对象无法
         * 转换成Cat对象,因为这两种类型不存在继承关系,会出现异常:java.lang.ClassCastException。
         */
         //Cat c3 = (Cat) a3;

        /**
         * 1,以上异常只有在强制类型转换的时候会发生,也就是说"向下转型"存在隐患(编译通过,但运行出错了)
         * 2,向上转型只要编译通过,运行一定不会出现问题,
         * 3,向下转型编译通过,运行可能出现问题,如何避免出现ClassCastException异常呢?
         *      使用instanceof运算符可以避免出现以上的异常。
         * 4,instanceof运算符的使用
         *      语法结构:(引用 instanceof 数据类型名)
         *      运算符执行结果类型是布尔类型,true/false
         * 5,java规范中要求:在进行强制类型转换之前,建议采用instanceof运算符进行判断,避免ClassCastException异常发生。
         *
         */

        if(a3 instanceof Cat){
            Cat c3 = (Cat) a3;
            c3.catchMouse();//调用子类对象中特有的方法
        }else if (a3 instanceof Bird) {
            Bird b2 = (Bird) a3;
            b2.fly();//调用子类对象中特有的方法
        }
    }
}

class Bird extends Animal{

    public void move(){
        System.out.println("鸟儿在飞翔");
    }

    public void fly(){
        System.out.println("鸟儿在fly");
    }
}

class Cat extends Animal{
    public void move(){
        System.out.println("猫在走猫步");
    }
    public void catchMouse(){
        System.out.println("猫在抓老鼠");
    }
}

class Animal{
    public void move(){
        System.out.println("动物在移动");
    }
}

3. 面向对象-->定义类和对象

   代码加注释讲解方式,其中Students类可以新建一个java类使用。
public class HelloWorld {

    public static void main(String[] args) {//表示定义一个公开的静态的主方法 ps:程序执行入口
        // 通过一个类可以实例化N个对象
        // 实例化对象语法:new 类名();
        // new是java语言当中的一个运算符。
        // new运算符的作用是创建对象,在jvm堆内存当中开辟新的内存空间
        // 方法区内存:在类加载的时候,class字节码代码片段被加载到该内存空间当中。
        // 栈内存(局部变量):方法代码片段执行的时候,会给该方法分配内存空间,在栈内存中压栈。
        // 堆内存:new的对象在堆内存中存储。
        // Student是一个引用类型
        // peo是一个变量名
        // new Student()是一个学生对象
        // peo是一个局部变量【在栈内存中存储】
        // 什么是对象?new运算符在堆内存中开辟内存空间称为对象。
        // 什么是引用?引用是一个变量,只不过这个变量中保存了另一个java对象的内存地址。
        // java语言当中,程序员不能直接操作堆内存,java中没有指针;不像C语言
        // java语言当中,程序员只能通过"引用"去访问堆内存当中对象内部的实例变量。
        Students peo = new Students();

        // 访问实例变量的语法格式:
        // 读取数据:引用.变量名
        System.out.println(peo.name);
        System.out.println(peo.noID);
        System.out.println(peo.sex);
        System.out.println(peo.age);
        System.out.println(peo.addr);

        // 修改数据:引用.变量名 = 值
        peo.name = "张三";
        peo.noID = 1233;
        peo.age = 16;
        peo.sex = true ? "男" : "女";
        peo.addr = "深圳";

        // 再创建一个Student对象
        Students st = peo;

        System.out.println(st.name);
        System.out.println(st.noID);
        System.out.println(st.sex);
        System.out.println(st.age);
        System.out.println(st.addr);
    }
}

/*学生类
 学生类是一个模板
 描述所有学生的共同特征【状态+行为】
 当前类只描述学生的状态信息【属性】
*/

class Students {
    // 类体 = 属性 + 行为

    // 属性【存储数据采用变量的形式】
    // 由于变量定义在类体当中,方法体之外,这种变量称为成员变量
    // 所有学生都有学号信息
    // 但是每一个学生的学号是不同的
    // 所有访问这个学号必须先创建对象,通过对象去访问学号信息
    // 学号信息不能直接通过"类"去访问,所以这种成员变量有被叫做:实例变量
    // 对象有被称为实例,实例变量有被称为对象变量。【对象级别的变量】
    // 不创建对象,这个noID变量的内存空间是不存在的,只有创建了对象,这个noID的变量内存空间才会创建。

    int noID;// 学号
    String name; //姓名
    int age; //年龄
    String sex; //性别
    String addr; // 地址

}

4. 面向对象-->构造方法

demo代码示例:

public class HelloWorld {

    public static void main(String[] args) {//表示定义一个公开的静态的主方法 ps:程序执行入口

        new Students();
    }

}

class Students {
    //构造方法
     public Students() {
         System.out.println("构造方法");
     }
     
}

5. 面向对象-->参数的传递

demo代码示例:

public class HelloWorld {

    public static void main(String[] args) {//表示定义一个公开的静态的主方法 ps:程序执行入口

        User u = new User(20);
        // 传递u给add方法的时候,实际上传递的是u变量中保存的值,只不过这个值是一个java对象的内存地址。
        add(u);//等同于 add(0x....);

    }

    public static void add(User a){
        a.age++;
        System.out.println("add---->" + a.age);
    }

}
class User{
    int age;//实例变量
    public User(int i){
        age = i;
        System.out.println("age---->" + age);
    }
}

上篇:Java基础学习四 方法
下篇:Java基础学习六 关键字

上一篇 下一篇

猜你喜欢

热点阅读