【JavaSE】类和对象(中)

类和对象(中)

    • 4. this引用
      • 4.1 为什么要有this引用
      • 4.2 什么是this引用
      • 4.3 this引用的特性
    • 5. 对象的构造及初始化
      • 5.1 如何初始化对象
      • 5.2 构造方法(构造器)
        • 5.2.1 概念
        • 5.2.2 特性
      • 5.3 默认初始化
      • 5.4 就地初始化
    • 6. 封装
      • 6.1 封装的概念
      • 6.2 访问限定符
      • 6.3 封装扩展之包
        • 6.3.1 包的概念
        • 6.3.2 导入包中的类
        • 6.3.3 自定义包
        • 6.3.5 常见的包
        • 6.3.6 封装操作举例

4. this引用

4.1 为什么要有this引用

先看一个日期类的例子:

public class Date {
    public int year;
    public int month;
    public int day;
    public void setDay(int y, int m, int d){
        year = y;
        month = m;
        day = d;
    }
    public void printDate(){
        System.out.println(year + "/" + month + "/" + day);
    }
    public static void main(String[] args) {
    // 构造三个日期类型的对象 d1 d2 d3
        Date d1 = new Date();
        Date d2 = new Date();
        Date d3 = new Date();
    // 对d1,d2,d3的日期设置
        d1.setDay(2020,9,15);
        d2.setDay(2020,9,16);
        d3.setDay(2020,9,17);
    // 打印日期中的内容
        d1.printDate();
        d2.printDate();
        d3.printDate();
    }
}
//----------------
//打印
2020/9/15
2020/9/16
2020/9/17

但是三个对象都在调用setDate和printDate函数,但是这两个函数中没有任何有关对象的说明,setDate和printDate函数如何知道打印的是那个对象的数据呢

其实在成员方法的第一个形参中默认隐藏了一个this,this引用的是调用成员方法的对象。

4.2 什么是this引用

**this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。**只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

public class Date {
    public int year;
    public int month;
    public int day;
    public void setDay(int year, int month, int day){
        this.year = year;
        this.month = month;
        this.day = day;
    }
    public void printDate(){
        System.out.println(this.year + "/" + this.month + "/" + this.day);
    }
}

注意:this引用代表的是的是调用成员方法的对象。

每个成员方法括号中的第一个参数默认是this

image-20221119134555767

注意,我们要习惯使用this。

image-20221119135849351

4.3 this引用的特性

  1. this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型

  2. this只能在"成员方法"中使用

  3. 在"成员方法"中,this只能引用当前对象,不能再引用其他对象

  4. this是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法
    对象的引用传递给该成员方法,this负责接收

5. 对象的构造及初始化

5.1 如何初始化对象

通过前面知识点的学习知道,在Java方法内部定义一个局部变量时,必须要初始化,否则会编译失败。

public static void main(String[] args) {
    int a;
    System.out.println(a);
}
// Error:(26, 28) java: 可能尚未初始化变量a

要让上述代码通过编译,非常简单,只需在正式使用a之前,给a设置一个初始值即可。如果是对象:

public class Date {
    public int year;
    public int month;
    public int day;
    public void setDay(int y, int m, int d){
        this.year = y;
        this.month = m;
        this.day = d;
    }
    public void printDate(){
        System.out.println(year + "/" + month + "/" + day);
    }
}
public static void main(String[] args) {
    Date d = new Date();
    d.printDate();
    d.setDate(2021,6,9);
    d.printDate();
}
// 代码可以正常通过编译

需要调用之前写的SetDate方法才可以将具体的日期设置到对象中。通过上述例子发现两个问题:

  1. 每次对象创建好后调用SetDate方法设置具体日期,比较麻烦,那对象如何快捷进行初始化呢?
  2. 局部变量必须要初始化才能使用,为什么字段声明之后没有给值依然可以使用?

这两个问题就涉及到了构造方法和默认初始化的问题。

5.2 构造方法(构造器)

5.2.1 概念

构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。

什么是构造方法?

构造方法非常特殊:这个方法没有返回值,方法名和类名是一样的。

