面向对象及abstract,final,static关键字的学习

本文详细介绍了Java中的面向对象特性,包括数据封装,如JavaBean规范,构造方法的作用,以及权限修饰符的使用。接着讨论了继承的概念,重写和重载方法的区别,以及抽象类和abstract方法的关键特性。此外,还探讨了final关键字的用途,如防止变量重赋值和阻止方法重写,并解释了static修饰符在静态变量、静态方法和静态代码块中的应用。
摘要由CSDN通过智能技术生成

1. 概述

1.两大任务:

1. 数据的载体

2. 方法的载体【重点】

面向对象三大特征:
1. 封装

不限于 JavaBean 规范封装,包括方法封装,工具封装,框架封装...

2. 继承

Java 继承的模式是一个类单继承模式 接口多继承模式

继承关注的重点是【方法继承,保证方法的延续性,沿用性,以及数据类型的统一】

3. 多态

程序员经典理解:编译看左,运行看右

2. 面向对象—>封装

2.1 JavaBean 规范实体类要求

要求所有成员变量全部 private 私有化修饰
必须提供所有成员变量对应的 getter and setter 方法
必须提供无参数构造方法
案例:

public class Student {
    // 私有化成员变量 Field
    private Integer id;
    private String name;
    private Integer age;
    // boolean 类型成员变量对应的 getter 方法是 is开头 ==> isGender
    // Boolean 包装类型还是 get 和 set 开头
    private boolean gender; //private Boolean gender;
   	
    
    // 构造方法 Constructor
    public Student() {}
    
    public Student(Integer id, String name, Integer age) {
        // this 关键字目前的作用是区分成员变量和参数变量
        // this 表示 new + 当前构造方法实例化的对象本身
        this.id = id;
        this.name = name;
        this.age = age;
    }
    
    // getter and setter
    public Integer getId() {
        return id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }
    
    ...
}

2.2构造方法作用:

1. 提供数据类型,构造方法的名称要求必须是类名,JVM 会根据当前构造方法的名称 明确实例化对象的数据类型是哪一个,计算得到对应所需的内存空间

2. 用于初始化类对象成员变量数据内容

new:

1. 在内存堆区根据当前数据类型所需申请对应的内存空间

2. 申请的内存空间进行数据擦除

new + 构造方法 是实例化对象的一种形式,也是最为基础的形式。

2.3 权限修饰符

权限修饰符

作用域or作用范围

public

可以在任何地方使用

protected

本类中,同一个包中,不同包的子类中

private

只能在本类中使用

package

默认修饰符,可以省略。在本类中和同包中可以使用

friendly

同一个package内的其它所有classes都可以访问friendly成员,但对package以外的classes则形同private。

3. 面向对象—>继承

3.1 基本格式和特征

基本格式

class A extends B {

}

A 类是 B 类的一个子类

B 类是 A 类的唯一父类

特征:

1. 父类中非私有化成员(成员变量和成员方法)都可以继承给子类使用

2. 父类中私有化成员子类无法获取

3. 实例化子类对象会默认调用父类的无参数构造方法。

4.父类构造方法是用于继承给子类数据内容对应内存空间初始化操作使用的方法。

5.JVM 设计规则【先有父,再有子】

3.2 重写方法 Override method

3.2.1 重写方法的前提

子类继承父类方法,父类方法无法满足子类的特征需求,可以进行重写操作。

3.2.2重写操作要求:

1. 要求方法声明完全一致,包括 返回值类型,方法名和形式参数列表

2. 权限修饰符子类权限必须大于等于父类

父类 public 子类允许 public

父类 protected 子类允许 public protected

3. Java 原作者要求,重写方法必须有 @Override 注解

@Override 是开启重写语法格式严格检查

3.3 重载方法 Reload

3.3.1重载方法的前提

同一个类,或者同一个接口内

3.3.2重载方法要求

1. 方法名必须一致

2. 方法形式参数列表数据类型必须不同

3. 返回值类型无限制

4. 权限修饰符无限制

/*
方法重载 Reload
 */
public static void test(int num) {
    System.out.println(num);
}
public static void test(int num1, int num2) {
    System.out.println(num1 + num2);
}
private static void test(float num) {
    System.out.println(num);
}
重写和重载的区别

相同点

不同点

重写和重载方法名都要求一致

重写方法参数类型要与父类方法一致,重载方法参数列表数据类型必须不同

