Java - 2. 面向对象编程

面向对象 - 封装

-- 前面的学习思想都是面向过程编程,现在开始学习 面向对象编程
-- 什么是对象?    对象:特殊的数据结构,用来记住一个事物的数据,从而代表该事物
-- Tips:对象就是实例,实例就是对象。

快速入门

第一步:设计对象的模板【设计图】:类(类是对象的抽象,用来描述一组对象的共同特征)

  • 类中可以定义成员变量、成员方法
成员变量类中定义的变量
局部变量方法中定义的变量
// 定义一个student类
public class Student {
    // 类中可以定义:成员变量、成员方法。【非私有成员:成员变量、成员方法】
    //       ① 成员变量:定义在类中的变量
    //       ② 局部变量:定义在方法中的变量
    // 成员变量:又称对象的属性,描述对象的特征
    String name;    // 姓名
    int age;        // 年龄
    String sex;    // 性别
    int chinese;    // 语文成绩
    int math;       // 数学成绩
    
    // 成员方法:描述对象的行为
    public void sum(){
        int sum;
        sum = chinese + math;
        System.out.println("总分:" + sum);
    }
    public void avg(){
        System.out.println("平均分:" + (chinese + math) / 2);
    }
}

第二步:每new一次类,就得到一个新对象

public class Test1 {
    public static void main(String[] args) {
        Student s1 = new Student();     // 创建Student对象
        s1.name = "张三";
        s1.age = 18;
        s1.sex = "男";
        s1.chinese = 100;
        s1.math = 45;
        System.out.println(s1.name + " " + s1.age + " " + s1.sex);
        s1.sum();   
        s1.avg();       

        Student s2 = new Student();     // 创建Student对象
        s2.name = "李四"; 
        s2.age = 19;
        s2.sex = "女";
        s2.chinese = 87;
        s2.math = 100;
        System.out.println(s2.name + " " + s2.age + " " + s2.sex);
        s2.sum();
        s2.avg();
    }
}

类的用法 - 构造器

-- 构造器:特殊的方法。名称必须和类名相同
--     【例如】类名为Student,那么定义的构造器必须也为Student

-- 构造器的应用场景:创建对象时,为 对象成员变量的初始化赋值。