如果我们没有在类中写任何的构造方法,那么Java会帮我们提供一个默认的不带参数的构造方法。

public class Date {
    public int year;
    public int month;
    public int day;
    public void setDay(int y, int m, int d){
        year = y;
        month = m;
        day = d;
    }
    public void printDate(){
        System.out.println(year + "/" + month + "/" + day);
    }
    Date() {
        System.out.println("这个是构造方法,在实例化对象的时候就会进行调用");
    }
    //
    //
    public static void main(String[] args) {
        Date date1 = new Date();
    }
}
//--------------
//编译器运行结果为
//这个是构造方法,在实例化对象的时候就会进行调用

当然在一个类中没有写构造方法的话,Java会默认提供。

但是一个类当中写了构造方法的话,java就不会提供了。

看看效果

public class Date {
    public int year;
    public int month;
    public int day;
    public void setDay(int y, int m, int d){
        year = y;
        month = m;
        day = d;
    }
    public void printDate(){
        System.out.println(year + "/" + month + "/" + day);
    }
    public Date() {
        System.out.println("这个是构造方法,在实例化对象的时候就会进行调用");
    }
    public Date(int year ,int month ,int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
    //
    //
    public static void main(String[] args) {
        Date date1 = new Date(11,11,11);
        date1.printDate();
    }
}
//--------------
//编译器运行结果为
//11/11/11

这样我们就可以通过构造方法在进行对象实例化的过程中进行成员变量的初始化。

至于我们写了两个Date函数,那么这两个函数就属于重载关系

public Date() {
    System.out.println("这个是构造方法,在实例化对象的时候就会进行调用");
}
public Date(int year ,int month ,int day) {
    this.year = year;
    this.month = month;
    this.day = day;
}

重载:方法名相同,参数列表不同,与返回值无关。

我们可以说当一个对象调用完构造函数,那么这个对象就生成了。

因为生成一个对象分为两步1. 为对象分配内存 2. 调用合适的构造方法

补充:

  1. 对于构造方法,我们不能进行添加void因为如果添加了返回值的话,那么就不属于我们的构造方法了。

  2. 如果自己没有写构造函数,那么编译器会提供一个默认的不带任何参数的构造方法。

5.2.2 特性

  1. 名字必须与类名相同

  2. 没有返回值类型,设置为void也不行

  3. 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)

  4. 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)

  5. 如果用户没有显式定义,编译器会生成一份默认的构造方法,生成的默认构造方法一定是无参的。一旦用户定义,编译器则不再生成。

如果生成了一个带有参数的构造方法,那么一定要在对象实例化的过程中进行传参,否则会报错。

  1. 构造方法中,可以通过this调用其他构造方法来简化代码

在这个过程中this代表的是调用当前对象的其他构造方法。

public class Date {
    public int year;
    public int month;
    public int day;

    public void printDate(){
        System.out.println(year + "/" + month + "/" + day);
    }
    public Date() {
        this(11,11,11);
    }
    public Date(int year ,int month ,int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
    public static void main(String[] args) {
        Date date1 = new Date();
        date1.printDate();
    }
}
//------------
//编译器运行结果为
//11/11/11

但是在调用其他构造方法的时候有一定的要求:

  1. 那么就是this语句一定要放在构造方法中作为第一条语句。不然会报错。

image-20221119163345957

  1. 只能在构造方法内部才能使用,不能在其他方法中使用。

  2. 不能形成环,否则进行反复调用构造函数,形成封闭循环

image-20221119164045666

  1. 绝大多数情况下构造函数使用public来修饰,特殊场景下会被private修饰。

至于这个我们先不管,以后会讲。

总结

this.date 访问当前对象的成员变量

this.func() 访问当前对象的成员方法

this() 调用当前对象的其他构造方法

this不能调用静态static修饰的成员方法和变量这个后面我们再说

5.3 默认初始化

为什么局部变量在使用时必须要初始化,而成员变量可以不用呢?

要搞清楚这个过程,就需要知道 new 关键字背后所发生的一些事情:

Date d = new Date(2021,6,9);

在程序层面只是简单的一条语句,在JVM层面需要做好多事情,下面简单介绍下:

  1. 检测对象对应的类是否加载了,如果没有加载则加载

  2. 为对象分配内存空间

  3. 处理并发安全问题
    比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突

  4. 初始化所分配的空间
    即:对象空间被申请好之后,对象中包含的成员已经设置好了初始值,比如:

数据类型默认值
byte0
char‘\u0000’
short0
int0
long0L
booleanfalse
float0.0f
double0.0
referencenull
  1. 设置对象头信息(关于对象内存模型后面会介绍)
  2. 调用构造方法,给对象中各个成员赋值

所以在调用构造函数进行初始化之前,我们就会进行赋值为默认值。

补充

public只是权限的问题。(只提一下)

局部变量:定义在方法内部的变量。

成员变量:定义在类的内部的变量,定义在成员方法的外部。

定义在成员方法内部的变量就叫做局部变量。

image-20221119173212258

5.4 就地初始化

在声明成员变量时,就对成员变量设置初始值。

public class Date {
    public int year = 1900;
    public int month = 1;
    public int day = 1;
    //进行就地初始化
    public Date(){
    }
    public Date(int year, int month, int day) {
    }
    public static void main(String[] args) {
        Date d1 = new Date(2021,6,9);
        Date d2 = new Date();
    }
}

当然这个除非是业务需求,不然没有提别大的意义,如果成员变量会进行修改,那么就地初始化相当于进行了一个默认值的定义。

6. 封装

6.1 封装的概念

**面向对象程序三大特性:封装、继承、多态。**而类和对象阶段,主要研究的就是封装特性。

何为封装呢?

简单来说就是套壳屏蔽细节。把类的实现细节进行隐藏,对外只提供一些交互的接口。

封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互

比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器,USB插孔等,让用户来和计算机进行交互,完成日常事务。但实际上:电脑真正工作的却是CPU、显卡、内存等一些硬件元件。

然而要进行封装就涉及到了访问限定符。

6.2 访问限定符

Java中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,更符合人类对事物的认知,而访问权限用来控制方法或者字段能否直接在类外使用。Java中提供了四种访问限定符:

private 默认权限 protected public

默认权限就是我们什么都没加的时候的使用默认权限访问限定符。

public class Date {
	int year;
}

private

权限非常小,被修饰之后只能在自己的类中进行使用。

class Student {
    public String name;

