当前位置: 首页 > news >正文

C++ 类和对象(上)

 面向对象的三大特性:封装,继承,多态

 C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。比如:
之前在数据结构初阶中,用C语言方式实现的栈,结构体中只能定义变量;现在以C++方式实现,
会发现struct中也可以定义函数。

C++当中的 struct 升级为了 类,在struct当中除了可以定义变量,还可以定义函数,而且以前C当中的struct 的玩法也可以实现:

struct Stack
{int* a;int top;int capacity;
};//没有进行重命名int main()
{struct Stack st1;  //C++兼容 C的struct 语法Stack st2;        // 同时 升级为了 类return 0;
}

 我们现在来简单实现一个栈,就可以把栈的当中使用的变量,和函数都写到一个类当中去:

struct Stack
{void Init(size_t capacity = 4){a = (int*)malloc(sizeof(int) * capacity);if (nullptr == a){perror("malloc申请空间失败");return;}capacity = capacity;top = 0;}void Push(const int& data){// 扩容····书写 这里是省略a[top] = data;++top;}int Top(){return a[top - 1];}void Destroy(){if (a){free(a);a = nullptr;capacity = 0;top = 0;}}int* a;int top;int capacity;
};//没有进行重命名int main()
{Stack std;std.Init();std.Push(1);std.Push(2);std.Push(3);std.Push(4);cout << "栈顶元素:" << std.Top() << endl;std.Destroy(); return 0;
}

我们可以用 ” .  “来访问到类当中的函数。

而且上述例子,我们是把成员定义来 函数的下面的,但是我们发现并没有报错,因为C++当中的创建一个类就是创建一个域,而C++是把这个类看做是一个整体的。

 在C++当中 跟喜欢 把上述的 struct 的定义方式,用class 来代替,定义一个class和在C++当中定义一个 struct一样,都可以定义成员和函数,在最后都需要 加 分号 “;”。

 但是,如果我们直接把上述的 struct 换成 class 就编译不通过了:

 

 在C++当中 给了 三种访问修饰符:

 public 在类外可以访问,protected 和 pricate在此处都是一样的,只能再类内使用,后两者在继承当中才有区别。

 当我们加了 public修饰符之后,在类外就可以使用了:

class Stack
{
public:void Init(size_t capacity = 4){a = (int*)malloc(sizeof(int) * capacity);if (nullptr == a){perror("malloc申请空间失败");return;}capacity = capacity;top = 0;}void Push(const int& data){// 扩容····书写 这里是省略a[top] = data;++top;}int Top(){return a[top - 1];}void Destroy(){if (a){free(a);a = nullptr;capacity = 0;top = 0;}}
protected:int* a;int top;int capacity;
};

上述中  三个修饰符之后要交  “ : ” ,而且上述的public 修饰符修饰的范围是,下一个权限修饰符之前,或者是如果没有的话就是一直修饰到最后,如上述,public就修饰到 protected 修饰符的上一行。

 上述的访问修饰限定符,不仅仅可以在class 中使用,struct 也可以使用,而我们上述直接把 struct 换成 class 之后就会报错是因为,class,如果不使用 访问修饰限定符的话,他默认是private的。而struct默认是 public修饰的。

 但是我们不一般不用默认这个概念,一般都是使用 这个修饰符来修饰。

 【访问限定符说明】

  • 1. public修饰的成员在类外可以直接被访问
  • 2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
  • 3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
  • 4. 如果后面没有访问限定符,作用域就到 } 即类结束。
  • 5. class的默认访问权限为private,struct为public(因为struct要兼容C)

 类的定义

class className
{
// 类体:由成员函数和成员变量组成
}; // 一定要注意后面的分号

 class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分
号不能省略。

类体中内容称为类的成员:类中的变量称为类的属性成员变量; 类中的函数称为类的方法或者
成员函数

类的两种定义方式:

 类也是可以声明和定义分离的:

 1.)声明和定义全部放在类体中,需注意:成员函数如果在类中定义,默认这个函数是内联的。

 

 如果我们像上述一样在类中去定义 成员函数,这个函数是 内联的,但是同样的,决定一个函数是否是内联的,决定权是在编译器,如果这个函数定义得 复杂,长,那么可能就不会是内敛函数。

 2)类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加 “类名::

 

 上述例子,在头文件中 定义 类的声明,在cpp文件中 定义类中函数的实现,我们用“类名::函数名”这个方式来表示,这个函数是在类中的函数,是成员函数的定义。