重写方法返回值类型必须与父类方法一致,重载方法无限制

重写方法权限修饰符子类必须大于父类,重载方法无限制

3.4 abstract 关键字【重点】

解决的问题 开启强制实现限制。
abstract 关键字修饰的方法有且只有方法声明,要求子类或者实现类完成方法体。
3.4.1abstract方法的特征

1. abstract 关键字修饰的方法没有方法体。

2. abstract 方法有且只能定义在 abstract 修饰的类内 或者 interface 接口内。

3. 一个非 abstract 类继承 abstract 类或 interface 接口,必须【实现 implement】对应abstract 方法。

4. abstract 修饰的类无法实例化对象,假设获取到 abstract 修饰抽象类实例化对象,无法执行有可能存在的没有方法体的 abstract 方法。

5.阿里巴巴开发规约要求(AJCG) abstract 修饰的类推荐使用 Abstract 或者 Base 类名开头

4. 面向对象基础操作

4.1涉及到的内容

1. 类型设计

2. 类对象实例化操作

3. 类对象/类名调用方法操作,功能执行和数据操作【重点】

类型设计
package com.qfedu.a_object;

/**
 * 自定义的数组工具类
 *
 * @author Anonymous 2023/2/24 9:45
 */
public class MyArrayUtils {
    /**
     * 自定义方法,实现 int 类型数组数据展示功能
     *
     * @param arr int 类型数组
     */
    public static void printIntArray(int[] arr) {
        /*
        增强 for 循环
            for (int i = 0; i < arr.length; i++) {}
            for (int i : arr) {}

            for (当前数组/集合存储的数据类型 在循环中使用的临时变量 : 数组/集合)
                增强 for 循环自动遍历整个数组/集合,临时变量存储遍历数组对应的数据
         */
        for (int i : arr) {
            System.out.println(i);
        }
    }
}

4.2. 继承

4.2.1 实例化子类对象调用父类无参数构造方法
class GrandFather {
    public GrandFather() {System.out.println("GrandFather类 无参数构造方法");}
}

class Father extends GrandFather {
    public Father() {System.out.println("Father类 无参数构造方法");}
}

class Son extends Father {
    public Son() {System.out.println("Son 类无参数构造方法");}
}

/**
 * @author Anonymous 2023/2/24 9:51
 */
public class Demo2 {
    public static void main(String[] args) {
        Son son = new Son();
        /*
        Father类 无参数构造方法
        Son 类无参数构造方法

        Java 中的规定,实例化子类对象,会自动调用父类无参数构造方法,用于初始化父类可以给予
        子类使用的数据内容,方法空间。【注意】这里父类构造方法没有创建父类对象的能力。
        */
        System.out.println(son);
    }
}

5. final 关键字

final 可以修饰类,成员变量,成员方法,局部变量

5.1 final 修饰成员变量

final 修饰的成员变量要求必须进行初始化操作
【解决方案】
直接初始化赋值
【有参】数构造方法,实例化对象过程中初始化 final 修饰成员变量
final 修饰的成员变量一旦被赋值无法二次修改
package com.qfedu.b_final;

class A {
    /*
    Variable 'msg' might not have been initialized
    msg 变量可能尚未初始化
    【解决方案】
        1. 直接初始化赋值
        2. 【有参】数构造方法,实例化对象过程中初始化 final 修饰成员变量
     */
    public final String msg = "直接赋值 final 修饰成员变量";
}

class B {
    public final String info;

    /**
     * 当前类有且只有有参数构造方法,并且当前有参数构造方法参数内容
     * 是给予当前类内 final 修饰的成员变量 info 进行初始化赋值操作
     * 可以满足在用户使用 info 之前可以已经赋值准备好对应的数据内容。
     *
     * @param info 赋值 final 修饰成员变量对应的参数
     */
    public B(String info) {
        this.info = info;
    }
}

/**
 * @author Anonymous 2023/2/24 10:32
 */
public class Demo1 {
    public static void main(String[] args) {

        A a = new A();
        // final 修饰的成员变量无法进行二次赋值操作。
        // a.msg = "测试";
        System.out.println(a.msg);

        B b = new B("通过有参构造方法赋值 final 修饰成员变量");
        System.out.println(b.info);
    }
}

5.2 final 修饰成员方法

final 修饰成员方法不允许被子类重写
一般用于框架,业务核心代码内容修饰,不允许修改/重写代码内容
package com.qfedu.b_final;