    public void show() {
        System.out.println("姓名" + name);
    }
}

image-20221119183711913

默认权限default

只能在自己的包中进行使用

这就涉及到了包的概念,如果不懂包是什么,可以先跳过这块继续看下一块的内容。

image-20221119205824167

protect和public以后再讲,因为涉及到了子类的知识

6.3 封装扩展之包

6.3.1 包的概念

要了解封装就要了解权限,要了解权限,就要了解包。

在面向对象体系中,提出了一个软件包的概念,即:为了更好的管理类,把多个类收集在一起成为一组,称为软件包。有点类似于目录。比如:为了更好的管理电脑中的歌曲,一种好的方式就是将相同属性的歌曲放在相同文件下,也可以对某个文件夹下的音乐进行更详细的分类。

image-20221119191624982

包就像文件夹一样,一个文件夹当中不能有相同的文件名,不同文件夹下可以有相同的文件名。

在Java中也引入了包,包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式,比如:一个包中的类不想被其他包中的类使用。包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在
不同的包中即可。

6.3.2 导入包中的类

Java 中已经提供了很多现成的类供我们使用. 例如Date类:可以使用java.util.Arrays导入java.util这个包中的Arrays类.

public class Test {
    public static void main(String[] args) {
        int[] arr = {1,2,3};
        java.util.Arrays.toString(arr);
    }
}

但是这种方法比较麻烦,我们可以使用import语句导入包

import java.util.Arrays;  // 导包

public class Test {
    public static void main(String[] args) {
        int[] arr = {1,2,3};
        Arrays.toString(arr);  
    }
}

如果需要使用java.util中的其他类, 可以使用import java.util.*

import java.util.*;
public class Test {
    public static void main(String[] args) {
        int[] arr = {1,2,3};
        Arrays.toString(arr);
    }
}

import java.util.*不是把里面的所有的类都导进来,是随取随用。用到哪个类,就会导哪个类。

但是我们更建议显式的指定要导入的类名. 否则还是容易出现冲突的情况.

image-20221119193240618

import java.util.*;
import java.sql.*;
public class Test {
    public static void main(String[] args) {
// util 和 sql 中都存在一个 Date 这样的类, 此时就会出现歧义, 这个时候编译器就不知道该导入哪个包了,毕竟两个包中都有Date类,所以编译出错
        Date date = new Date();
        System.out.println(date.getTime());
    }
}
//--------------
// 编译出错
Error:(5, 9) java: 对Date的引用不明确
        java.sql 中的类 java.sql.Date 和 java.util 中的类 java.util.Date 都匹配

在这种情况下需要使用完整的类名

import java.util.*;
import java.sql.*;
public class Test {
    public static void main(String[] args) {
        java.util.Date date = new java.util.Date();
        System.out.println(date.getTime());
    }
}

使用import static可以导入包中静态的方法和字段

image-20221119194333543

pow方法就是Math中的一个静态方法,我们使用import static就可以进行简写,在调用的时候只需要写方法名。

没有import static修饰过的

import java.lang.Math;
public class Test {
    public static void main(String[] args) {
        double x = 10;
        double result = Math.pow(x,2);

    }
}

import static修饰过的

import static java.lang.Math.*;
public class Test {
    public static void main(String[] args) {
        double x = 10;
        double result = pow(x,2);

    }
}

至于这个import static不建议大家使用

6.3.3 自定义包

包就是所谓的文件夹

操作步骤

  1. 在 IDEA 中先新建一个包: 右键 src -> 新建 -> 包

image-20221119203116846

  1. 在弹出的对话框中输入包名,,通常会用公司的域名的颠倒形式,例利于域名是www.bit.com,那么包的名字就是com.bit.www

image-20221119203128151

  1. 在包中创建类, 右键包名 -> 新建 -> 类, 然后输入类名即可.

image-20221119203210866

  1. 此时可以看到我们的磁盘上的目录结构已经被 IDEA 自动创建出来了

image-20221119203219277

  1. 同时我们也看到了, 在新创建的 Test.java 文件的最上方, 就出现了一个 package 语句

image-20221119203103722

package是声明当前类是在哪个包底下。

package com.bite.demo1;

6.3.5 常见的包

  1. java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
  2. java.lang.reflect:java 反射编程包;
  3. java.net:进行网络编程开发包。
  4. java.sql:进行数据库开发的支持包。
  5. java.util:是java提供的工具程序包。(集合类等) 非常重要
  6. java.io:I/O编程开发包。

除了JDK自动导入的,剩下的都需要我们用import自己导入

10.Java类和对象完+作业+继承

回顾

什么是类?什么是对象?什么是面向对象?什么是面向过程
如何定义一个类
如何实例化一个对象
如果通过对象访问对象的成员属性、成员方法
通过(对象.)进行访问
this引用?代表的是当前对象的引用
构造方法中的this引用可以访问成员变量,可以访问成员方法,也可以访问当前对象的其他构造方法
引用指向null代表什么?代表这个引用不指向任何对象
引用不能指向引用,但是引用能指向引用所指向的对象。
一个引用只能指向一个对象,不能指向多个对象。
封装:根据业务需求,对类的细节进行隐藏,提供公开的接口,来和数据进行交互。

6.3.6 封装操作举例

class Person {
    private String name;
    public int age;