需要注意的是:我们一般在写的时候,喜欢把 类当中成员名前加一个 " _ "  ,原因是这样的:

class data
{
public:void Init(int year){year = year;}protected:int year;int month;int data;
};

 比如这个例子,在Init()函数中的  year = year 是哪个 year 赋值给 year 呢?

 其实是这样的赋值的:

 

 因为在成员的函数中的参数访问顺序是,先是 局部域 然后是 类域 最后是 全局域

 所以为了防止出现上述的情况,我们就把类当中的 成员加一个" _ "  来区分:

protected:int _year;int _month;int _data;

封装

 将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来
和对象进行交互。把数据和方法放到一起,不想给用户看的就是 私有的,想给用户看的就是 公有的。

封装本质上是一种管理,让用户更方便使用类,比如一个计算机,有键盘,鼠标,显示屏,开关机键,等等的可以让用户和计算机进行交互的硬件,但是,实际上在完成计算,和工作的是电脑里吗的cpu,显卡,内存等等的这些用户看不到的硬件。厂家在生产电脑的时候就会把这些cpu,显卡,内存等等的给包装起来,把键盘,显示器,开关机键这些给留在外面供用户和计算机交互。

上述就是封装的意义。

在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来
隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用


 不如我们在C中的数据结构,懂得封装的程序员一般是这样写的:

就是,哪怕 STTop()函数只有一行代码,也要写成函数来调用

 但是有一些就会 一些用封装,一些就直接访问,如下图:

 类的作用域

 类定义了一个新的作用域,类的所有成员都在类的作用域里面,在类体外定义成员的时候,需要使用 :: 作用域操作符指明成员属于那个域的。


class Person
{
public:void PrintPersonInfo();
private:char _name[20];char _gender[3];int _age;
};
// 这里需要指定PrintPersonInfo是属于Person这个类域
void Person::PrintPersonInfo()
{cout << _name << " " << _gender << " " << _age << endl;
}

这样也能理解,定义一个类就是一个新的作用域,意思就是我在一个类当中定义了一个 func()函数,我又在另一个类当中定义了一个 func()函数,如果我不指明是那个类当中的func()函数,编译器就不知道我是对哪一个 类 当中的函数进行定义了。

 对于函数的声明和定义很好区分,对于变量是声明还是定义,就要判断它开不开空间,如上述类当中的变量就是声明,也它没有开空间。

int main()
{Person p; // 整体定义return 0;
}

 如上,类当中的变量只是声明,他们是向上述一样整体进行定义的。

类的实例化

int main()
{Person p; // 整体定义return 0;
}

如我们之前写的这个例子,这就是一个类的实例化对象。

打个比方,我们要建房子,而类就像是一个 图纸一样,而图纸里面是不能建房子,住人的,他是一个模板,我们根据这个图纸就可以 开始建房子,而根据这个图纸建出来的房子就是这个类的实例化对象。这个对象才开辟了空间。

int main()
{Person p; p::age = 0;  // errorreturn 0;
}

像这样是不行的,因为我们这样是在访问 类当中的 top,而类当中的top是没有开辟空间的,也就是说图纸当中的 是不能住人的。

对象的大小

 以前在C当中计算结构体的大小很好计算,里面都是变量,只要注意内存对齐就行了,但是C++类当中的 不仅仅有成员,还有 成员函数,这怎么计算呢?

 计算类的大小也是要进行 内存对齐的,而其中的成员函数是不进行计算的,只算成员的大小。

 因为对象当中只存储了 成员,没有存储成员函数

 这就好比是,成员是一个家,成员函数是篮球场,健身房,这些东西没有必要在家里来建造,都建造的话很浪费,用公用就行了。

 此处的函数都是放在 一个 公共的区域,每一个这个类的对象,有的成员函数都在这个公共的区域里面。这个公共的区域编译器是知道在哪的,所以对象中不需要存储函数的地址。

class A
{
public:void printA(){printf("%d", _aff);}
//private:int _aff = 10;};int main()
{A a;cout << sizeof(A) << endl; //4cout << sizeof(a) << endl; //4a._aff = 1; // 在 a 这个对象当中去访问a.printA(); // 在公共区域当中去访问
}

需要注意的是:如果这个类是空类,也就是没有成员变量的类,那么这个类的大小是 1 byte,这个字节是为了占位,表示这个对象的存在。

class A
{
public:void func(){}
};class B
{};int main()
{cout << sizeof(A) << endl; //1cout << sizeof(B) << endl; //1return 0;
}