class C {
    public final void test() {
        System.out.println("C 类 test 成员方法");
    }
}

class D extends C {
    /*
    'test()' cannot override 'test()' in 'com.qfedu.b_final.C'; overridden method is final

    final 修饰的成员方法,子类不允许重写。
        一般用于框架,业务核心代码内容修饰,不允许修改/重写代码内容

    @Override
    public void test() {
        System.out.println("D 类继承 C 类重写 test 方法");
    }
    */
}
/**
 * @author Anonymous 2023/2/24 10:44
 */
public class Demo2 {
    public static void main(String[] args) {
        new D().test();
    }
}

5.3 final 修饰类

final 修饰类没有子类
在开发中基本类型不允许继承重新定义/制定规则。
例如:
Java 中是 String 类,基本数据类型的包装类 Integer Float Double
package com.qfedu.b_final;

final class  E {

}

/*
Cannot inherit from final 'com.qfedu.b_final.E'
不能继承一个 final 修饰类
final 修饰类没有子类
   在开发中基本类型不允许继承重新定义/制定规则。
   例如:
        Java 中是 String 类,基本数据类型的包装类 Integer Float Double

 */
//class F extends E {
//
//}

/**
 * @author Anonymous 2023/2/24 10:50
 */
public class Demo3 {
}

5.4 final 修饰局部变量

final 修饰的局部变量首次赋值允许,后期不允许二次赋值
package com.qfedu.b_final;

/**
 * @author Anonymous 2023/2/24 10:54
 */
public class Demo4 {
    public static void main(String[] args) {
        final int num ;
        /*
        final 修饰的局部变量,【首次】赋值没有任何的问题
            1. 定义时候初始化
            2. 后期代码赋值
         */
        num = 10;
        System.out.println(num);

        /*
        Cannot assign a value to final variable 'num'
        不能重新赋值一个 final 修饰的局部变量(local variable) num
         */
        num = 20;
    }
}

5.5 final 小面试题

package com.qfedu.b_final;

class Person {
    public String name;
    public Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

/**
 * @author Anonymous 2023/2/24 10:58
 */
public class Demo5 {
    public static void main(String[] args) {
        final Person person = new Person("张三", 66);

        System.out.println(person.name);
        System.out.println(person.age);
        /*
        以下代码错误的是:
            person.age = 20;
            person.name = "李四";
            person = new Person();
        答案
            全错
            1 2 错 3 对 
            1 2 对 3 错 【正确答案】
            【注意】
                final 修饰引用数据类型变量,指向不可变,指向数据空间内容可变
             从底层逻辑分析,final 修饰的为引用数据类型变量,当前变量存储数据不可变,变量存储
             内容是一个【地址】,表示地址无法修改,但是对应地址指向的数据空间内容,没有被 final 
             修饰,可以修改数据内容。
         */
    }
}

5.6 final 使用总结

1. final 修饰类一般是架构中的底层核心代码,基本数据类型 2. final 修饰成员变量一般用于常量使用,并且在开发中大量存在,例如: 订单状态,用户状态,设备状态 3. final 修饰局部变量一般用于常量数据使用,同时是为了避免【生命周期问题】。 4. final 修饰成员方法是核心业务逻辑方法

6. static【重点 难点】

6.1 类加载【重点】

程序所需资源加载过程
【核心】
三个重点:静态成员变量,静态成员方法,静态代码块
一个原则: 类加载过程中 static 修饰内容完成准备工作

6.2 static 修饰静态变量