    private void eat() {
        System.out.println("吃饭");
    }
    public void show() {
        System.out.println(name + " " + age);
    }
}

我们通过private关键字进行对成员变量和成员方法进行封装,private封装后的只能在类中使用。

name成员变量、eat成员方法都已经封装起来了

使用private关键字进行了封装。此时,name的权限就变小了,只能在当前类当中才能进行访问。

image-20221120141047983

补充

public哪里都能访问

private只能在当前类访问

default只能在包中进行访问

在Java编译器当中我们对构造函数创建有快捷方法。

第一步右键选择Generate、或者快捷键Alt+Insert

image-20221120141658711

第二步:选择Constructor

image-20221120141814151

第三步选择构造函数的形参(多选按住CTRL)

image-20221120142003727

这样就可以在封装的情况下,通过构造函数在对象实例化的过程中进行初始化成员变量。

但是,如果想要更改姓名的话却无法更改,除非再次进行实例化一个对象,所以我们可以通过创建成员方法作为接口那么我们就创建了成员方法setName进行姓名的更改getName进行名字的查询

class Person {
    private String name;
    public int age;

    private void ear() {
        System.out.println("吃饭");
    }
    public void show() {
        System.out.println(name + " " + age);
    }

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

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

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class Test {
    public static void main(String[] args) {
        Person person = new Person("mengdehong",20);
        person.setName("meng");
        System.out.println(person.getName());
        person.show();
    }
}
//--------------
//编译器运行结果为
//meng
//meng 20

但是我们有多个成员变量进行封装的时候,我们都要对每个成员变量进行set变量、get变量的方法吗?

实际上我们也有快捷操作。

第一步左键选择Generate

image-20221120144125619

第二部选择Getter and Setter

image-20221120144312677

第三步进行选择所需要创建成员方法的成员变量

image-20221120144348219

这样就创建好了成员方法作为接口

image-20221120144440370

今天我们讲了类和对象的一部分,剩下的内容我们会在下一篇博客中讲完。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/2024.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

常用hook

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。理解:hook是react提供的函数API官方提供的hook基础hookuseState APIconst [state, setState] useState(initialState); //返回state值 以及更新state的方法 …

壹沓科技完成近2亿元B轮融资:构建数字机器人,实现业务超自动化

RPA中国获悉,全球领先的数字机器人公司壹沓科技近期宣布完成近2亿元B轮融资,本轮融资由鼎晖VGC(创新与成长基金)领投,创享欢聚投资基金、IDG资本、钟鼎资本跟投,指数资本继续担任独家财务顾问。 壹沓科技CEO卞晓瑜表示&#xff1…

栈、队列、优先级队列的模拟实现

优先级队列的模拟实现栈stack的模拟实现push()pop()top()size()empty()swap()stack总代码队列queue的模拟实现push()pop()front()back()empty()size()swap()queue总代码优先级队列(堆)push()pop()top()empty()size()swap()priority_queue总代码deque的了解栈 在CSTL中栈并不属…

吃透Java面试题,建议收藏

本文已经收录到Github仓库,该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点,欢迎star~ Github地址:https://github.com/…

LeetCode:27. 移除元素

🍎道阻且长,行则将至。🍓 🌻算法,不如说它是一种思考方式🍀算法专栏: 👉🏻123 一、🌱27. 移除元素 题目描述:给你一个数组 nums 和一个值 val&am…

Chapter6.2:其他根轨迹及综合实例分析

该系列博客主要讲述Matlab软件在自动控制方面的应用,如无自动控制理论基础,请先学习自动控制系列博文,该系列博客不再详细讲解自动控制理论知识。 自动控制理论基础相关链接:https://blog.csdn.net/qq_39032096/category_10287468…

使用vite创建vue3工程

定义 什么是vite?-----新一代前端构建工具 优势 开发环境中,无需打包操作,可快速的冷启动---最牛的地方轻量快速的热重载(HMR)---一修改代码就局部刷新,webpack也具备,但vite更快真正的按需编…

【数据结构与算法】用队列实现栈

文章目录😎前言如何用队列实现栈?用队列实现栈整体的实现代码😎写在最后😎前言 😼前面我们相继实现了 栈 和 队列 ,是不是愁没有练手的地方呢?别担心,本章带大家用队列来实现一个栈&…

synchronized 加锁 this 和 class 的区别

synchronized 是 Java 语言中处理并发问题的一种常用手段,它也被我们亲切的称之为“Java 内置锁”,由此可见其地位之高。然而 synchronized 却有着多种用法,当它修饰不同对象时,其意义也是不同的,下面我们一起来看。 ​…

云原生时代顶流消息中间件Apache Pulsar部署实操之Pulsar IO与Pulsar SQL

文章目录Pulsar IO (Connector连接器)基础定义安装Pulsar和内置连接器连接Pulsar到Cassandra安装cassandra集群配置Cassandra接收器创建Cassandra Sink验证Cassandra Sink结果删除Cassandra Sink连接Pulsar到PostgreSQL安装PostgreSQL集群配置JDBC接收器创建JDBC Sink验证JDBC …

【网络】网络层协议——IP

目录网络层IP协议IP基础知识IP地址IP报头格式网段划分CIDR特殊的IP地址IP地址的数量限制私有IP地址和公有IP地址路由IP总结网络层 在复杂的网络环境中确定一个合法的路径。 IP协议 IP协议作为整个TCP/IP中至关重要的协议,主要负责将数据包发送给最终的目标计算机…

多线程 (六) 单例模式

🎉🎉🎉点进来你就是我的人了 博主主页:🙈🙈🙈戳一戳,欢迎大佬指点!人生格言:当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友一起加油喔🦾&am…

蓝桥杯刷题冲刺 | 倒计时19天

作者:指针不指南吗 专栏:蓝桥杯倒计时冲刺 🐾马上就要蓝桥杯了,最后的这几天尤为重要,不可懈怠哦🐾 文章目录1.抓住那头牛2.排列序数1.抓住那头牛 题目 链接: 抓住那头牛 - C语言网 (dotcpp.com…

网络安全之防火墙

目录 网络安全之防火墙 路由交换终归结底是联通新设备 防御对象: 定义: 防火墙的区域划分: 包过滤防火墙 --- 访问控制列表技术 --- 三层技术 代理防火墙 --- 中间人技术 --- 应用层 状态防火墙 --- 会话追踪技术 --- 三层、四层 UTM …

CrossOver零知识学习1 —— 初识

本文部分内容参考CrossOver22全新版功能简介 免费mac虚拟机工具_CoCo玛奇朵的博客-CSDN博客 特此致谢! 一、CrossOver简介 CrossOver是由CODE WEAVERS公司开发的类虚拟机软件,目的是使Linux和Mac OS X操作系统和Window系统兼容。CrossOver英文原意为“…

强烈推荐:0基础入门网安必备《网络安全知识图谱》

蚁景网安学院一直专注于网安实战技能培养,提供全方位的网安安全学习解决方案。我们集聚专业网安技术大佬资源,倾力打造了这本更全面更系统的“网络安全知识图谱”,让大家在网络安全学习路上不迷茫。 在这份网安技能地图册里,我们对…

01 | Msyql系统架构

目录MySQL系统架构连接器查询缓存分析器优化器执行器MySQL系统架构 大体来说,MySQL分为Server层和引擎层两部分。 Server层包含链接器、查询缓存、分析器、优化器和执行器,而引擎层负责的是数据的存储和读取,支持InnoDB、Myisam、Memory等多…

CSS实现文字凹凸效果

使用两个div分别用来实现凹凸效果;text-shadow语法 text-shadow: h-shadow v-shadow blur color; h-shadow:必需。水平阴影的位置。允许负值。 v-shadow :必需。垂直阴影的位置。允许负值。 blur:可选,模糊的距离。 co…

【C语言】你真的了解结构体吗

引言✨我们知道C语言中存在着整形(int、short...),字符型(char),浮点型(float、double)等等内置类型,但是有时候,这些内置类型并不能解决我们的需求,因为我们无法用这些单一的内置类型来描述一些复杂的对象&#xff0c…

k8s部署prometheus

k8s部署prometheus 版本说明: k8s:1.24.4 prometheus:release-0.12(https://github.com/prometheus-operator/kube-prometheus.git) 本次部署采用operator的方式将prometheus部署到k8s中,需对k8s和prom…