 内存对齐

  •  1. 第一个成员在与结构体偏移量为0的地址处。
  • 2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。VS中默认的对齐数为8
  • 3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
  • 4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

 

为什么要内存对齐

 1) 平台移植:

不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

2) 性能原因:

数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。总体来说:结构体的内存对齐是拿空间来换取时间的做法。

 第一个 _a 只读了一次,而第二次 不对齐的情况, 读了 两次

使用  #pragme pack(8)可以设置 默认对齐数为 8 ,在VS当中,默认对齐数是8。

在使用  #pragme pack(8)  之后,再使用  #pragme pack(),可以取消设置的默认对其书,还原默认。

 this指针

class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year; // 年int _month; // 月int _day; // 日
};
int main()
{Date d1, d2;d1.Init(2022, 1, 11);//2022-1-11d2.Init(2022, 1, 12);//2022-1-12d1.Print();d2.Print();return 0;
}

先来看这个例子,既然成员函数都是调用的是一个 公共的函数,那么为什么此处的两个对象 d1 和 d2 ,两个对象调用的同一个函数,打印的结果不一样呢?我们看函数也没有传参,此处的是怎么分辨Print()函数中 _year  _month _day 这些变量的?

 此处,我们看来是访问的是 本 对象当中的 变量:

 其实不是,因为这个只是一个声明,是没有存储空间的,其实这样的代码,编译器是会做一些处理的:

此处其实隐含了一个  this 指针,如果交给编译器,编译器会这样把这个函数进行修改:

	// 编译器对成员函数的修改void Print(Date* this){cout <<this-> _year << "-" << this->_month << "-" << this->_day << endl;}

然后再函数调用的时候,也会传入这个对象的地址:

Print(&A):
Print(&B):

 但是上述只是编译器来写的,它在函数的形参和实参上面,只允许自己来创建  Date* this 这个形参,而不允许用户去 创建这个形参:

 如上图,报错了。

但是编译器又允许我们在函数内部去使用这个this:

 也就是说,这个this是编译器给我们创建好了的,我们可以在函数当中去使用这个this。

 这个this 是不能修改的:

 因为,其实此处的this 的类型这样的 : Date* const this ;  也就是说,此处的 const 修饰但是this ,这个this  是不能被修改的,但是 this  指向的内容是可以进行修改的。

 const  加在 * 的前面,这个指针指向的内容才不能被修改。

  空对象中的this

class A
{
public:void Print(){cout << "Print()" << endl;}
private:int _a;
};
int main()
{A* p = nullptr;p->Print();  //Print()return 0;
}

 上述例子是正常执行的,但是下述代码不是正常执行的:

class A
{
public:void PrintA(){cout << _a << endl;}
private:int _a;
};
int main()
{A* p = nullptr;p->PrintA();return 0;
}

 运行错误:

 首先一样的,创建了一个 p 空对象,然后对空对象 P 当中的print()函数进行访问,在Print()函数调用的时候,会把 p 的地址传进去,传递一个空指针不会报错。

 第一种不会报错是因为,没有对空对象当中的成员进行访问,他访问的成员函数,成员函数是存储在 公共区当中的,不是在对象当中,不会发生解引用。

 而在第二种当中,Print()函数对空对象当中的 _a  成员变量进行了访问,然后函数中就会把 _a这个变量之前加一个  this->  表示引用,这时候的引用就是空指针引用,就会报错。

 而上述   p->Print()   并没有解引用,因为 对象当中不存储 成员函数,成员函数存储在公共区当中,此处只是在公共区当中去找到这个函数,然后  call  (调用)这个函数。

 

 当然,使用  "  ::  "  来替代  "   ->   "  来使用也是不行的,因为 "  ::    "  前应该写的是 作用域,而类域当中的 成员变量和成员函数都是没有存储在其中的, 类只是一个模板,创建某一种对象的模板。

 

 this 存储 在 哪里?(对象里面?栈?堆?静态区?常量区?)

 首先不能在对象里面,因为之前我们在计算对象的大小的时候,是没有这this指针的大小的。

因为这个this 是作为函数的参数传入进去的,那么这个this 就要 压栈,那么这个this 指针是更普通参数引用 存储在函数栈帧当中的,也就是存储在栈上的。