  • 语法特征: 1. static 修饰的静态成员变量在内存的【数据区】 2. static 修饰的静态成员变量在整个代码的运行周期中有且只有一个。 3. static 修饰的静态成员变量在类文件加载阶段,需要准备就绪,已具备数据提供能力和数据存储能力。 4. static 修饰的静态成员变量别名【类变量】,语法建议直接通过类名操作 例如: Integer.MAX_VALUE ==> public static final int MAX_VALUE = 0x7FFFFFFF; 5. 【使用建议】 静态成员变量最好不要和类对象有相关性。 静态成员变量生命周期从类加载开始到程序结果 类对象是从实例化对象开始,到 JVM GC 回收结束,可以实例化对象相当于程序开始运行,晚于静态成员变量加载。 GC 收回是在程序退出之前,完成内存收回工作之后,静态成员变量销毁。

package com.qfedu.c_static;

class A {
    /*
    static 修饰静态成员变量
     */
    public static int num = 10;
}

/**
 * @author Anonymous 2023/2/24 11:49
 */
public class Demo1 {
    public static void main(String[] args) {
        // 通过类名可以直接调用当前静态成员变量
        System.out.println(A.num);

        // 当前情况下,匿名对象生命周期有且只在当前行,超出对象销毁
        new A();

        /*
        Static member 'com.qfedu.c_static.A.num' accessed via instance reference
        【警告】
            static 修饰的静态内存,通过实例化对象引用,IDE(Eclipse IDEA MyEclipse) 工具不建议

         */
        System.out.println(new A().num);

        // 对象已销毁,但是静态成员变量依然可以通过类名直接调用。
        System.out.println(A.num);
    }
}

6.3 static 修饰静态成员方法

  • 语法特征: 1. 静态成员方法使用 static 修饰 2. static 修饰的静态成员方法不允许使用类内的【非静态成员】 static 修饰的静态成员方法在类文件加载阶段已具备执行能力,方法内有非静态相关内容,无法执行,因为 非静态成员需要实例化对象调用操作,加载过程中没有相关的对象存在。【没有对象】 3. static 修饰的静态成员方法可以直接使用类内的其他静态资源。 4. 静态成员方法常用于【工具类】方法封装 Arrays 静态成员方法是可以通过类名直接调用,可以摆脱类对象的限制,执行效率较高。无需考虑对象实例化过程,以及销毁对象过程的时间和内存空间的占用浪费。 5. 静态成员方法推荐使用类名直接调用,也可以称之为【类方法】

6.4 static 修饰静态代码块

6.4.1 补充知识点
代码块有三种形式
构造代码块【不多见】
局部代码块【已淘汰】
静态代码块【目前还有很大作用】
构造代码块

Java 编译器在编译代码的过程中,会将构造代码块内容放入到每一个构造方法的【第一行】

局部代码块

局部代码块,利用 Java 局部变量特征,压缩局部变量生存空间。

num2 作用范围和生命周期都在 大括号范围以内。

提高内存的复用度,加快 GC 垃圾回收。

6.4.2 静态代码块特征
  • 1. 静态代码块在类文件加载阶段一定执行!!!并且有且只执行一次。 2. 静态代码块可以调用类内的其他静态资源 3. 静态代码块不可以调用类内的非静态资源 4. 静态代码块一般用于程序初始化操作,预处理操作,项目运行前准备工作。 案例: 配置资源读取 配置文件读取 相关资源加载

6.5 static 面试题

package com.qfedu.c_static;

/**
 * 在代码块中所有的静态 static 修饰内容平级,按照基础的从上到下顺序执行加载。
 * 并且每一个 static 修饰内容都需要执行完各自的需求
 *      静态代码块【执行/运行】
 *      静态成员变量 【具备数据存储和数据提供能力】
 *      静态成员方法 【具备执行能力】
 *
 * 静态成员变量对于当前类而言有且只有一个,非静态成员变量属于每一个实例化对象,个数不限制。
 *
 * @author Anonymous 2023/2/24 15:47
 */
public class Demo5 {
    static Demo5 d1 = new Demo5();
    static Demo5 d2 = new Demo5();

    {
        System.out.println("构造代码块");
    }

    static {
        System.out.println("静态代码块");
    }

    public Demo5() {
        System.out.println("构造方法");
    }

    public static void main(String[] args) {
        /*
        构造代码块
        构造方法
        构造代码块
        构造方法
        静态代码块
        构造代码块
        构造方法
         */
        Demo5 demo5 = new Demo5();
    }
}
class Father {
    static {
        System.out.println("Father 静态代码块");
    }

    static Father f = new Father();

    public Father() {
        System.out.println("Father 类构造方法");
    }
}

class Son extends Father {
    static {
        System.out.println("Son 静态代码块");
    }

    static Father f = new Father();

    public Son() {
        System.out.println("子类构造方法");
    }
}

/**
 * @author Anonymous 2023/2/24 16:01
 */
public class Demo6 {
    public static void main(String[] args) {
        Son son = new Son();
        /*
        Father 静态代码块
        Father 类构造方法
        Son 静态代码块
        Father 类构造方法
        Father 类构造方法
        子类构造方法
         */
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

中分头背带裤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值