• 【第一阶段:java基础】第8章:面向对象编程高级-1(P333-P393)static、main、代码块、单例设计模式


    本系列博客是韩顺平老师java基础课的课程笔记,B站:课程链接,吐血推荐的一套全网最细java教程,获益匪浅!

    类变量和类方法

    类变量/静态变量

    • 基本介绍:静态变量被同一个类的所有对象共享,在类加载的时候就生成了
    • 内存布局:在jdk8以前,静态变量存放在方法区,jdk8以及jdk8以后,放在堆中
    • 语法:访问修饰符 static 数据类型 变量名; 或者 static 访问修饰符 数据类型 变量名
    • 访问方法:可以通过类名.类变量名 或者是对象名.类变量名来访问 (前提是满足访问修饰符的访问权限和范围)
    • 细节:静态变量是类加载的时候就创建的,所以即使没有创建对象实例,也可以通过类名.类对象名来访问
    • 在这里插入图片描述

    类方法/静态方法

    • 语法:访问修饰符 static 返回类型 方法名() {} 或者把static放在最前面
    • 访问方法:可以通过类名.类变量名 或者是对象名.类变量名来访问 (前提是满足访问修饰符的访问权限和范围)
    • 经典使用场景:当方法中不涉及到任何和对象相关的成员,则可以将方法设计成静态方法,这样我们不需要创建对象就可以使用了,提高开发效率(比如说工具类方法:打印一维数组,冒泡排序等)
    • 细节(静态方法与普通方法的关系)
      • 类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法区
      • 类方法可以通过类名调用,普通方法只能通过对象名调用
      • 类方法中不允许使用和对象有关的关键字,比如this和super,普通方法可以
      • 类方法中只能访问静态成员(变量和方法),普通方法都可以访问
      • static只可以修饰内部类,不可以修饰外部类

    为什么static只修饰外部类不可以修饰内部类:1️⃣static修饰的为类成员会随着类的加载而加载,比如静态代码块,静态成员,静态方法(这里只是加载,并没有调用)等等,可以想象一下,如果把一个Class文件中的外部类设为static,目的难道是让这个类随着应用的启动而加载吗?如果在这次使用过程中根本没有使用过这个类,那么是不是就会浪费内存。这样来说设计不合理,总而言之,设计不合理的地方,Java是不会让它存在的。2️⃣而为什么内部类可以使用static修饰呢,因为内部类算是类的成员了,如果没有使用静态来修饰,那么在创建内部类的时候就需要先有一个外部类的对象,如果我们一直在使用内部类,那么内存中就会一直存在外部类的引用,而我们有时候只需要使用内部类,不需要外部类,那么还是会浪费内存,甚至会造成内存溢出。使用static修饰内部类之后,内部类在创建对象时就不需要有外部类对象的引用了。💥最终结论就是:static可以用来修饰内部类,但是不可以用来修饰外部类

    • 练习题
    • 在这里插入图片描述
      在这里插入图片描述

    理解main方法语法

    • public static void main(String[] args)

    • main方法是java虚拟机在调用,所以它的访问权限必须是public

    • java虚拟机在执行main()方法时不必创建对象,所以它的方法必须是static

    • 该方法接受String类型的数组参数,该数组中保存执行java命令时,传递给所运行的类的参数

    • args是在java执行程序时通过命令行传入的 (java Hello tom jack smith)

    • 在这里插入图片描述

    • main方法中,可以直接调用main 方法所在类的静态方法和静态属性;但是不能直接访问该类中的非静态成员,必须创建一个该类的实例对象后,才能通过这个对象去访问非静态成员

    代码块

    • 代码块又称为初始化块,属于类中的成员,类似于方法,将逻辑语句封装在方法体中,通过{}包围起来
    • 但和方法不同,没有方法名,返回和参数,只有方法体,而且不用通过对象或类显示调用,而是加载类时,或创建对象时隐式调用
    • 语法:[修饰符]{代码};

    注意事项

    • 修饰符可选,要写的话只能写static
    • 代码块分为两类,用static修饰的是静态代码块,没有static修饰的就时普通代码块
    • 逻辑语句可以为任何逻辑语句(输入 输出 方法调用 循环 判断等)
    • ;号可以写上也可以忽略

    好处

    • 相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操

    • 如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用性

    • 在这里插入图片描述

    • 代码块的调用优先于构造器

    细节

    • 类在什么时候被加载?

      • 创建对象实例时 new
      • 创建子类对象实例,父类会被加载
      • 使用类的静态成员时
      • 在这里插入图片描述
    • 普通代码块与静态代码块的调用

      • 静态代码块随着类的加载而执行,但是只会执行一次
      • 在这里插入图片描述
    • 总结

      • 静态代码块在类加载时调用,类只会被加载一次
      • 普通代码块在类创建时调用,创建一次就会被调用一次
      • 普通代码块,每创建一个对象就执行一次(隐式调用),和类的加载没有关系,所以如果只是使用类的静态成员,普通代码块并不会被执行。【可以将普通代码块当做构造器的补充,调用了构造器就会调用普通代码块】
    • 创建一个对象时,在一个类中的调用顺序是

        1. 调用静态代码块和静态属性初始化:两者的优先级是一样的,如果存在多个静态代码块和静态属性初始化,则按照他们的定义顺序调用
        1. 普通代码块和普通属性初始化:两者的优先级是一样的,如果存在多个普通代码块与呕普通属性初始化,则按照他们的定义顺序调用
        1. 调用构造器
      • 在这里插入图片描述
    • 构造器中隐含了本类普通代码块的调用

      • 构造器在最前面隐含了两个步骤:(1)super() (2)调用普通代码块
      • 静态相关的代码块和属性初始化,在类加载时,就执行完毕了。
        在这里插入图片描述
    • 创建一个子类对象时,(静态)代码块,(静态)属性初始化,以及构造器的调用顺序 🍓考点

        1. 父类的静态属性、静态代码块
        1. 子类的静态属性、静态代码块
        1. 父类的普通属性和普通代码块初始化
        1. 父类的构造器
        1. 子类的普通属性和普通代码块初始化
        1. 子类的构造方法
      • 静态代码块只能直接调用静态成员,普通代码块可以调用任意成员
    • 练习题

    • 在这里插入图片描述

    单例设计模式

    • 设计模式(23种):设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。

    • 单例模式: 采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法

    饿汉式

    1. 构造器私有化(防止直接new对象)
    2. 类的内部创建一个静态对象(因为需要在静态方法中返回对象,所以这个对象是静态的)
    3. 向外暴露一个静态的公共方法
    • 之所以叫做饿汉式是因为,随着类的加载会提早创建对象。很可能会造成创建了对象但是没有使用,造成浪费
    • 在这里插入图片描述

    懒汉式

    1. 构造器私有化
    2. 定义一个static的静态属性对象
    3. 提供一个public的static方法,可以返回对象
    • 懒汉式只有在用户调用getInstance时才会创建对象,多次调用返回的是同一个对象
    • 在这里插入图片描述

    饿汉式VS懒汉式

    • 两者主要的区别在于创建对象的时机不同,饿汉式是在类加载的时候创建对象实例,而懒汉式是在使用时才创建
    • 饿汉式不存在线程安全问题,懒汉式存在线程安全问题
    • 饿汉式存在浪费资源的可能
    • 在javaSE标准类中,java,lang,Runtime就是经典的单例模式
  • 相关阅读:
    Redis7的数据结构
    如何快速新建多个不同名称文件夹?
    高级架构师_Docker_第2章_ Docker核心原理_ 第5节 Dockerfile简介
    CentOS7搭建FLV和RTMP流媒体服务器
    漫谈 Java 平台上的反应式编程
    NSSCTF做题(6)
    Docker通信全视角:原理、实践与技术洞察
    Java刷题面试系列习题(十一)
    2023最新版Android逆向教程——第4天:真机环境的配置
    Redis集群-哨兵模式原理(Sentinel)
  • 原文地址:https://blog.csdn.net/qq_39328436/article/details/127928937