在VS下,因为this要频繁的进行调用,所以VS对这个this 存储的位置进行了优化:

 他把 this 指针存储在了  ecx  当中,ecx是寄存器。

C语言和C++实现Stack的对比

 C语言实现:

  • 每个函数的参数都是  Stack*  ,都是通过指针来操作的,调用时候,必须传入Stack指针。
  • 每个函数第一步都需要判断,传入函数的  Stack*  等等这些参数是否为NULL。

 而且在主函数当中调用这些函数的时候,命名都是  数据结构的类型 + 函数操作:

 我们发现,C当中实现 Stack 都需要用指针来实现,在链表当中有得地方甚至要用要 二级指针,这样不管是在实现,还是在 使用的时候,都很容易出错。

 C++实现:

C++当中 是把 Stack 当中的 函数和 结构的变量定义到一起,如果把成员的访问权限打开,那么对于像 栈,顺序表这些甚至可以直接访问创建对象的当中的成员。在类当中,我们可对 类当中的方法和 成员,根据 我们想不想要用去去访问,利用访问权限进行封装:

 而且在主函数当中去 使用其中的方法的时候,显得很方便,不用再去 复杂的命名,而且 调用的时候不再使用指针:

int main()
{
Stack s;
s.Init();s.Push(1);
s.Push(2);
s.Push(3);
s.Push(4);
printf("%d\n", s.Top());
printf("%d\n", s.Size());
s.Pop();
s.Pop();
printf("%d\n", s.Top());
printf("%d\n", s.Size());
s.Destroy();
return 0;
}

相关文章:

C++ 类和对象(上)

类 面向对象的三大特性&#xff1a;封装&#xff0c;继承&#xff0c;多态 C语言结构体中只能定义变量&#xff0c;在C中&#xff0c;结构体内不仅可以定义变量&#xff0c;也可以定义函数。比如&#xff1a; 之前在数据结构初阶中&#xff0c;用C语言方式实现的栈&#xff0c;…...

【BIM+GIS】BIM模型导入GIS软件之前的一些处理设置

文章目录 一、模型位置发生偏移二、模型对象丢失或增加三、模型材质发生变化四、导出过程缓慢五、模型属性批量丢失一、模型位置发生偏移 在视图→可见性/图形替换模型类别→场地(VV可见性快捷),勾选项目基点。 单击选中项目基点,在属性中修改几点坐标。 即使修改了项目基…...

js FileReader的常用使用方法

FileReader 对象允许 Web 应用程序异步读取存储在用户计算机上的文件&#xff08;或原始数据缓冲区&#xff09;的内容&#xff0c;使用 File 或 Blob 对象指定要读取的文件或数据。 主要的读取方法&#xff1a; readAsArrayBuffer()&#xff1a; 开始读取指定的 Blob 中的内…...

网络威胁情报:数据的力量

在一个日益互联和数字化的世界中&#xff0c;网络威胁已成为一项重大挑战&#xff0c;可能危及您组织的声誉、财务稳定性和整体运营效率。 事实上&#xff0c;根据 IBM 2022 年的一份报告&#xff0c;数据泄露的平均成本现在为 435 万美元。 鉴于网络威胁的重要性和影响日益突…...

shell:清理指定目录中指定天数之前的旧文件

前言 我们在服务器运行一些服务经常会产生很多临时文件&#xff0c;而有些临时文件不定期处理很容易就打满了整个磁盘&#xff1b;所以有必要去定期清理&#xff0c;基于这个需求我们就可以搞一个脚本结合crontab或者服务调度这些来使用&#xff1b; 脚本实现 #!/bin/bash# …...

想入门网络安全?先来看看网络安全行业人才需求!

如果你是一个想要入门网络安全行业的小白、如果你是网络安全专业在读的大学生、如果你是正在找工作的新手&#xff0c;那么这篇文章你一定要仔细看。毕竟知己知彼百战百胜&#xff0c;知道行业的人才需求才能更好得发挥自己的优势。 当你打开BOSS直聘、拉钩等招聘网站&#xf…...

0424 spring AOP学习

AOP是指什么&#xff1f; 面向切面编程&#xff0c;Aspect Oriented Program。是一种编程范式、思想。 Spring AOP里涉及的AOP原理叫什么&#xff1f; 动态代理。 动态代理其实就是在运行时动态的生成目标对象的代理对象&#xff0c;在代理对象中对目标对象的方法进行增强。…...

GB/T 28181-2022 新版差异笔记