-- 构造器的特点:
--     1. 构造器的名称必须与类名相同
--     2. 构造器不能有返回值类型(包括也不能写void)
--     3. 构造器可以重载,可以定义多个
--     4. 创建对象时自动调用构造器
--     5. 类默认自带一个无参构造器,默认调用
--     6. 如果定义了有参构造器,那默认的无参构造器就没了,若想用无参构造器,需要重新定义
    public class Student {
        String name;    // 姓名
        int age;        // 年龄
        char sex;        // 性别
    
        // 构造器:无参构造器
        public Student() {
            System.out.println("无参构造器被调用了!");
        }
    
        // 构造器:有参构造器
        public Student(String n, int a, char s) {
            System.out.println("有参构造器(完整)被调用了!");
            name = n;
            age = a;
            sex = s;
        }
    
        // 构造器:有参构造器
        public Student(String n){
            name = n;
            System.out.println("有参构造器(部分)被调用了!");
        }
    }
    public class Test1 {
        public static void main(String[] args) {
            Student s1 = new Student("张三", 18, '男');
            Student s2 = new Student();
            Student s3 = new Student("李四");
        }
    }
    // 输出如下:
    // 有参构造器(完整)被调用了!!!
    // 无参构造器被调用了!!!
    // 有参构造器(部分)被调用了!!!

    类的用法 - this

    类的用法 - 封装

    面向对象编程的三大特征:封装、继承、多态

    类就是一种封装

    封装的设计思想:合理隐藏、合理暴露

    类的用法 - 实体类 javabean

    实体类:特殊的类。必须满足以下

    • 类中的成员变量全部私有,并提供public修饰的getter/setter方法​​
    • 类中必须有无参构造器。有参构造器可选
    • 【实体类的应用场景】实体类的对象只负责数据存取,而对数据的业务处理交给其他类的对象去完成,以实现数据和数据业务处理 分离。 
    // 以下是一个标准的实体类:
    public class Student {
        // 封装的思想:将属性私有化(provite),通过方法访问属性
        // 1.属性私有化。作用:封装属性,避免属性被修改
        private String name;
        private int age;
        private char sex;
        private double chinese;
        private double math;
    
        // 2.提供getter和setter方法。
        // set:设置属性值
        // get:获取属性值
        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;
        }
        public char getSex() {
            return sex;
        }
        public void setSex(char sex) {
            this.sex = sex;
        }
        public double getChinese() {
            return chinese;
        }
        public void setChinese(double chinese) {
            this.chinese = chinese;
        }
        public double getMath() {
            return math;
        }
        public void setMath(double math) {
            this.math = math;
        }
    
        // 提供一个无参构造器
        public Student() {}
        
        // 提供一个有参构造器(可选)
        public Student(String name, int age, char sex, double chinese, double math) {
            this.name = name;
            this.age = age;
            this.sex = sex;
            this.chinese = chinese;
            this.math = math;
        }
    }

    类的用法 - static

    static:静态的。可以修饰 成员变量、成员方法

    成员变量按有无static修饰,分:类变量、实例变量。

    • static修饰的成员变量:类变量。属于类,在计算机(内存)只有一份,被类的所有对象共享。
    • 无static修饰的成员变量:实例变量。属于类的每个对象,每个对象都有一份

    成员方法按有无static修饰,分:类方法、实例方法

    • static修饰的成员方法:类方法。属于类。建议:类名.方法名
    • 无static修饰的成员方法:实例方法。属于对象。只能对象调用

    类变量的应用场景:

    类方法的应用场景:类方法常用作工具类【工具类:工具类中的方法都是类方法,每个方法用来完成一个功能,工具类是给开发人员共同使用的】

    问答题:为什么工具类中的方法用类方法,而不用实例方法?
    回答:① 实例方法需要创建对象来调用,创建这个对象只是为了调用方法,对象占内存,这样会浪费内存。② 类方法,直接用类名调用即可,能节省内存。

    面向对象 - 继承 extends

    继承 - 基础

    • 子类继承父类的 非私有成员(成员变量、成员方法)
    • 子类对象由子类、父类共同创建。
    • 使用继承的好处:减少重复代码,提高代码复用性。
    • Java是单继承的,类不支持多继承,但支持多层继承

      面试题:为什么类不支持多继承?   反证:假设A类、B类有同名的方法(功能不同),则会冲突

    • object 类:java所有类的祖宗类。任何一个类都是object的子类(或子孙类)

    权限修饰符

    权限修饰符:限制类中的(成员变量、成员方法、构造器…)能被访问的范围。

    限制能被访问的范围
    private本类
    缺省本类、同一包下的类
    protected本类、同一包下的类、子孙类
    public任意范围

    方法重写

    当父类的方法不能满足子类的需求时,子类重写一个方法名、参数列表一样的方法,就是方法重写

    注:重写后,Java遵循就近原则来访问方法 。

    // 方法重写的注意事项
    // 1. 重写方法时,加上@Override注解,他可以指定java编译器,检查方法重写的格式是否正确,代码可读性也更好。
    // 2. 子类重写父类方法时,访问权限必须大于或等于父类该方法的权限
    // 3. 重写方法的返回值类型,要与原方法相同,或范围更小。
    // 4. 私有方法、静态方法不能重写,重写会报错。
    public class ChongXie02 {
        public static void main(String[] args) {
            Dog d1 = new Dog();
            d1.shout(); // 输出: 汪汪汪!!!
        }
    }
    
    class Dog extends Animal{
        // 重写Animal父类中的 shout 方法
        @Override
        public void shout(){
            System.out.println("汪汪汪!!!");
        }
    }
    
    class Animal{
        // 叫声的方法
        public void shout(){
            System.out.println("动物会叫~~");
        }
    }
    

    方法重写 - 拓展:重写object类的tostring方法(重点)

    public class ChongXie01 {
        public static void main(String[] args) {
            Student s1 = new Student("刘思", 18, '女');
            System.out.println(s1); // 输出:com.HAF.JiCheng.Student@1b6d3586
            // 直接输出对象时,默认调用OBject父类的toString方法(可以省略不写调用toString的代码),返回对象的地址信息
            // System.out.println(s1.toString);
            // 输出对象的地址实际上没有意义,开发中更希望输出对象的内容信息,所以子类要重写0bject的toString方法,
        }
    }
    
    class Student {
        String name;
        int age;
        char sex;
    
        // 重写toString方法
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", sex=" + sex +
                    '}';
        }
    
        // 生成get、set方法
        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;
        }
    
        public char getSex() {
            return sex;
        }
    
        public void setSex(char sex) {
            this.sex = sex;
        }
    
        // 无参构造器
        public Student() {}
    
        // 全参构造器
        public Student(String name, int age, char sex) {
            this.name = name;
            this.age = age;
            this.sex = sex;
        }
    }

    子类中访问其他成员的特点

    在子类方法中访问其他成员(成员变量、成员方法):依照就近原则。

    • 先子类局部范围找。 然后子类成员范围找。 然后父类成员范围找,仍没有找到则报错。

     如果子类和父类,出现重名成员,会优先用子类的,若此时要在子类中使用父类的怎么办?

    • 可以通过super关键字,指定访问父类的成员:super.父类成员变量/父类成员方法
    public class JiCheng01 {
        public static void main(String[] args) {
            Student1 s1 = new Student1();
            s1.show();
        }
    }
    
    class People{
        String name = "父类";
    }
    
    class Student1 extends People{
        String name = "子类";
        public void show(){
            String name = "局部变量";
            System.out.println(name);       // 输出:局部变量
            System.out.println(this.name);  // 输出:子类
            System.out.println(super.name); // 输出:父类
            // this.name:表示当前对象的成员变量
            // super.name:表示父类的成员变量
        }
    }
    

    面向对象 - 多态

    多态 - 基础

    什么是多态?       多态是在继承/实现后的一种现象,表现为对象多态、行为多态

    面向对象 (高级)

    final

    final:最终的,不可改变的。可以修饰 类、方法、变量

    final 修饰的类:称为最终类inal 修饰的方法:称为最终方法final 修饰的变量
    不能被继承不能被重写只能赋值一次
    • final 修饰基本类型的变量,赋值后不可改变。
    • final 修饰引用类型的变量,变量存储的地址不能改变,但地址所指向对象的内容可以改变

    拓展:final的使用场景:工具类(工具类用final修饰更规范)

    抽象类、接口(特殊的抽象类)

    -- 抽象类
    -- abstract:抽象。可以修饰 类、方法
    -- abstract 修饰的类:抽象类。
    -- abstract 修饰的方法:抽象方法。
    
    -- 【抽象类的特点】
    --     1. 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类。
    --     2. 类该有的成员(成员变量、方法、构造器),抽象类也可以有。
    --     3. 抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现。
    --     4. 一个类继承抽象类后,必须重写抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
    
    
    -- 接口:特殊的抽象类,接口内只能定义常量和抽象方法
    -- 【语法】
    -- public interface 接口名{
    --      常量
    --      抽象方法
    -- }
    
    -- 接口是用来被类实现的(也就是被类继承)。实现接口的类称为实现类
    -- 一个类能实现多个接口(接口就是干爹),一个接口可被多个类实现(类可以理解成干儿子)。
    -- 实现类实现多个接口,必须重写每个接口的所有抽象方法,否则必须将实现类定义成抽象类。
    
    -- 【接口的特点】
    --     1. 接口不能有构造方法,不能创建对象
    --     2. 接口不能有成员变量,只能有常量(默认是public static final)
    --     3. 接口内的方法都是抽象方法(默认是public abstract)
    --     4. 接口可以继承接口,接口可以多继承
    --     5. 接口不能有静态代码块和构造代码块
    
    -- 【接口的好处】
    --     1. 弥补类单继承的不足,类可以同时实现多个接口。
    --     2. 让程序面向接口编程,这样就不用关心实现细节,也可以灵活方便的切换各种实现。

      1.  定义一个接口

    // 接口
    public interface JieKou01 {
        // 定义一个常量
        public static final int TEST_NUM = 10;
    
        // 定义一个抽象方法
        public abstract void test();
    }

      2.  定义一个类(实现上面的接口)。实现接口后的类:称  实现类

    // 实现类:实现接口的类称为实现类
    public class JieKou_ShiXianLei implements JieKou01{
        // 重写接口的所有抽象方法
        @Override
        public void test(){
            System.out.println("重写接口的所有抽象方法");
        }
    }

    内部类

    内部类:如果一个类定义在另一个类的内部,则这个类是内部类。

    枚举

    泛型

    常用API

    API:应用程序编程接口。就是别人写好的程序,程序员可以直接调用,以解决问题。

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值