Java基础
Java基础
1.基础概念
1.注释
1.单行注释
- //注释
2.多行注释
- /*注释*/
3.文档注释
- /**注释*/
2.关键字
1.关键字特点
- 关键字的字母全部小写
2.class
- 用于创建/定义 一个类
- 类是Java最基本的组成单元
3.字面量
| 字面量类型 | 说明 |
|---|---|
| 整数类型 | 不带小数点的数字 |
| 小数类型 | 带小数点的数字 |
| 字符串类型 | 用双引号括起来的内容(即使没有内容) |
| 字符类型 | 用单引号括起来的,且内容只能有一个 |
| 布尔类型 | 布尔值:true/false,表示真假 |
| 空类型 | 一个特殊的值:null,空值,需要用字符串的形式打印出来,不能直接打印 |
-
特殊字面量
-
\t 制表符
- 打印的时候,会把前面的字符串的长度去补齐到8,或者是8的整数倍,最少补一个空格,最多补8个空格
- 在两个字符串中间**+‘\t’+**,可以使中间补齐
4.变量
- 在程序执行过程中,其值有可能发生改变 的量(数据)
基本用法
1.使用场景
- 当某个数据经常发生改变时,可以用变量存储,当数据变化时,只要修改变量里面记录的值即可
2.定义格式
- 数据类型 变量名=数据值;
3.使用方式
-
输出打印
-
参与计算
-
修改记录的值
4.注意事项
- 只能存一个值
- 变量名不允许重复定义
- 一条语句可以定义多个变量
- 变量在使用之前一定要进行赋值
- 变量的作用域范围
- 使用前必须赋值
5.计算机中的数据存储
- 任意数据都是以二进制的形式来存储的
1.文本数据
1.常见进制
- 二进制(bin):由0和1组成,Java中以0b开头,如果用了0b开头,后面的数字中又有0和以外的数字则报错
- 十进制(oct):由0-9组成,不加前缀
- 八进制(dec):由0-7组成,以0开头
- 十六进制(hex):由0-9和a-f组成,以0x开头
# 在jdk7后加前缀
2.任意进制转为十进制
- 每个系数*基数的权次幂 相加
- 系数:每一位上的数
- 基数:当前进制数
- 权:从右向左,依次为0,1,2,3,……
3.十进制转为其他进制
- 除基取余法:不断的除以基数(几进制,基数就是几)得到余数,直到商为0,再将余数倒着拼起来
4.ASCII表
- 用7位二进制数字对应字母和符号
- 可以将字母转化为二进制存储
5.编码
1.GB2312编码
- 简体中文
2.BIG5编码
- 繁体中文
3.GBK编码
- 收录汉字,包含国家标准GB13000-1中的全部中日韩汉字,和BIG5编码中的所有汉字
- 计算机默认编码
4.Unicode编码
- 国际标准字符集,将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言,跨平台的文本信息转化
2.图片数据
1.黑白图
- 每个像素点,0为黑,1为白
2.灰度图
- 每个像素点,0为黑,255为白,中间数字为不同程度的灰
3.彩色图
-
由光学三原色(红绿蓝,rgb)作为一个整体来作为一个像素点,可以通过设置一个像素点中的三原色的深浅来调整颜色
-
每个原色的取值范围都是0-255
-
可以写成十进制(255,120,156)
-
也可以写成十六进制
3.声音数据
- 对声波采样,形成波形图,波形图中的每个点会数字对应,采样的点多则还原度高(无损),采样点少则还原度低(全损)
6.数据类型
| 数据类型 | 关键字 | 取值范围 | 内存占用 |
|---|---|---|---|
| 整数 | byte | -128~127 | 1 |
| short | -32768~32767 | 2 | |
| int | 十位数 | 4 | |
| long | 十九位数 | 8 | |
| 浮点数 | float | -3.401298e-38~3.402823e+38 | 4 |
| double | -4.9000000e-324~1.797693e+308 | 8 | |
| 字符 | char | 0~65535 | 2 |
| 布尔 | boolean | true,false | 1 |
# 定义long类型 的变量,在数字的后面要加一个L作为后缀
# 同理float类型 的变量。数字后加F作为后缀
7.标识符
- 标识符:给类,方法,变量等起的名字
标识符命名规则
1.硬性要求
- 由数字,字母,下划线,美元符号组成
- 不能以数字开头
- 不能是关键字
- 区分大小写
2.软性建议
-
小驼峰命名法(适合方法和变量)
-
标识符是一个单词 的时候,全部小写:name
-
标识符由多个单词 组成时,第一个单词的首字母小写,其他单词首字母大写:firstName
-
-
大驼峰命名法(适合类名)
- 标识符是一个单词 的时候,首字母大写:Student
- 标识符由多个单词 组成的时候,每个单词的首字母大写:GoodStudent
8.键盘录入
1.概述
- java中有一个写好的类叫Scanner,可以接收键盘输入的数据
- 步骤:
- 导包:在java.util.Scanner这个包
- 创建对象
- 接收数据
1 | import java.util.Scanner; //导包要写在类定义的上面 |
# 两个变量都要接收数据,就要写两遍接收数据的一行,不能在同一行两个变量接收数据
# Java中没有提供直接接收字符数据的方法,要先接收字符串数据,再进行转化,用charAct()来获取输入的字符串中的某个字符
9.IDEA
1.概述
- 结构
- 项目
- 模块
- 包
- 类
- 包
- 模块
- 项目
2.快捷键
- ctrl+alt+L,自动格式代码
- ctrl+alt+M,自动抽取方法
- alt+insert/alt+Fn+insert,生成构造方法,可以用shift多选
# PTG插件也可以更快速的实现
- ctrl+alt+v,快速在调用的方法前生成一个对应数据类型以及变量来接收
# 例如:sc.nextDouble(),ctrl+alt+v,则生成double v = sc.nextDouble();
-
ctrl+b,查看源码
-
选中一段代码后ctrl+alt+t,选择被哪种代码包裹,如for,if,while等
-
shift+alt+方向键,将代码移动
-
对报错的地方alt+enter会给出解决方法
-
选中后ctrl+shift+u,全部大写/小写
3.快捷功能
-
psvm
- 快速生成main方法
-
鼠标滚轮/alt
- 竖列选中
-
fori
- 快速生成一个for循环其中变量为i
- 如果在fori前加上数字.则会生成i<这个数字的循环
-
数组名.fori
- 快速生成数组的遍历
-
集合名.fori
- 快速生成集合的遍历
2.运算符
- 运算符:对字面量或者变量进行操作的符号
- 表达式:用运算符把字面量或者变量连接起来,符合java语法 的句子
1.算术运算符
| 符号 | 作用 |
|---|---|
| + | 加 |
| - | 减 |
| * | 乘 |
| / | 除 |
| % | 取模:取余数 |
# 如果有小数参与运算,则结果不一定准确
# 如果都是整数参与运算,结果为整数
1.数字相加
类型转换
1.隐式转换(自动类型提升)(默认)
-
把一个取值范围小的数值,转成取值范围大的数据,再进行计算
-
byte,short,char三种类型,在运算时,都会先提升为int再进行运算
2.强制转换
- 把一个取值范围大的数值,赋值给取值范围小的变量
- 目标数据类型 变量名=(目标数据类型)被强转的数据
1 | double a=12.3; |
# 可能会发生数据错误,可以用补码 来解释为什么会出错,以及会转为什么数据
# 如果要强转的是变量相加,需要把变量相加加括号
2.字符串相加
- 当相加操作中出现字符串时,+就是字符串连接符,会将前后的数据进行拼接,产生一个新的字符串
- 连续进行相加操作时,从左到右逐个执行
- 例如1+2+“人”,从左到右,先1+2没有字符串出现,则进行计算=3,3再余后面的"人"进行拼接,得到3人
3.字符相加
- 字符加字符/数字时,会先从ASCII中查询相应字符对应的数字,再进行计算
2.自增自减运算符
1.自增
- ++,变量的值加1
# 既可以写在变量前,也可以写在变量后
2.自减
- –,变量的值减1
# 既可以写在变量前,也可以写在变量后
3.参与计算
- 写在变量后,则先用后增/减
- 写在变量后,则先增/减后用
3.赋值运算符
| 符号 | 作用 |
|---|---|
| = | 赋值 |
| += | 加后赋值 |
| -= | 减后赋值 |
| *= | 乘后赋值 |
| /= | 除后赋值 |
| %= | 取余后赋值(是两个整数相除的余数) |
# 除了=,其他都会进行强制转换,转换为前面的变量的类型
4.关系运算符(比较运算符)
| 符号 | 说明 |
|---|---|
| == | 判断两个变量是否相等,成立为true,否则false |
| != | 判断是否不等 |
| > | 判断是否大于 |
| >= | 判断是否大于等于 |
| < | 判断是否小于 |
| <= | 判断是否小于等于 |
# 结果都是boolean类型,只有true和false
5.逻辑运算符
| 符号 | 作用 | 说明 |
|---|---|---|
| & | 逻辑与(且) | 并且,两边都为真,结果才为真,1为true,0为false |
| | | 逻辑或 | 或者,两边都为假,结果才是假,1为true,0为false |
| ^ | 逻辑异或 | 相同为false,不同为true |
| ! | 逻辑非 | 取反,真值取反就是假值 |
# &和|可以用补码 来解释
- 短路逻辑运算符
| 符号 | 作用 | 说明 |
|---|---|---|
| && | 短路与 | 结果和&相同,但是有短路效果 |
| || | 短路或 | 结果和|相同,但是有短路效果 |
# 如果左边能确定整个表达式的结果,则右边不执行
6.三元运算符
-
关系表达式?表达式1:表达式2;
-
先计算关系表达式,如果结果为真,则执行表达式1,为假则执行表达式2
# 三元运算符的结果必须要被使用
7.运算符优先级
| 优先级 | 运算符 |
|---|---|
| 1 | . () {} |
| 2 | !、~、++、– |
| 3 | *、/、% |
| 4 | +、- |
| 5 | <<、>>、>>> |
| 6 | <、<=、>、>=、instanceof |
| 7 | ==、!= |
| 8 | & |
| 9 | ^ |
| 10 | | |
| 11 | && |
| 12 | || |
| 13 | ? : |
| 14 | =、+=、-=、*=、/=、%=、&= |
# <<左移,补码向左移动,右边就会空出,在这个低位补0,同理右移高位正数补0负数1
# >>>无符号右移,向右移动,高位补0
8.原码,反码,补码
1.原码
- 十进制数据的二进制表现形式,最左边是符号位,0为正,1为负
- 八个bit为一个字节
- 最大值:01111111=127
- 最小值:11111111=-127
1.原码的计算
- 二进制的计算方式,加1,则直接在末位加1,满二进一
2.原码的弊端
- 用原码对正数进行计算是不会有问题的
- 但如果是负数计算,结果就出错,实际运算的结果与预期的结果是相反的
2.反码
- 为了解决原码不能计算负数 的问题而出现的
1.反码的计算
-
正数的反码不变,负数的反码在原码的基础上,符号位不变,数字取反,0变1,1变0
-
如果加1,则在末位加1,满二进一,得到的就是加1后的反码
2.反码的弊端
- 反码的11111111表示-0,如果再加1,则变为00000000=0
- 同样类似于-4的反码+7,跨0,会比正确结果小1
# 因为反码中的0有11111111和00000000两种表示方式
3.补码
-
在负数的反码的基础上加1,这样-0就是00000000,-1就是11111111,反码再依次向后,形成补码
-
-127就是10000001,-128就是10000000,-128只有补码,没有原码
-
计算机中数字的存储计算都是以补码的形式来操作的
-
所以一个字节 的范围就是**-128~127**
3.判断与循环
1.顺序结构
- java程序默认的执行流程,按照代码的先后顺序,从上到下依次执行
2.分支结构
1.if语句
1.第一种格式
1 | if(关系表达式){ |
- 执行流程
- 首先计算关系表达式的值
- 如果关系表达式的值为true就执行语句体
- 如果关系式的值为false就不执行语句体
- 继续执行后面的其他语句
# 只有一条语句的时候可以省略,但是尽量不要省略,如定义并初始化一个变量的语句,写成一句,但是是两句,不加{}会报错
2.第二种格式
1 | if(关系表达式){ |
- 执行流程
- 首先计算关系表达式的值
- 如果关系表达式的值为true就执行语句1
- 如果关系表达式的值为false就执行语句2
- 继续执行后面的语句
3.第三种格式
1 | if(关系表达式1){ |
- 执行流程
- 首先计算关系表达式1的值
- 如果为true就执行语句体1;如果为false就计算关系表达式2的值
- 如果为true就执行语句体2;如果为false就计算关系表达式3的值
- ……
- 如果所有关系表达式结果都为false,就执行else后的语句
2.switch语句
1.格式
1 | switch(表达式){ |
- 执行流程
- 首先计算表达式的值
- 依次和case后面的值进行比较,如果有对应的值,就会执行相应的语句,在执行的过程中,遇到break就会结束
- 如果所有的case后面的值和表达式的值都不匹配,就会执行default里面的语句体,然后结束整个switch语句
# case后面的值只能是字面量,不能写变量
2.case穿透
- 没有加break,正常有break就会结束整个switch,如果没有就会一直向下执行,直到有break或者}
# default也是特殊的case
- 可以在case后面的多个语句重复的时候,利用case穿透
# 将前面case后面的语句删除,只保留最后一个重复的语句,这样就会一直穿透到最后一个重复语句,然后break
# 同时可以将重复的语句的几个值都写在一个,case1,2,3,4,5
# 同样也可以用下面的写法优化
3.写法优化
- 在jdk12以后
1 | switch(表达式){ |
# 如果{}中只有一个语句,还能把{}省略,把case/default和语句体写在同一行
3.循环结构
1.for循环
1.格式
1 | for(初始化语句;条件判断语句;条件控制语句){ |
- 执行流程
- 执行初始化语句
- 执行条件判断语句,看其结果是true还是false
- 如果是false,循环结束
- 如果是true,执行循环体语句
- 执行条件控制语句
- 回到第二步继续执行条件判断语句
2.注意
- 不要在循环语句中写定义赋值语句,然后在语句外使用,变量只在循环中有效
- 变量定义在循环中,变量只能在本次循环中有效
2.while循环
1.格式
1 | 初始化语句; |
2.和for循环的对比
1.相同点
- 运行规则是一样的
2.区别
- for循环中,控制循环的变量,因为归属for循环的语法结构中,在for循环结束后,就不能再次被访问到了
- 知道循环次数或者循环的范围
- while循环中,控制循环的变量,对于while循环来说不归属其语法结构中,在while循环结束后,该变量还可以继续使用
- 不知道循环的次数和范围,只知道循环的结束条件
3.do……while循环
格式
1 | 初始化语句; |
- 先执行后判断
4.无限循环
- for循环中不写条件
- while/do……while循环中条件写true
# 无限循环下面就不能再写代码了,会报错无法达到的代码
5.跳转控制语句
-
continue,用于结束本次循环,开始下一次循环
-
break,结束整个循环
4.数组
1.数组介绍
- 数组指的是一种容器,可以用来存储同种数据类型 的多个值
# 并不一定是完全一样的数组类型,要结合隐式转化
2.数组的定义与静态初始化
1.定义
1 | 数据类型[] 数组名; |
或
1 | 数据类型 数组名[]; |
2.静态初始化
-
初始化:在内存中,为数组开辟空间,并将数据存入容器中的过程
-
完整格式
1 | 数据类型[] 数组名 = new 数据类型[]{元素}; |
-
简写格式
-
数据类型[] 数组名 = {元素};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
\# 初始化后长度不可变
### 3.数组元素访问
#### 1.数组的地址值
* 直接打印数组名,会显示数组的地址值,而不是数组里面的元素
* 地址值的格式
* [:表示当前是一个数组
* D,I:表示数组里面元素的类型
* @:间隔符号,固定格式
* 数字加字母:十六进制,真正的地址值
* 一般将这些统称为地址值
#### 2.索引
* 索引:也称下标,角标
* **从0开始**,逐个+1,连续不间断
### 4.数组遍历
* 数组遍历:将数组中所有的内容取出
* **遍历是指取出数据的过程**
* 可以使用循环来遍历数组
* 数组过长时为了获取数组的长度可以使用**length**
* 调用方法:
* 数组名.length
### 5.数组动态初始化
* 动态初始化:初始化时只指定数组的长度,由系统分配初始值
* 格式
```java
数据类型[] 数组名 = new 数据类型[数组长度] -
默认初始化值
- 整数:0
- 小数:0.0
- 字符:/u0000,即空格
- 布尔:false
- 引用:null
动态与静态的区别
- 动态:手动指定数组长度,系统给出默认初始化值
- 只明确元素个数,不明确具体数组
- 静态:手动指定数组元素,系统根据元素个数,计算出数组的长度
- 已经明确了要操作的具体数据,直接静态初始化
6.数组内存图
1.内存分配
-
JVM虚拟机,将其内存空间分为五个部分
- 栈:方法运行时使用的空间,如main方法运行,进入方法栈中执行
- 堆:存储对象或者数组,new来创建的,都存储在堆内存
- 方法区:存储可以运行的class文件
- 本地方法栈:JVM在使用操作系统功能的时候使用
- 寄存器:给cpu使用
# jdk8后将方法区取消,改为元空间,原方法区的功能放在了堆和元空间中
2.数组的内存
- main方法进入栈内存
- 定义数组进入栈内存
- 定义的同时new在堆内存中开辟空间
- 堆中的空间地址值赋值给栈内存中的数组
- 调用时,先通过栈内存中的数组变量的地址值,找到堆内存中的数据,再通过索引找到对应数据
- 赋值也同理,覆盖原来索引上的元素
- 创建第二个数组也同理,在堆内存中开辟一个新的独立空间
3.两个数组指向同一个空间
- 定义完第一个数组后,第二个数组定义并直接将第一个数组赋值给第二个数组,这时候就没有new
- 堆内存中是同一个空间,两个数组变量的地址值也是相同
- 修改任意一个数组中的数据,另一个数组也会被修改
7.数组常见问题
- 索引越界异常:访问了数组中不存在的索引
8.数组常见操作
1.求最值
- 先定义一个变量记录最值(变量初始化的值必须是数组中的一个值)
- 遍历数组获取每一个元素
- 让每一个元素和最值比较,比最值更大/更小,就让变量记录新的元素
- 遍历数组获取每一个元素
# 遍历输出可以使用print使其输出在同一行
2.求和
- 先定义一个求和变量
- 再循环得到每一个元素
- 加到变量中
- 再循环得到每一个元素
3.交换数据
- 和两个变量交换数据一样
- 将两个索引的数据交换,需要一个空的变量
# 可以使用循环实现数组首尾交换
4.打乱数据
- 使用
1 | import java.util.Random; |
# 需要先导入
1 | Random 变量 = new Random(); |
-
构造函数使用当前时间作为种子值
-
变量.nextInt(整数)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
\# 这是Random类中的一个方法,可以返回一个0~整数(不包含)的一个随机数
* 再赋值给一个新的变量
* 循环遍历数组
* 从第一个元素开始,和随机数元素交换
* 获取随机数写在循环中,所以每次生成的随机数不同
## 5.方法
### 1.方法的介绍
#### 1.定义
* **方法**(method)是程序当中**最小** 的执行单元
#### 2.使用场景
* 将重复的代码,具有独立功能的代码抽取到方法中
### 2.方法的格式
#### 1.最简单的
##### 1.定义
```java
public static void 方法名(){
方法体;
}
-
2.调用
1 | 方法名(); |
2.带参数的
1.定义
1 | public static void 方法名(参数1,参数2,……){ |
2.调用
1 | 方法名(参数1,参数2,……) |
# 参数个数必须和方法中的一样
3.形参和实参
- 形参:形式参数,是指方法定义中的参数
- 实参:实际参数,方法调用中的参数
3.带返回值的
1.定义
1 | public static 返回类型 方法名(参数1,参数2,……){ |
- return表示结束方法,return后就不能再写了
# 返回类型[]表示返回一个此数据类型的数组
2.调用
1.直接调用
1 | 方法名(实参); |
2.赋值调用
1 | 数据类型 变量名 = 方法名(实参); |
3.输出调用
1 | System.out.println(方法名(实参)); |
3.方法的重载
- 在同一个类 中,定义了多个同名 的方法,这些同名的方法具有同种的功能
- 每个方法具有不同的参数类型和参数个数,这些同名的方法,就构成了重载关系
- 参数不同
- 个数不同
- 类型不同
- 顺序不同:定义的形参的类型的顺序
# Java虚拟机会通过参数的不同来区分同名的方法
4.方法的内存
1.方法调用的基本内存原理
- 被调用则入栈,方法中调用了其他的方法则会再将其他的方法入栈,当栈顶的方法使用完后,出栈,再接着运行下面一个方法
2.方法传递基本数据类型的内存原理
基本数据类型
-
变量中存储的是真实的数据
-
数据值是存储在自己的空间中
-
赋值给其他变量,也是赋的真实的值
-
传递基本数据类型时,传递的是真实的数据,形参的改变不会影响实际参数的值
# 例如先定义一个变量并赋值为1,再方法中将变量赋值为2,调用方法传入定义的变量,输出变量,此时显示的值仍为1
定义并赋值时,先入栈,然后调用的方法再入栈,给变量赋值为2,然后方法出栈,但是先入栈的变量并没有被修改值,所以再打印变量,输出的仍然是原来的值
要解决这个问题,可以在方法中返回修改后的变量,同时使用方法格式中的带返回值的格式中的赋值调用,再赋给一个新的变量,再将这个变量输出
3.方法传递引用数据类型的内存原理
引用数据类型
-
变量中存储的是地址值,即使用其他空间中的数据,自己空间中存储的是地址值
-
传递引用数据类型,传递的是地址值,形参的改变会影响到实际参数的值
# 和数组的内存相同
6.面向对象
1.设计对象并使用
1.类和对象
- 类:是对象共同特征的描述
- 对象:是真实存在的东西
# java中必须先设计类,才能获得对象
1.如何定义类
1 | public class 类名{ |
2.如何获得类的对象
1 | 类名 对象名 = new 类名(); |
3.如何使用对象
- 访问属性
1 | 对象名.成员变量 |
- 访问行为
1 | 对象名.方法名(……) |
2.类的补充
1.定义类的补充事项
-
用来描述一类事物的类,叫做:Jvavbean类
-
在Jvavbean类中,是不写main方法的
-
编写的main方法的类,叫做测试类
-
测试类中可以创建javabean类的对象并进行赋值调用
-
一个java文件中可以定义多个类,且只能有一个类是public修饰
-
public修饰的类名必须成为代码文件名
# 实际开放中一个文件定义一个class类
- 成员变量的完整定义格式是
1 | 修饰符 数据类型 变量名 = 初始化值; |
# 一般无需指定初始化值,存在默认值
2.开发中类的设计
- 根据需求,从中提取名词,作为属性
- 根据需求,从中提取动词,作为行为
2.封装
- 封装:如何正确设计对象的属性和方法
# 面向对象三大特征之一
1.原则
- 对象代表什么,就得到封装对应的数据,并提供数据对应的行为
2.private关键字
-
是一个权限修饰符
-
可以修饰成员(成员变量和成员方法)
-
被private修饰的成员只能在本类中才能访问
-
保证数据安全性
# 与public相反
- 如果要使其他类能够使用,可以提供两个方法
- set:给成员赋值
- get:对外提供成员变量的值
# 这两个需要用public修饰
3.this关键字
1.成员变量和局部变量
1.局部变量
- 定义在方法内
2.成员变量
- 定义在类内,方法外
3.就近原则
-
局部变量和成员变量重名时
-
使用本方法的变量
2.this
1 | this.变量名 |
- 可以使用成员变量
4.构造方法
1.概述
- 构造方法:也叫构造器,构造函数
- 作用:在创建对象的时候给成员变量进行赋值的
2.构造方法的格式
1 | public class 类名{ |
-
特点
-
方法名与类名相同
-
没有返回值类型,void也没有
-
没有具体的返回值(不能由return带回结果数据)
-
-
执行时机
- 创建对象的时候由虚拟机调用,不能手动调用构造方法
- 每创建一次对象,就会调用一次构造方法
3.构造方法注意事项
-
定义
- 如果没有定义构造方法,系统将给出一个默认的无参数构造方法
- 如果定义了构造方法,系统将不再提供默认的构造方法
-
重载
- 带参构造方法,和无参数构造方法,两者方法名相同,但是参数不同,这就叫构造方法的重载
-
推荐使用方式
- 无论是否使用,都手动书写无参数构造方法,和带全部参数的构造方法
5.标准JavaBean
- 标准的JavaBean类
- 类名要见名知意
- 成员变量使用private修饰
- 提供至少两个构造方法
- 无参构造方法
- 带全部参数的构造方法
- 成员方法
- 提供每一个成员变量对应的set/get
- 如果还有其他行为,也需要写上
6.对象内存图
1.一个对象的内存图
- 例如
1 | Student s = new Student(); |
- 1.加载class文件到方法区
- main()同时临时存储到方法区
- 再加载JavaBean类的class文件
- 包含所有成员变量和成员方法等
- 2.申明局部变量
- 在栈内存中,main方法进栈后,在方法中开辟一个空间即s
- 3.在堆内存中开辟一个空间
- new的Student
- 其中存储所有成员变量
- 还有成员方法的地址
- 指向方法区的方法
- 用对象调用方法时可以找到对应方法
- new的Student
- 4.默认初始化
- 给堆内存中的成员变量默认初始化
- 5.显示初始化
- 如果一开始赋值了,堆内存中的成员变量就按赋的值初始化
- 6.构造方法初始化
- 空参构造或者有参构造
- 7.将堆内存中的地址赋值给左边的局部变量
- 堆内存中的地址值赋值给栈内存中的s
- 8.方法进栈
- 调用方法
- 9.方法出栈
- main方法中调用的方法使用完后先出栈
- main方法再出栈
- 其中的变量也消失
- 变量指向的堆内存中的空间也消失
- 其中的变量也消失
2.多个对象的内存图
- 和一个对象的内存图相似
- 但是JavaBean类的class文件只需要加载一次
- 堆内存中的两个方法地址都指向方法区的同一个方法
3.两个变量指向同一个对象内存图
-
和前面的两个数组指向同一个空间相似
-
如果将第一个变量赋值null,表示不存在的空间
- 则这个变量就会和堆内存中的空间的连接断开
- 输出时就会显示NullPointerException报错
-
但是第二个变量和堆内存中的空间并没有断开,所以还能正常输出变量
-
如果两个变量都赋值null则和堆内存的连接都断开,堆内存中的空间就变成会垃圾消失
4.this的内存原理
- this的本质:代表方法调用者的地址值
5.基本数据类型和引用数据类型的区别
1.基本数据类型
- 数据直接存储在栈内存中
# 赋值给其他变量,也是赋的真实的值
2.引用数据类型
- 栈内存中记录的是其他空间的地址值
# 赋值给其他变量,赋的地址值
6.局部变量和成员变量的区别
| 区别 | 成员变量 | 局部变量 |
|---|---|---|
| 类中的位置不同 | 类中,方法外 | 方法内,方法申明上 |
| 初始化值不同 | 有默认初始化值 | 没有,使用之前需要完成赋值 |
| 内存位置不同 | 堆内存 | 栈内存 |
| 生命周期不同 | 随着对象的创建而存在,随着对象的消失而消失 | 随着方法的调用而存在,随着方法的运行结束而消失 |
| 作用域 | 整个类中有效 | 当前方法中有效 |
7.字符串
1.API
- API(Application Programming Interface):应用程序编程接口
2.String
1.概述
-
java.lang.String类代表字符串,java程序中的所有字符串文字都为此类的对象
-
字符串的内容是不会发生改变的,它的对象在创建后不能被改变
# 要修改就要先对原字符串,创建一个数组,里面存储每个字符,再修改对应的字符
2.创建String对象的两种方式
1.直接赋值
1 | Sting name = " "; |
2.new
| 构造方法 | 说明 |
|---|---|
| public String() | 创建空白字符串,不含任何内容 |
| public String(String original) | 根据传入的字符串,创建字符串对象 |
| public String(char[] chs) | 根据字符数组,创建字符串对象 |
| public String(byte[] chs) | 根据字节数组,创建字符串对象 |
# 后两个都要先创建一个对应的数组即char[] chs和byte[] chs
3.内存分析
- 有一个单独的串池(StringTable)
# 7以前在方法区,后在堆内存中
-
直接创建 的,在赋值时,系统先在串池观察是否有这个字符串,如果没有则创建,然后将地址赋值到栈内存中的变量,如果有则直接赋值到栈内存中的变量(复用)
-
new的,不会涉及到串池,直接在堆内存中开辟空间,直接把地址值赋值到栈内存中,不会有复用现象,占用更多空间
# 键盘录入的也是new的
3.String的比较
1.==号
1.基本数据类型
- 比较的是具体的数据值
2.引用数据类型
- 比较的是数据的的地址值
2.bolean equals方法
- 变量名.equals(要比较的字符串):完全一样结果才是true,否则为false
3.bolean equalslgnoreCase方法
- 变量名.equalslgnoreCase(要比较的字符串):忽略大小写的比较
4.StringBuilder
1.概述
- StringBuilder可以看作一个容器,创建后里面的内容是可变的
- 作用:提高字符串的操作效率
2.构造方法
| 方法名 | 说明 |
|---|---|
| public StringBuilder() | 创建一个空白可变字符串对象,不含任何内容 |
| public StringBuilder(String str) | 根据字符串的内容,来创建可变字符串对象 |
3.常用方法
| 方法名 | 说明 |
|---|---|
| public StringBuilder append(任意类型) | 添加数据,并返回对象本身 |
| public StringBuilder reverse() | 反转容器中的内容 |
| public int length() | 返回长度(字符出现的个数) |
| public String toString() | 通过toString()就可以实现把StringBuilder转换为String |
5.StringJoiner
- StringJoiner和StringBuilder一样,也可以看成是一个容器,创建之后里面的内容是可变的
- 作用:提高字符串的操作效率,而且代码编写更加简洁
# 因为在jdk8后才出现,所以使用较少
1.构造方法
| 方法名 | 说明 |
|---|---|
| public StringJoiner (间隔符号) | 创建一个StringJoiner对象,指定拼接时的间隔符号 |
| public StringJoiner(间隔符号,开始符号,结束符号) | 创建一个StringJoiner对象,指定拼接时的间隔符号,开始符号,结束符号 |
2.成员方法
| 方法名 | 说明 |
|---|---|
| public StringJoiner add(添加的内容) | 添加数据,并返回对象本身 |
| public int length() | 返回长度(字符出现的个数) |
| public String toString() | 返回一个字符串(该字符串就是拼接之后的结果) |
6.字符串原理
1.字符串存储的内存原理
- 直接赋值的
- 会复用 字符串常量池中的
- new出来的
- 不会复用,而是开辟一个新的空间
2.==比较的原理
- 基本数据类型 比较数据值
- 引用数据类型 比较地址值
3.字符串拼接的底层原理
-
拼接的时候没有变量,都是字符串
- 触发字符串的优化机制
- 在编译的时候就已经是最终的结果了
-
有变量和字符参与拼接
- jdk8前使用StringBuilder
- main方法进栈
- 变量直接赋值,并且在串池生成一个对应字符串
- 在堆内存中创建一个StringBuilder的方法,通过append方法将参与的变量和字符放到StringBuilder中
- 再用toString将其变回字符串,字符串就变成了拼接好的
- toString中使用了一个名为newString的方法,这个方法在返回的时候是new了一个新的字符串
- jdk8
- 先预估最终字符串的长度并创建该长度的数组
- 把字符存进去后,再把数组整体变成一个字符串
- jdk8前使用StringBuilder
4.StringBuilder提高效率原理图
- main方法进栈
- StringBuilder方法进栈,同时在堆内存中开辟空间
- 调用append方法把字符全部添加到堆内存中的空间中
5.StringBuilder原码分析
- 在创建的时候会创建一个字节数组,默认容量 16,表示最多能存储16
- 向其中添加字符串时,添加的是ASCII码
- 当添加的字符串大于16,就会扩容,创建一个新的数组,容量=老容量*2+2
- 如果添加的数据超出了扩容后的容量,则会创建一个当前数据量的容量的数组
8.ArrayList
1.集合介绍
- 与数组类似,用于存储元素,但区别于数组的是可以自动扩容
- 但是集合只能存储引用数据类型
- 如果要存储基本数据类型就要包装类
- 基本数据类型中int对应Integer,char对应Character,其余数据类型都将首字母大写
2.集合
ArrayList
-
ArrayList是Java中写好的一个类
-
需要导包:
1 | import java.util.ArrayList; |
1.泛型
- 限定集合中存储数据的类型
- 格式:
1 | ArrayList<类型> 变量名 = new ArrayList<类型>(); |
# jdk7前
1 | ArrayList<类型> 变量名 = new ArrayList<>(); |
# jdk7后
2.成员方法
| 方法名 | 说明 |
|---|---|
| boolean add(E e) | 添加元素,返回值表示是否添加成功 |
| boolean remove(E e) | 删除指定元素,返回值表示是否删除成功 |
| E remove(int index) | 删除指定索引的元素,返回被删除元素 |
| E set(int index,E e) | 修改指定索引下的元素,返回原来的元素 |
| E get(int index) | 获取指定索引的元素 |
| int size() | 集合的长度,也就是集合中元素的个数 |
9.面向对象进阶
1.static
1.static
- static表示静态,是Java中的一个修饰符,可以修饰成员方法,成员变量
1.静态变量
-
特点:
- 被该类所有对象共享
- 不属于对象,属于类
- 静态变量是随着类的加载而加载的,优先于对象出现
-
调用方式:
- 类名调用(推荐)
- 对象名调用
-
内存图
-
main方法进栈
-
用类名调用静态变量
- 类名的字节码会加载到方法区
- 在堆内存中会创建一个静态存储位置(静态区)
# jdk8前静态区在方法区
- 在静态区存入静态变量
- 静态变量是随着类的加载而加载的,优先于对象出现
- 给变量赋值
-
创建一个对象
-
在堆内存中为非静态变量开辟空间
-
给对象的属性赋值
-
2.静态方法
-
特点:
- 多用于测试类 和工具类
- 工具类:
- 不描述任何事物的类
- 类名见名知意
- 私有化构造方法
- 方法定义为静态便于调用
- 不描述任何事物的类
- 工具类:
- JavaBean类中很少使用
- 多用于测试类 和工具类
-
调用方式:
- 类名调用(推荐)
- 对象名调用
2.注意事项
-
静态方法只能访问静态变量和静态方法
-
非静态方法可以访问静态变量或静态方法,也可以访问非静态的成员变量和非静态的成员方法
-
静态方法中没有this关键字
-
内存图
- 静态:
- 随着类的加载而加载
- 非静态:
- 跟对象有关
- 静态方法不能访问非静态变量(实例变量):
- main方法进栈
- 将对象的字节码文件加载到方法区
- 包含对象的属性变量和方法
- 将静态的变量存到堆内存中的静态区
- 静态方法进栈
- 方法调用变量会到静态区调用
- 但是静态区中只有静态的变量,非静态的在方法区
- 非静态可以访问所有:
- main方法进栈
- 将对象的字节码文件加载到方法区
- 包含对象的属性变量和方法
- 将静态的变量存到堆内存中的静态区
- 有new在堆内存中开辟空间
- 存储对象的属性变量
- 空间关联静态区
- 空间的地址赋值给栈内存中的变量
- 非静态方法调用到堆内存中访问开辟的空间
- 静态:
2.继承
1.概述
-
面向对象的三大特点之一
-
Java中提供一个关键字extends,用这个关键字,可以让一个类和另一个类建立起继承关系
1 | public class Student extends Person {} |
-
Student称为子类(派生类),Person称为父类(基类或超类)
-
将多个子类中重复的代码抽取到父类中,提高了代码的复用性
-
子类可以在父类的基础上,增加其他功能,使子类更强大
2.什么时候使用继承
- 在类与类之间,存在相同的内容,并满足子类是父类中的一种,就可以考虑使用继承,来优化代码
3.特点
- Java只支持单继承,不支持多继承,但支持多层继承,子类只能访问 父类中非私有的成员
- 只支持单继承:
- 一个子类只能继承一个父类
- 不支持多继承:
- 子类不能同时继承多个父类
- 支持多层继承:
- 子类的父类可以有父类
- 父类的父类就是子类的间接父类
- 所有类都直接或间接继承Object
- 默认继承于Object
- 子类的父类可以有父类
4.子类能继承的
| 父类中的 | 非私有 | private |
|---|---|---|
| 构造方法 | 不能 | 不能 |
| 成员变量 | 能 | 能 |
| 成员方法 | 能 | 不能 |
1.构造方法
- 如果继承父类的构造方法则构造方法的名字和父类相同,但是构造方法的特点是方法名和类名相同
2.成员变量
-
内存图
-
main方法进栈
-
字节码加载进方法区
-
将子类的字节码文件加载到方法区
-
将子类的父类的字节码文件加载到方法区
-
在栈内存中声明变量
- 在堆内存中开辟空间
- 把这个空间一分为二
- 存储子类和父类的成员
- 在堆内存中开辟空间
-
赋值时,先在堆内存的子类中找是否有对应的成员,没有则在父类中找,再赋值
-
# 但是如果父类中的变量private了,则不能赋值
3.成员方法
- 不会直接继承方法
- 而是会有一个虚方法表
- 虚方法:
- 非private
- 非static
- 非final
- 虚方法:
- 每个子类中继承父类的虚方法表的同时再加上自己的虚方法,然后给其子类继承
5.继承中的访问特点
1.成员变量
- 就近原则:逐级查找最近的变量
- 如果几个类中的变量重名:
- 不加关键字:从局部开始向上找
- 加this关键字:从本类中开始向上找
- 加super关键字:从父类中开始向上找
2.成员方法
-
与成员变量的特点相同
-
方法的重写:当父类的方法不能满足子类现在的需求时,需要进行方法重写
-
书写格式:在继承体系中,子类出现了和父类一样的方法声明,则这个子类的方法就是重写的方法
-
@Override重写注解:@Override写在重写后的方法上,校验子类重写时语法是否正确
-
本质:将原来继承的虚方法表中的方法覆盖为当前类的方法,其子类继承的虚方法表也就是覆盖后的虚方法表
-
-
注意事项
- 重写方法的名称和形参列表必须和父类中的一致
- 子类重写父类方法时,访问权限子类必须大于等于父类
- 子类重写父类方法时,返回值类型子类必须小于等于父类
- 只有被添加到虚方法表中的方法才能被重写
3.构造方法
-
父类中的构造方法不会被子类继承
-
子类中所有的构造方法默认先访问父类中的无参构造,再执行自己
- 子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类就无法使用
- 子类初始化之前,一定要调用父类构造方法先完成父类数据空间的初始化
-
子类的构造方法第一行语句默认都是super();(不写也是默认存在的),第二行才可以写构造方法
-
如果要调用父类的有参构造,则需要加上super(父类中带参构造的变量名);
6.this,super使用总结
1.this
- 可以理解为一个变量,表示当前方法调用者的地址值
2.super
- 代表父类存储空间
3.多态
- 面向对象三大特点之一
1.概述
- 同类型的对象,表现出的不同形态
1 | 父类类型 对象名称 = 子类对象; |
-
前提:
- 有继承关系
- 有父类引用指向子类对象
- 有方法重写
-
好处:
- 使用父类型作为参数,可以接收所有子类的对象
2.调用成员的特点
1.变量调用
- 编译看左边,运行看左边
# javac在编译的时候看左边的父类中有没有这个变量,有则能编译成功
# 运行时,实际获取的就是左边父类中成员变量的值
2.方法调用
- 编译看左边,运行看右边
# javac在编译的时候看左边的父类中有没有这个方法,有则能编译成功
# 运行时,实际运行的是子类中的方法
3.优势
- 在多态形式下,右边对象可以实现解耦合,便于扩展和维护
- 定义方法的时候,使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性和便利
4.弊端
- 不能使用子类的特有功能
- 如果要使用就要转换类型
# 就可以将其转换为真正的子类类型,从而调用子类的特有功能
# 转换类型与真实对象类型不一致会报错
判断是否为某一类型并且强制转换
1 | 变量名1 instanceof 类型1 变量名2 |
# 如果变量名1是类型1则强转为类型1,转换后变量名为变量名2
# 如果不是则不强转,结果返回false
# 在jdk14后
4.包,final,权限修饰符,代码块
1.包
-
文件夹,用于管理不同功能的Java类,便于后期代码维护
-
包名规则:
- 公司域名反写+包的作用,全部英文小写,见名知意
-
全类名(全限定名):
-
包名+类名
-
使用其他类时就要使用全类名
-
或者直接导包:
- import 全类名
-
使用同一个包中的类时,不需要导包
-
java.lang包中的类不需要导包
-
如果同时使用两个包中的同名类,需要用全类名
-
2.final
1.修饰方法
- 表示该方法是最终方法,不能被重写
2.修饰类
- 表示该类是最终类,不能被继承
3.修饰变量
-
叫做常量,只能被赋值一次
- 常量的命名:
- 单个单词:全部大写
- 多个单词:全部大写,中间用下划线连接
- 常量的命名:
-
修饰的变量是基本数据类型:
- 变量存储的数据值不能发生改变
-
修饰的变量是引用数据类型:
- 变量存储的地址值不能发生改变,对象内部的可以改变
# 例如数组中的值可以变,但是数组的地址值是不能变的
3.权限修饰符
作用范围
- private<空<protected<public
| 修饰符 | 同一个类 | 同一个包中的其他类 | 不同包下的子类 | 不同包下的无关类 |
|---|---|---|---|---|
| private | ✔ | |||
| 空 | ✔ | ✔ | ||
| protected | ✔ | ✔ | ✔ | |
| public | ✔ | ✔ | ✔ | ✔ |
# 如果方法中的代码抽取其他方法中共性的代码,这个方法一般也私有
4.代码块
1.局部代码块
- {}中的内容,可以其他结束代码块中的变量的生命周期
# 但是现在已经不需要节省变量的一点空间了
2.构造代码块
- 把构造方法中重复的内容写在成员位置的代码块
- 执行时机:
- 在创建本类对象的时候会先执行构造代码块再执行构造方法
# 使用也较少,因为不够灵活
3.静态代码块
- 格式:
- static{}
- 特点:
- 需要通过static关键字修饰,随着类的加载而加载,并且自动触发,只执行一次
- 使用场景:
- 在类加载的时候,做一些数据初始化的时候使用
5.抽象类
1.抽象方法
-
一个方法抽取到父类中,但是子类的具体写法不同,这时候就可以写一个抽象方法,起所在的类就是抽象类
-
抽象方法的定义格式:
1 | public abstract 返回值类型 方法名(参数列表); |
- 抽象类的定义格式:
1 | public abstract class 类名{} |
2.注意事项
- 抽象类不能实例化
- 即不能创建对象
- 抽象类不一定有抽象方法,有抽象方法一定是抽象类
- 抽象类可以有构造方法
- 当创建子类对象时,给属性进行赋值
- 抽象类的子类
- 重写抽象类中的所有抽象方法
- 或者是抽象类
3.意义
- 强制子类按照格式重写这个抽象方法
- 在开发时可以更加统一
6.接口
- 一个父类下的几个子类,其他几个可以共享一个方法,但也有不能使用这个方法的,这样就不能写在父类中
- 这时候就需要接口,只给几个子类使用
- 和抽象类很像
- 但是一般只表示行为
- 一般不像抽象类表示一种事物
1.定义接口并使用接口
- 接口用关键字interface来定义
1 | public interface 接口名{} |
- 接口不能实例化
- 接口和类之间是实现关系,通过implements关键字表示
1 | public class 类名 implements 接口名{} |
- 接口的子类(实现类)
- 重写接口中的所有抽象方法
- 或者是抽象类
2.接口中的成员特点
1.成员变量
- 只能是常量
- 默认修饰符:public static final
2.构造方法
- 无
3.成员方法
- 只能是抽象方法
- 默认修饰符:public abstract
# jdk7前接口中只能定义抽象方法
3.接口和类之间的关系
1.类和类
- 继承关系,只能单继承,不能多继承,但是可以多层继承
2.类和接口
- 实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
# 在多个接口中有重名的方法,重写的时候所有方法只需要重写一次即可
3.接口和接口
- 继承关系,可以单继承,也可以多继承
# 实现类在实现的时候就要把接口的继承体系中的所有方法都重写
4.JDK8后的接口
-
可以定义有方法体的方法,即默认方法
- 格式:
1
public default 返回值类型 方法名(参数列表){}
- 可以不强制重写,但是重写的时候就要把default去掉
- 当多个接口中有相同名字的默认方法,子类必须对该方法重写
-
允许在接口中定义静态方法,用static修饰
1
public static 返回值类型 方法名(参数列表){}
- 只能通过接口名调用,不能通过实现类名或者对象名调用
-
可以定义私有的方法
- 格式:
1
private 返回值类型 方法名(参数列表){}
- 对于静态的:
1
private static 返回值类型 方法名(参数列表){}
- 用于抽取出方法中重复的代码,再给方法调用,但是不让其他方法调用
# 私有方法在jdk9后
5.接口的应用
-
接口代表规则,是行为的抽象,要让一个类拥有这个行为,就让这个类实现对应接口
-
当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方法称之为接口多态
6.适配器设计模式
-
设计模式 :
- 是一套被反复使用,多数人知晓的,经过分类编目的,代码设计经验的总结,使用设计模式是为了可重用代码,让代码更容易被他人理解,保证代码可靠性,程序的重用性
-
适配器设计模式 :
- 解决接口与接口实现类之间的矛盾问题
- 当一个接口中有很多抽象方法,但有时候只需要用到其中一部分的时候
- 先编写一个中间类,实现对应接口,对接口中的抽象方法进行空实现,即不写方法体
- 让真正的实现类继承中间类,并重写需要用到的方法
- 为了避免其他类创建适配器类的对象,中间类用abstract修饰
7.内部类
-
类的五大成员之一
-
在一个类中,再定义一个类
-
内部类表示的事物是外部类的一部分
-
内部类单独出现没有任何意义
-
访问特点:
- 内部类可以直接访问外部类的成员,包括私有
- 外部类要访问内部类的成员,必须创建对象
1.成员内部类
- 写在成员位置的,属于外部类的成员
1.如何书写
- 可以被一些修饰符修饰
- 成员内部类中的成员,在jdk16后可以定义静态变量
2.创建成员内部类
- 在外部类中编写方法,对外提供内部类的对象
# 在内部类私有的时候使用
或
- 直接创建:
1 | 外部类名.内部类名 对象名 = 外部类对象.内部类对象; |
3.成员内部类如何获取外部类的成员变量
-
没有重名的时候可以直接调用
-
有重名时则会就近原则
-
用this可以调用内部类的方法外的变量
-
要调用外部类的变量则要用外部类名.this.变量名
-
内存图
- 内部类和外部类是两个字节码加载到方法区
- 堆内存中开辟两个空间
- 一个是外部类
- 一个是内部类
- 内部类中除了其本身的成员,还有一个隐藏的this记录外部类对象的地址值
2.静态内部类
-
成员内部类的一种特殊情况
-
被用static修饰
-
创建静态内部类对象的格式
1 | 外部类名.内部类名 对象名 = new 外部类名.内部类名; |
-
调用非静态方法的格式
- 先创建对象,用对象调用
-
调用静态方法的格式
1 | 外部类名.内部类名.方法名(); |
3.局部内部类
- 将内部类定义在方法里面,类似于方法里面的局部变量
- 外界是无法直接使用的,需要在方法内部创建对象并使用
- 该类可以直接访问外部类的成员,也可以访问方法内的局部变量
4.匿名内部类
- 本质就是隐藏了名字的内部类
- 可以写在成员位置,也可以写在局部位置
- 格式:
1 | new 类名或者接口名(){ |
- 其实际名字:外部类名$序号
- 这个整体就是一个类的子类对象或者是一个接口的实现类对象
- 应用场景
- 当方法的参数是接口或者类时
- 可以传递这个接口的实现类对象
- 但是如果这个实现类对象只使用一次,就没必要定义,可以用匿名内部类简化代码
10.常用API
1.Math
- 用于进行数学计算的工具类
- 私有化构造方法,所有方法都是静态的
- 用Math.方法名 调用
| 方法名 | 说明 |
|---|---|
| public static int abs(int a) | 获取参数绝对值 |
| public static double ceil(double a) | 向上取整 |
| public static double floor(float a) | 向下取整 |
| public static int round(float a) | 四舍五入 |
| public static int max(int a, int b) | 获取两个int值中的较大值 |
| public static double pow(double a,double b) | 返回a的b次幂的值 |
| public static double random() | 返回值为double的随机值,0.0-1.0,包含0.0,不包含1.0 |
# 在int类型中的最小值-2147483648没有绝对值
2.System
- 工具类,提供了一些于系统相关的方法
| 方法名 | 说明 |
|---|---|
| public static void exit(int status) | 终止当前运行的Java虚拟机,其中0为正常停止,非0为异常停止 |
| public static long currentTimeMills() | 返回当前系统的时间毫秒值形式 |
| public static void arraycopy(数据源数组,起始索引,目的地数组,起始索引,拷贝个数) | 数组拷贝 |
# 数组拷贝时如果是基本数据类型则数据类型要一致,如果是引用数据类型则子类类型可以赋值给父类类型也不能超过数组长度
3.Runtime
- 表示当前虚拟机的运行环境
| 方法名 | 说明 |
|---|---|
| public static Runtime grtRuntime() | 当前系统的运行环境对象 |
| public void exit(int status) | 停止虚拟机 |
| public int availableProcessors() | 获得CPU的线程数 |
| public long maxMemory() | JVM能从系统中获取总内存大小(单位byte) |
| public long totalMemory() | JVM已经从系统中获取总内存大小(单位byte) |
| public long freeMemory() | JVM剩余内存大小(单位byte) |
| public Process exec(String command) | 运行cmd命令 |
4.Object和Objects
- Java中的父类,所有类都直接或简洁的继承于Object类
1.Object的构造方法
| 方法名 | 说明 |
|---|---|
| public Object() | 空参构造 |
2.Object的成员方法
| 方法名 | 说明 |
|---|---|
| public String toString() | 返回对象的字符串表示形式 |
| public boolean equals(Object obj) | 比较两个对象是否相等 |
| protected Object clone(int a) | 对象克隆 |
# Object中的equals比较的是地址值,一般需要重写用alt+insert选择自动重写,可以比较具体的属性
# toString一般也会重写,打印对象时打印属性
3.对象克隆
- 把A对象的属性值完全拷贝给B对象,也叫对象拷贝,对象复制
- 要重写Object中的clone方法
- 在JavaBean类中实现接口
1.浅克隆
- 基本数据类型直接拷贝数据
- 引用数据类型直接拷贝地址值
2.深克隆
- 基本数据类型直接拷贝数据
- 字符串复用串池的
- 引用数据类型
- 例如数组
- 先创建一个新的数组
- 把原来数组的数据拷贝到新的数组中
- 再把新的数组的地址值给对象
4.Objects
- 一个工具类,提供一些方法去完成一些功能
| 方法名 | 说明 |
|---|---|
| public static boolean equals(Object a,Object b) | 先做非空判断,比较两个对象 |
| public static boolean isNull(Object obj) | 判断对象是否为null,为null返回true,反之 |
| public static boolean nonNull(Object obj) | 判断对象是否为null,是isNull的结果相反 |
5.BigInteger和BigDecimal
1.BigInteger
1.构造方法
| 方法名 | 说明 |
|---|---|
| public BigInteger(int num,Random rnd) | 获取随机大整数,范围:0~ |
| public BigInteger(String val) | 获取指定的大整数,字符串中必须是整数 |
| public BigInteger(String val,int radix) | 获取指定进制的大整数 |
| public static BigInteger valueOf(long val) | 静态方法获取BigInteger的对象,内部有优化,对常用数字-16~16进行了优化,会提前创建好,如果多次获取不会重新创建新的 |
# 对象一旦创建,内部记录的值不能发生改变
2.常见成员方法
| 方法名 | 说明 |
|---|---|
| public BigInteger add(BigInteger val) | 加法 |
| public BigInteger subtract(BigInteger val) | 减法 |
| public BigInteger multiply(BigInteger val) | 乘法 |
| public BigInteger divide(BigInteger val) | 除法,获取商 |
| public BigInteger[] divideAndRemainder(BigInteger val) | 除法,获取商和余数,返回数组,0索引的为商,1索引的为余数 |
| public bollean equals(Object x) | 比较是否相同,比较的是属性值 |
| public BigInteger pow(int exponent) | 次幂 |
| public BigInteger max/min(BigInteger val) | 返回较大值/较小值 |
| public int inValue(BigInteger val) | 转为int类型整数,超出范围数据有误 |
3.底层存储方式
- 先把一个大整数转化成补码
- 再把补码每32位分为一组
- 再把每一组转成各自的十进制
- 再按顺序放到一个数组中
- 数组的最大长度的理论值是int的最大值:2147483647约为21亿
- 数组中的每一位能表示的数字范围:-2147483648~2147483647约为42亿
- 所以BigInteger能表示的最大数字为42亿的21亿次方
- 几乎是无限的
2.BigDecimal
- 计算机中用二进制存储小数通常需要很多位
- 而在Java中
| 类型 | 占用字节数 | 总bit位数 | 小数部分bit位数 |
|---|---|---|---|
| float | 4个字节 | 32个bit位 | 23个bit位 |
| double | 8个字节 | 64个bit位 | 52个bit位 |
1.作用
- 用于小数的精确计算
- 用于表示很大的小数
2.创建对象
- 通过传递double类型的小数来创建对象
# 可能不精确
-
通过传递字符串表示的小数来创建对象
-
通过静态方法获取对象
# 如果要表示的数字没有超过double的范围,建议使用这种方法
# 如果传递0~10之间的整数,包含0和10,那么方法会返回已经创建好的对象,不会new
3.使用
| 方法名 | 说明 |
|---|---|
| public static BigDecimal valueOf(double val) | 获取对象 |
| public BigDecimal add(BigDecimal val) | 加法 |
| public BigDecimal subtract(BigDecimal val) | 减法 |
| public BigDecimal multiply(BigDecimal val) | 乘法 |
| public BigDecimal divide(BigDecimal val) | 除法 |
| public BigDecimal divide(BigDecimal val,精确几位,舍入模式) | 除法 |
4.底层存储方式
- 将要存储的字符串形式的小数
- 先遍历每一个字符
- 然后将这些字符对应的ASCII码存储到数组中
6.正则表达式
- 用**.matches(“规则”)** 使用正则表达式
1.作用
- 校验字符串是否满足规则
- 在一段文本中查找满足要求的内容
2.规则
字符类(只匹配一个字符)
| 格式 | 说明 |
|---|---|
| [abc] | 只能是a,b或c |
| [^abc] | 除了a,b,c之外的任何字符 |
| [a-zA-Z] | a到z A到Z |
| [a-d[m-p]] | a到d,或m到p |
| [a-z&&[def]] | a-z和d,e,f的交集,即d,e,f |
| [a-z&&[^bc]] | a-z和非bc的交集(等同于[ad-z]) |
| [a-z&&[^m-p]] | a到z和除了m到p的交集(等同于[a-lq-z] |
预定义字符(只匹配一个字符)
| 格式 | 说明 |
|---|---|
| . | 任何字符 |
| \d | 一个数字[0-9] |
| \D | 非数字[^0-9] |
| \s | 一个空白字符[\t\n\x08\f\r] |
| \S | 非空白字符[^\s] |
| \w | [a-zA-A_0-9]英文,数字,下划线 |
| \W | [^\w]一个非单词字符 |
# 用的时候在\前再加一个\
数量词
| 格式 | 说明 |
|---|---|
| X? | X,一个或0次 |
| X* | X,0次或多次 |
| X+ | X,一个或多次 |
| X{n} | X,正好n次 |
| X{n,} | X,至少n次 |
| X{n,m} | X,至少n次但不超过m次 |
3.分组
- 用()将规则划分组
- 以左括号为基准,最左为第一组
4.捕获分组
- 后续还要使用本组的数据
- 在正则内部:
- \\组号
- 在正则外部:
- $组号
5.非捕获分组
- 分组后不需要再使用本组数据,仅仅将数据括起来
| 符号 | 含义 |
|---|---|
| (?:正则) | 获取所有 |
| (?=正则) | 获取前面部分 |
| (?!正则) | 获取不是指定内容的前面部分 |
# 非捕获分组是不会占用组号的
7.JDK7以前时间相关类
1.Date时间类
- JDK写好的JavaBean类,用来描述时间,精确到毫秒
- 利用空参构造创建的对象,默认表示系统当前时间
- 利用有参构造创建的对象,表示指定时间
- 修改时间对象中的毫秒值
- setTime(毫秒值);
- 获取时间对象中的毫秒值
- getTime();
2.SimpleDateFormat类
- 格式化:
- 将时间转化形式
- 解析:
- 将字符串表示的时间变成Date对象
| 构造方法 | 说明 |
|---|---|
| public SimpleDateFormat() | 构造一个SimpleDateFormat,使用默认格式 |
| public SimpleDateFormat(String pattern) | 构造一个SimpleDateFormat,使用指定格式 |
# 其中格式例如:yyyy-MM-dd HH:mm:ss或者yyyy年MM月dd日 HH时mm分ss秒
| 常用方法 | 说明 |
|---|---|
| public final String format(Date date) | 格式化(日期对象转化为字符串) |
| public Date parse(String source) | 解析(字符串转化为日期对象) |
3.Calendar
-
代表系统当前时间的日历对象,可以单独修改,获取时间中的年月日
-
是一个抽象类,不能直接创建对象
-
获取Calendar日历类对象的方法
| 方法名 | 说明 |
|---|---|
| public static Calendar getInstance() | 获取当前时间的日历对象 |
| 常用方法 | 说明 |
|---|---|
| public final Date getTime() | 获取日期对象 |
| public final setTime(Date date) | 给日历设置日期对象 |
| public long getTimeInMillis() | 拿到时间毫秒值 |
| public void setTimeInMillis(long millis) | 给日历设置时间毫秒值 |
| public int get(int field) | 取日历中的某个字段信息 |
| public void set(int field,int value) | 修改日历的某个字段信息 |
| public void add(int field,int amount) | 为某个字段增加/减少指定的值 |
8.JDK8新增时间相关类
- 原有的时间对象是不变的
1.Date时间类
- ZoneId:时区
| 方法名 | 说明 |
|---|---|
| static Set |
获取Java中支持的所有时区 |
| static ZoneId systemDefault() | 获取系统默认时区 |
| static ZoneId of(String zonId) | 获取一个指定时区 |
- Instant:时间戳
| 方法名 | 说明 |
|---|---|
| static Instant now() | 获取当前时间的Instant对象(标准时间) |
| static Instant ofxxxx(long epochMilli) | 根据(秒/毫秒/纳秒)获取Instant对象 |
| ZonedDate atZone(ZoneId zone) | 指定时区 |
| boolean isxxxx(Instant otherInstant) | 判断系列的方法 |
| Instatnt minusxxx(long millisToSubtract) | 减少时间系列的方法 |
| Instant pulsxxx(long millisToSubstract) | 增加时间系列的方法 |
# 其中xxx是Years/Days/Hours/Minutes/Nanos/Seconds/Weeks
- ZoneDateTime:带时区的时间
| 方法名 | 说明 |
|---|---|
| static ZonedDateTime now() | 获取当前时间的ZonedDateTime对象 |
| static ZonedDateTime ofxxxx(……) | 获取指定时间的ZonedDateTime对象 |
| ZonedDateTime withxxx(时间) | 修改时间系列的方法 |
| ZonedDateTime minusxxx(时间) | 减少时间系列的方法 |
| ZonedDateTime plusxxx(时间) | 增加时间系列的方法 |
2.SimpleDateFormat类
- DateTimeFoemat:用于时间的格式化和解析
| 方法名 | 说明 |
|---|---|
| static DateTimeFormatter ofPattern(格式) | 获取格式对象 |
| String format(时间对象) | 按照指定方式格式化 |
3.Calendar
- LocalDate:年月日
- LocalTime:时分秒
- LocalDateTime:年月日时分秒
| 方法名 | 说明 |
|---|---|
| static xxx now() | 获取当前时间的对象 |
| static xxx of(……) | 获取指定时间的对象 |
| get开头的方法 | 获取日历中的年月日时分秒风信息 |
| isBefore,isAfter | 比较两个LocalDate |
| with开头的 | 修改时间系列的方法 |
| minus开头的 | 减少时间系列的方法 |
| plus开头的 | 增加时间系列的方法 |
| 方法名 | 说明 |
|---|---|
| public LocalDate toLoacalDate() | LocalDateTime转换成一个LocalDate对象 |
| public LocalTime toLocalTime() | LocalDateTime转换成一个LocalTime对象 |
4.工具类
- Duration:时间间隔(秒,纳秒)
- Period:时间间隔(年月日)
- ChronnUnit:时间间隔(所有单位)
9.包装类
-
基本数据类型对应的引用类型
-
基本数据类型中int对应Integer,char对应Character,其余数据类型都将首字母大写
-
在JDK5提出一个机制:
- 自动装箱
- 把基本数据类型自动的变成其对应的包装类
- 自动拆箱
- 把包装类自动的变成其对应的基本数据类型
- 自动装箱
-
int和Integer可以看作一个东西,在内部会自动转换
-
Integer成员方法
| 方法名 | 说明 |
|---|---|
| public static String toBinaryString(int i) | 得到二进制 |
| public static String toOctalString(int i) | 得到八进制 |
| public static String toHexString(int i) | 得到十六进制 |
| public static int paresInt(String s) | 把字符串类型的整数转换为int类型的整数 |