GB/T 28181-2022 新版差异笔记 文章目录 GB/T 28181-2022 新版差异笔记更改了标准范围删除部分术语和定义增加PTZ缩略语更改SIP监控域互联结构图更改了“联网系统通讯协议结构图”增加了媒体流数据传输的RTP时间戳要求增加了对H.265、AAC的支持更改了SDP协议的引用更改了与其他…...

以轻量级服务器niginx为核心的JavaWeb项目:第一章 项目设计

这里写目录标题 一 需求分析与环境搭建1.需求分析2.环境搭建1.2.1首先配置mysql环境1.2.2 配置maven环境 二 打成War包&#xff0c;发到linux上 一 需求分析与环境搭建 1.需求分析 2.环境搭建 1.2.1首先配置mysql环境 先查找一下mysql环境 [roothadoop122 ~]# mysql --vers…...

【error】 Request method ‘GET‘ not supported app端调用后台接口报错,后台人员自己调用时没问题

目录 问题描述原因分析解决方案方法一&#xff1a;方法二&#xff1a;方法三&#xff1a; 联系自身 问题描述 org.springframework.web.HttpRequestMethodNotSupportedException: Request method ‘GET’ not supported at org.springframework.web.servlet.mvc.method.Request…...

Microsoft Bitlocker企业级管理部署方案

目录 一、前言 二、BitLocker部署前的准备工作 三、BitLocker的部署方式 3.1 通过群组策略部署BitLocker...

Jetpack Compose 中使用分页 API 调用的无限滚动

Jetpack Compose 中使用分页 API 调用的无限滚动 最近&#xff0c;我在DashCoin 的硬币屏幕上添加了一个带有分页 API 调用的无限滚动。它使浏览硬币列表变得非常困难&#xff0c;并且确实减少了初始加载时间&#xff0c;比以前少了。如果没有正确实施&#xff0c;实施无限滚动…...

第5章 数据结构之“链表”

链表简介 1.多个元素组成的列表。 2.元素的存储不连续&#xff0c;用next指针连在一起。 数组 vs 列表 数组&#xff1a;增删非手尾元素时往往需要移动元素。如果要在数组中增加一个元素&#xff0c;数组后面的所有元素需要往后面移动一位。如果在数组中删除一个元素&#x…...

SpringMVC - REST风格介绍已经RESTful简化开发

文章目录 RESTREST基本介绍RESTful快速入门RESTful快速开发 REST REST基本介绍 REST (Representational State Transfer), 表现形式状态转换(访问网络资源的风格) 传统风格资源描述形式 http://localhost/user/getById?id1http://localhost/user/saveUser REST风格描述形式 …...

Android 10.0 user模式下解除系统进入recovery功能的限制

1.前言 在10.0的系统rom定制化开发中,系统中recovery模式功能也是很重要的一部分,而在原生系统中,对于debug模式的产品,可以通过电源键和音量+键进入recovery模式, 但是在user模式下的产品,对于通过这种方式,进入recovery模式就受限制了,防止用户无操作为了产品安全等…...

用这些 JavaScript 试题来提高你的编程技能

文章目录 一、解释 Promise 的概念和用法。二、解释节流&#xff08;throttle&#xff09;和防抖&#xff08;debounce&#xff09;在 JavaScript 中的应用场景。三、请列举 JavaScript 中的原始数据类型。四、请解释JavaScript中的作用域。五、写一个名为 multiply 的函数&…...

倾斜摄影超大场景的三维模型在网络发布应用遇到常见的问题浅析

倾斜摄影超大场景的三维模型在网络发布应用遇到常见的问题浅析 倾斜摄影超大场景的三维模型在网络发布应用时&#xff0c;常见的问题包括&#xff1a; 1、加载速度慢。由于数据量巨大&#xff0c;网络发布时需要将数据文件分割成多个小文件进行加载&#xff0c;这可能会导致页…...

基于遗传算法的梯级水电站群优化调度研究(Matlab代码实现)

&#x1f4a5; &#x1f4a5; &#x1f49e; &#x1f49e; 欢迎来到本博客 ❤️ ❤️ &#x1f4a5; &#x1f4a5; &#x1f3c6; 博主优势&#xff1a; &#x1f31e; &#x1f31e; &#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 …...

java每日问题

一&#xff0c;什么时聚集索引什么时非聚集索引 聚集索引就是基于主键创建的索引除了主键索引以外的其他索引被称为非聚集索引也叫二级索引由于在innodb引擎里面一张表的数据对应的物理文件本事就是按照B树来组织的一种索引结构而聚集索引就是按照每张表的主键来构建一颗B树然后…...

C++设计模式之 依赖注入模式探索

依赖注入模式 前言依赖注入模式的角色依赖注入模式的UML图依赖注入模式的设计和实现(C)依赖注入和访问者模式的区别依赖注入模式的使用场景依赖注入模式的优缺点结语 前言 GoF设计模式主要关注的是面向对象编程设计的问题&#xff0c;而依赖注入作为一种编程技术&#xff0c;它…...

如何实现Spring AOP以及Spring AOP的实现原理

AOP:面向切面编程,它和OOP&#xff08;面向对象编程)类似。 AOP组成: 1、切面:定义AOP是针对那个统一的功能的&#xff0c;这个功能就叫做一个切面&#xff0c;比如用户登录功能或方法的统计日志&#xff0c;他们就各种是一个切面。切面是有切点加通知组成的。 2、连接点:所有可…...

数学建模——数据预处理

在数学建模时&#xff0c;经常遇到数据的预处理&#xff0c;那么会有一些什么情况呢&#xff0c;跟着北海老师总结了他的内容~希望对大家有所帮助&#xff01; 缺失值 比赛提供的数据&#xff0c;发现有些单元格是null或空的缺失太多:例如调查人口信息&#xff0c;发现“年龄…...

第8章:树

1.树是什么 一种分层数据的抽象模型前端工作中常见的树包括&#xff1a;DOM树&#xff0c;级联选择(省市区)&#xff0c;树形控件&#xff0c;…javascript中没有树&#xff0c;但是可以用Object和Array构建树 4.树的常用操作&#xff1a;深度/广度优先遍历&#xff0c;先中后…...

Java基础学习(10)

Java基础学习 一、JDK8时间类1.1 Zoneld时区1.2 Instant时间戳1.3 ZonedDateTime1.4 DateTimeFormatter1.5 日历类时间表示1.6 工具类1.7 包装类JDK5提出的新特性Integer成员方法 二、集合进阶2.1 集合的体系结构2.1.1 Collection 2.2collection的遍历方式2.2.1 迭代器遍历2.2.…...

Tomcat多实例部署实验

引言 本文主要内容是tomcat的多实例配置实验。 一、实验准备 Tomcat多实例是指在一台设备上运行多个Tomcat服务&#xff0c;这些Tomcat相互独立&#xff0c;互不影响。多实例与虚拟主机不同&#xff0c;虚拟主机的本质是在一个服务下有多个相对独立的目录&#xff0c;但是多实…...

无良公司把我从上家挖过来,白嫖了六个月,临近试用期结束才说不合适,催我赶紧找下家!...

职场套路多&#xff0c;一不小心就会掉坑&#xff0c;一位网友讲述了自己的遭遇&#xff1a; 今天被领导催促离职了&#xff0c;当时就是这个领导把他从别的公司挖过来。这家公司催得太急&#xff0c;为了投奔这里&#xff0c;他和上家的HR都闹翻了&#xff0c;上家总监挽留他&…...

忙碌中也要记得休息,这两款好玩的游戏推荐给你

第一款&#xff1a;古墓丽影9年度版 《古墓丽影9》&#xff08;原名Tomb Raider&#xff09;是由水晶动力开发&#xff0c;史克威尔艾尼克斯发行的动作冒险游戏。 它于 2013 年发布。续集是古墓丽影崛起和古墓丽影暗影。 本作的重点是新版劳拉&#xff08;Lara Croft&#xf…...

四种方法可以实现判断字符串包含某个字符

小编介绍过js中使用indexOf() 方法判断字符串包含某个字是一个很好用的方法&#xff0c;但除了这个方法之外&#xff0c;JavaScript中还有四种方法可以实现判断字符串包含某个字符&#xff1a; 1、使用字符串search() 方法 search() 方法用于检索字符串中指定的子字符串&…...

ubuntu进程相关command

列出当前系统中所有正在运行的进程的详细信息 ps aux查看所有包含某关键字的进程 例&#xff1a;查看所有包含关键字click的进程 ps aux | grep click运行后显示如下信息&#xff1a; root 8998 0.0 0.0 10984 4052 ? S 4月23 0:00 sudo ./bin/click…...

7.参数校验

在controller和service进行前端传参校验&#xff0c;保证存到数据库的数据是正确的 1.引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>这里无需…...