java_1
❌第一章 java概述
一、什么是程序
程序:计算机执行某些操作或解决某个问题而编写的一系列有序指令的集合
二、java的特点
- java的语言是面向对象的(oop)
- Java 语言是健壮的。Java 的强类型机制、异常处理、垃圾的自动收集等是Java 程序健壮性的重要保证
- Java 语言是跨平台性的。[即: 一个编译好的.class 文件可以在多个系统下运行,这种特性称为跨平台]
- Java 语言是解释型的[了解]
解释性语言:javascript,PHP, java 编译性语言: c / c++
区别是:解释性语言,编译后的代码,不能直接被机器执行,需要解释器来执行, 编译性语言, 编译后的代码, 可以直接被机器执行, c /c++
三、java的核心机制-JVM虚拟机
JVM:java virtual machine
基本介绍
- JVM 是一个虚拟的计算机,具有指令集并使用不同的存储区域。负责执行指令,管理数据、内存、寄存器,包含在JDK 中.
- 对于不同的平台,有不同的虚拟机。
- Java 虚拟机机制屏蔽了底层运行平台的差别,实现了“一次编译,到处运行”
四、什么是JDK、JRE
JDK基本介绍
- JDK 的全称(Java Development Kit Java 开发工具包)
JDK = JRE + java 的开发工具 [java, javac,javadoc,javap 等] - JDK 是提供给Java 开发人员使用的,其中包含了java 的开发工具,也包括了JRE。所以安装了JDK,就不用在单独安装JRE 了
JRE基本介绍
- JRE(Java Runtime Environment Java 运行环境)
JRE = JVM + Java 的核心类库[类] - 包括Java 虚拟机(JVM Java Virtual Machine)和Java 程序所需的核心类库等,如果想要运行一个开发好的Java 程序,计算机中只需要安装JRE 即可
JDK、JRE和JVM的关系
- JDK = JRE + 开发工具集(例如Javac,java 编译工具等)
- JRE = JVM + Java SE 标准类库(java 核心类库)
- 如果只想运行开发好的 .class 文件 只需要JRE
五、下载、安装JDK
https://www.oracle.com
六、配置环境变量path
为什么要配置path
没有配置环境变量无法使用java
配置环境变量path的步骤
- 我的电脑–>属性–>高级系统设置–>环境变量
- 增加JAVA_HOME 环境变量,指向jdk的安装路径 c:\····
- 编辑path环境变量,增加
%JAVA_HOME%\bin
- 打开DOS命令窗口,任意目录下敲入java/javac。如果出现javac的参数信息,则配置成功
七、java开发的注意事项和相关要求
java执行的流程分析
- .java文件(源文件)通过指令javac编译形成了.class文件
- .class文件(字节码文件)通过java指令运行出结果
java开发注意事项和细节
Java源文件以.java为扩展名。源文件的基本组成部分是类(class)
Java应用程序的执行入口是main()方法。它有固定的书写格式:
1
2
3public static void main(String[] args) {
}Java语言严格区分大写
Java方法由一条条语句构成,每个语句以
;
结束大括号都是成对出现的,缺一不可。
一个源文件中最多只能有一个public类。其它类的个数不限。
如果源文件包含一个public类,则文件名必须按该类名命名!
一个源文件中最多只能有 public类。其它类的个数不限,也可以将main方法写在非 public类中.然后指定运行非public类”这样入口方法就是非public的main方法
八、java转义字符
java常用的转义字符
\t
:一个制表位,实现对齐的功能\n
:换行符\\
:一个\\"
:一个”\'
:一个’\r
:一个回车
九、java注释
介绍
用于注解说明解释程序的文字就是注释,注释提高了代码的阅读性(可读性);
注释是一个程序员必须要具有的良好编程习惯。将自己的思想通过注释先整理出来,再用代码去体现。
java中的注释类型
- 单行注释 //
- 多行注释 /* */
- 文档注释
/** */
使用细节
- 被注释的文字,不会被JVM(java 虚拟机)解释执行
- 多行注释里面不允许有多行注释嵌套
十、java代码规范
- 类、方法的注释.要以javadoc的方式来写。
- 非java Doc的注释,往往是给代码的维护者看的,着重告述读者为什么这样写, 如何修改.注意什么问题等
- 使用tab操作,实现缩进,默认整体向右边移动,时候用shift+tab整体向左移
- 运算符和=两边习惯性各加一个空格。
- 源文件使用utf-8编码
- 行宽度不要超过80字符
- 代码编写 次行风格 和 行尾风格
十一、DOS命令
Dos介绍
Dos: Disk Operating System 磁盘操作系统, 简单说一下windows 的目录结构
相对路径和绝对路径
相对路径:从当前目录开始定位,形成的一个路径
绝对路径:从顶级目录(如d:)开始定位,形成的路径
常用的dos命令
查看当前目录是有什么内容 dir
dir dir d:\abc\test
切换到其他盘下:盘符号 cd : change directory
切换到 c 盘 cd /D c:切换到当前盘的其他目录下 (使用相对路径和绝对路径演示), ..\表示上一级目录
案例演示: cd d:\abc2\test200 cd ....\abc2\test200切换到上一级:
案例演示: cd ..切换到根目录:cd
案例演示:cd \查看指定的目录下所有的子级目录 tree
清屏 cls [苍老师]
退出DOS exit
不常用
- md[创建目录]
- rd[删除目录]
- copy[拷贝文件]
- del[删除文件]
- echo[输入内容到文件]
- type,move[剪切])
✅第二章 变量
一、为什么需要变量
一个程序就是一个世界
变量是程序的基本组成单位
二、变量的介绍
概念
变量相当于内存中一个数据存储空间的表示,你可以把变量看做是一个房间的门牌号,通过门牌号我们可以找到房间,而通过变量名可以访问到变量(值)。
变量使用的基本步骤
声明变量
int a;
赋值
a = 60;
也可以一步到位int a = 60;
三、变量的快速入门
记录人的信息
1 | public class Var02 { |
变量使用注意事项
- 变量表示内存中的一个存储区域[不同的变量,类型不同,占用的空间大小不同, 比如:int4个字节,double就是8个字节
- 该区域有自己的名称[变量名]和类型[数据类型]
- 变量必须先声明,后使用,即有顺序
- 该区域的数据/值可以在同一类型范围内不断变化
- 变量在同一个作用域内不能重名
- 变量三要素 变量=变量名+值+数据类型,这一点请大家注意。
四、程序中+号的使用
- 当两边都是数值类型时,做加法运算
- 当左右两边有一边为字符串时,则做拼接运算
- 运算顺序:从左到右
五、数据类型
每一种数据都定义了明确的数据类型,在内存中分配了不同大小的内存空间(字节)。
java中的数据类型
- 基本数据类型
- 数值型
- 整数类型,存放整数
- byte[1] short[2] int[4] long[8]
- 浮点类型(小数)
- float[4] double[8]
- 整数类型,存放整数
- 字符型 char[2] ,存放单个字符 ‘a’
- 布尔型 boolean[1],存放true,false
- 数值型
- 引用数据类型
- 类
- 接口
- 数组
基本数据类型八种:byte short int long float double char boolean
引用类型: 类 接口 数组
整数类型
基本介绍
Java 的整数类型就是用于存放整数值的,比如 12 , 30, 3456 等等
案例
1 | byte n1 = 10; |
整形的类型
类型 | 占用存储空间 | 范围 |
---|---|---|
byte[字节] | 1字节 | -127~128 |
short[短整型] | 2字节 | -(2^15) ~ 2^15-1 |
int[整形] | 4字节 | -(2^31) ~ 2^31-1 |
long[长整形] | 8字节 | -(2^63) ~ 2^63-1 |
整形的使用细节
- Java各整数类型有固定的范围和字段长度,不受具体OS[操作系统]的影响,以 保证java程序的可移植性。
- Java的整型常量(具体值)默认为int型,声明long型常量须后加 l或’L’
- java程序中变量常声明为int型,除非不足以表示大数,才使用long
- bit:计区机中的最小储存单位。byte:计算机中基本存储单元[byte = 8 bit ]
浮点类型
基本介绍
Java 的浮点类型可以表示一个小数,比如 123.4 ,7.8 ,0.12 等等
浮点型的分类
类型 | 占用储存空间 | 范围 |
---|---|---|
单精度float | 4字节 | -3.43E38 ~ 3.40E38 |
双精度double | 8字节 | -1.798E308 ~ 1.798E308 |
说明
- 关于浮点数在机器中存放形式的简单说明,浮点数=符号位+指数位+尾数位
- 尾数部分可能丢失,造成精度损失(小数都是近似值)。
浮点类型使用细节
与整数类型类似, Java浮点类型也有固定的范围和字段长度,不受具体OS的
影响。[float 4个字节 double是8个字节]
Java的浮点型常量(具体值)默认为double声明float型常量,须后加 f 或 F
浮点型常量有两种表示形式
- 十进制数形式:如:5.12 512.0f .512 (必须有小数点)
- 科学计数法形式:如:5.12e2 [5.12*10的2次方] 5.12E-2 [5.12/10的2次方]
通常情况下,应该使用double型.因为它比float型更精确。[举例说明]
double num9 = 2.1234567851;
float num10 = 2.1234567851F;
浮点使用陷阱:2.7和 8.1/3 比较
字符类型
基本介绍
字符类型可以表示单个字符,字符类型是char,char 是两个字节(可以存放汉字),多个字符我们用字符串String
案例演示
char c1 = 'a';
char c2 = '\t';
char c3 = '韩';
char c4 = 97;
字符类型使用细节
字符常量是用单引号(‘ ’)括起来的单个字符。
例如:
char c1 = "a';
char c2 ='中'; char c3 = 9;
ava中还允许使用转义字符、‘来将其后的字符转变为 特殊字符型常量。
例如:
char c3 = '\n';
//‘n’ 表示 换行符在java中,char的本质是一个整数,在输出时,是 unicode 码对应的字符。
可以直接给char赋一个整数,然后输出时,会按照对应 unicode字符输出
[97–> a]
char类型是可以进行运算的,相当于一个整数,因为它都对应有Unicode码
注意
字符型存储到计算机中,需要将字符对应的码值(整数)找出来。比如 ‘a’
存储:‘a’ == > 码值 97 == > 二进制(110 0001)== > 存储
读取:二进制(110 0001) => 97 = = = > ‘a’ => 显示
字符和码值的对应关系是通过字符编码表决定的(是规定好的)
几种需要了解的编码表
ASCII码、Unicode编码、UTF-8编码
布尔类型
基本介绍
- 布尔类型也叫boolean类型,booolean类型数据只允许取值true和false,无 null
- boolean类型占1个字节
- boolean类型适于逻辑运算,一般用于程序流程控制、
- if条件控制语句
- while循环控制语句
- do while循环控制语句
- for循环控制语句
六、java API文档
API (Application Programming Interface,应 用程序编程接口)是Java提供的基本编程接口 (java提供的类还有相关的方法)。中文在线文档: https://www.matools.com
Java语言提供了大量的基础类,因此Oracle公司 也为这些基础类提供了相应的API文档,用于告诉 开发者如何使用这些类.以及这些类里包含的方法。
Java类的组织形式
举例说明如何後用ArrayList类有哪些方法.
安:包–> 类–> 方法 直接索引
七、基本数据类型转换
自动类型转换
基本介绍
当java程序在进行赋值或运算时,精度小的类型自动转换为精度大的数据类型,这就是自动类型转换
自动类型转换规则
数据类型按精度(容量)大小排序为
自动类型转换注意和细节
有多种类型的数据混合运算时,系统首先自动将所有数据 转换成容量最大的那种数据类型.然后再进行计算
当我们把精度(容量)大的数据类型赋值给精度(容量)小的数据类型时,就会报错,反之就会进行自动类型转换。
bytef short)和char之间不会相互自动转换。
bytef,short,char他们三者可以计算,在计算时首先转换为int类型c
boolean不参与转换
自动提升原则:表达式结果的类型自动提升为操作数中最大的类型
强制类型转换
介绍
自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换符 ( ),但可能造成精度降低或溢出,格外要注意
案例演示
int i = (int)1.9;
int j = 100;
byte b1 = (byte)j;
强制类型转换细节说明
当进行数据的大小从 大——>小,就需要使用到强制转换
强转符号只针对于最近的操作数有效,往往会使用小括号提升优先
int x = (int)10*3.5+6*1.5;
inty = (int)(10*3.5+6*13);
char类型可以保存int的常量值,但不能保存int的变量值,需要强转
c1 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
```int m = 100; ``` //ok
```char c2 = m;``` //错误
```char c3 = (char)m;``` //ok
```System.out.println(c3); ``` //100 对应的 5^5
4. byte和short, char类型在进行运算时,当做int类型处理
## 八、基本数据类型和String类型的转换
### 介绍
在程序开发中,我们经常需要将基本数据类型装换成String类型,或将String类型转成基本数据类型
### 基本类型转Sting类型的使用
#### 语法
将基本类型的值 + “” 即可
#### 案例
```java
int n1 = 100;
float n2 = 1.1f;
double n3 = 4.3;
boolean b1 = true;
String str1 = n1 + "";
String str2 = n2 + "";
String str3 = n4 + "";
String str4 = b1 + "";
String 类型转基本类型
语法
通过基本类型的包装类调用parseXX方法即可
案例
Integer.parseInt(“123”)
Double.parseDoubel(“1.2”)
Float.parseFloat(“2.4”)
Boolean.parseBoolean(“true”)
Byte.parseByte(“12”)
注意事项
在将String 类型转成 基本数据类型时,要确保String类型能够转成有效的数据 ,
比如 我们可以把 “123” , 转成一个整数,但是不能把 “hello” 转成一个整数
如果格式不正确,就会抛出异常,程序就会终止,(在异常处理章节中,会处理)
✅第三章 运算符
一、运算符介绍
运算符基本介绍
运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等。
- 算术运算符
- 赋值运算符
- 关系运算符 [比较运算符]
- 逻辑运算符
- 位运算符 [需要二进制基础]
- 三元运算符
算数运算符
基本介绍
算术运算符是对数值类型的变量进行运算的,在Java 程序中使用的非常多
算数运算符的使用范例
运算符 | 运算 | 范例 | 结果 |
---|---|---|---|
+ | 正号 | +7 | 7 |
- | 负号 | b=-11,-b | -11 |
+ | 加 | 1+3 | 4 |
- | 减 | 5-2 | 3 |
* | 乘 | 5*6 | 30 |
/ | 除 | 9/9 | 1 |
% | 取模(取余) | 11%9 | 2 |
++ | 自增(前),先运算,后取值 | a=2; b=++a; | a=3; b=3 |
++ | 自增(后),先取值,后运算 | a=2; b=a++; | a=3; b=2 |
– | 自减(前),先运算,后取值 | a=2; b=–a; | a=1; b=1 |
– | 自减(后),先取值,后运算 | a=2; b=a–; | a=1; b=2 |
+ | 字符串相加 | “gbl” + “gmm” | “gblgmm” |
细节说明
对于除号它的整数除和小数除是有区别的:
整数之间做除法时,只保留整 数部分而舍弃小数部分。例如:intx= 10/3结果是3
当对一个数取模时,可以等价a%b=a-a/b*b,这样我们可以看到取模的一 个本质运算。
当自增当做一个独立语言使用时,不管是++i;还是i++;都是一样的,等价
当自增当做一个表达式使用时j=++i 等价
当自增当做一个表达式使用时j = i++ 不等价
关系运算符
介绍
- 关系运算符的结果都是boolean 型,也就是要么是true,要么是false
- 关系表达式 经常用在 if 结构的条件中或循环结构的条件中
关系运算符的使用范例
运算符 | 运算 | 范例 | 结果 |
---|---|---|---|
== | 相等于 | 8 == 7 | false |
!= | 不等于 | 8 != 7 | true |
< | 小于 | 8 < 7 | false |
> | 大于 | 8 > 7 | true |
<= | 小于等于 | 8 <= 7 | false |
>= | 大于等于 | 8 >= 7 | true |
instanceof | 检查是否是类的对象 | “hsp” instanceof String | true |
细节说明
- 关系运算符的结果都是boolean 型,也就是要么是true,要么是false。
- 关系运算符组成的表达式,我们称为关系表达式。 a > b
- 比较运算符”==”不能误写成”=”
逻辑运算符
介绍
用于连接多个条件(多个关系表达式),最终的结果也是一个boolean 值。
逻辑运算符一览
- 短路与 && , 短路或 ||,取反 !
- 逻辑与 &,逻辑或 |, 逻辑异或^
逻辑运算规则说明
- a&b : & 叫逻辑与:规则:当a 和 b 同时为true ,则结果为true, 否则为false
- a&&b : && 叫短路与:规则:当a 和 b 同时为true ,则结果为true,否则为false
- a|b : | 叫逻辑或,规则:当a 和 b ,有一个为true ,则结果为true,否则为false
- a||b : || 叫短路或,规则:当a 和 b ,有一个为true ,则结果为true,否则为false
- !a : 叫取反,或者非运算。当a 为true, 则结果为false, 当 a 为false 是,结果为true
- a^b: 叫逻辑异或,当 a 和 b 不同时,则结果为true, 否则为false
逻辑与& 和 短路与&& 基本规则
名称 | 语法 | 特点 |
---|---|---|
短路与&& | 条件1&&条件2 | 两个条件都为true,结果为true,否则false |
逻辑与& | 条件1&条件2 | 两个条件都为true,结果为true,否则false |
逻辑与& 和 短路与&&使用区别
- &&短路与:如果第一个条件为false,则第二个条件不会判断,最终结果为false,效率高
- & 逻辑与:不管第一个条件是否为false,第二个条件都要判断,效率低
- 开发中, 我们使用的基本是使用短路与&&, 效率高
逻辑或| 和 短路或|| 基本规则
名称 | 语法 | 特点 |
---|---|---|
短路或|| | 条件1 || 条件2 | 两个条件中只要有一个成立,结果为true,否则为false |
逻辑或| | 条件1 | 条件2 | 只要有一个条件成立,结果为true,否则为false |
逻辑或| 和 短路或|| 使用区别
- ||短路或:如果第一个条件为true,则第二个条件不会判断,最终结果为true,效率高
- | 逻辑或:不管第一个条件是否为true,第二个条件都要判断,效率低
- 开发中,我们基本使用 ||
取反!基本规则
名称 | 语法 | 特点 |
---|---|---|
!取反(非) | !条件 | 如果条件本身成立,结果为false,否则为true |
逻辑异或^ 案例演示
a^b: 叫逻辑异或,当 a 和 b 不同时,则结果为true, 否则为false
赋值运算符
介绍
赋值运算符就是将某个运算后的值,赋给指定的变量
赋值运算符的分类
基本赋值运算符 =
复合赋值运算符
+= ,-= ,*= , /= ,%=
例子
a += b; ===> a = a + b;
赋值运算符的特点
- 运算顺序从右往左 int num = a + b + c;
- 赋值运算符的左边 只能是变量,右边 可以是变量、表达式、常量值
int num = 20; int num2= 78 * 34 - 10; int num3 = a; - 复合赋值运算符等价于下面的效果
比如:a+=3;等价于a=a+3; 其他类推 - 复合赋值运算符会进行类型转换。
byte b = 2; b+=3; b++;
三元运算符
基本语法
条件表达式 ? 表达式1: 表达式2;
运算规则
如果条件表达式为true,运算后的结果是表达式1;
如果条件表达式为false,运算后的结果是表达式2;
口决 :一真大师
使用细节
- 表达式1 和表达式2 要为可以赋给接收变量的类型(或可以自动转换)
- 三元运算符可以转成if–else 语句
二、运算符的优先级
基本介绍
- 运算符有不同的优先级,所谓优先级就是表达式运算中的运算顺序。如右表,上一行运算符总优先于下一行。
- 只有单目运算符、赋值运算符是从右向左运算的。
常见的运算符优先级
三、标识符的命名规则和规范
标识符概念
- Java对各种变量.方法和类等命名时使用的字符序列称为标识符
- 凡是自己可以起名字的地方都叫标识符
int num1 = 90;
标识符的命名规则(必须遵守)
由26个英文字母大小写,0-9,__或$组成
数字不可以开头。
int 3ab = 1;
错误不可以使用关键字和保留字,但能包含关键字和保留字。
Java中严格区分大小写,长度无限制。
int totalNum = 10; int n = 90;
标识符不能包含空格。
a b 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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
### 标识符命名规范
1. 包名:多单词组成时所有字母都小写:aaa.bbb.ccc //比如 com.hsp.crm
2. 类名、接口名:多单词组成时,所有单词的首字母大写:XxxYyyZzz [大驼峰]
比如: TankShotGame
3. 变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:xxxYyyZzz [小驼峰,简称 驼峰法] 比如: tankShotGame
4. 常量名:所有字母都大写。多单词时每个单词用下划线连接:XXX_YYY_ZZZ
比如 :定义一个所得税率 TAX_RATE
5. 后面我们学习到 类,包,接口,等时,我们的命名规范要这样遵守,更加详细的看文档.
## 四、关键字
### 关键字的定义和特点
#### 定义
被Java 语言赋予了特殊含义,用做**专门用途的字符串**(单词)
#### 特点
关键字中所有字母都为小写
### 常见的关键字


## 五、保留字
### 介绍
java 保留字:现有Java 版本尚未使用,但以后版本可能会作为关键字使用。自己命名标识符时要避免使用这些保留字**byValue、cast、future、 generic、 inner、 operator、 outer、 rest、 var 、 goto 、cons**
### 键盘输入语句
#### 基本介绍
在编程中,需要接收用户输入的数据,就可以使用键盘输入语句来获取。Input.java , 需要一个 扫描器(对象), 就是 **Scanner**
#### 使用步骤
1. 导入该类的所在包,
```import java.util.Scanner;```
2. 创建该类对象(声明变量)
```Scanner myScanner = new Scanner(System.in);```
3. 调用里面的功能
```String name = myScanner.nextInt();```
## 六、进制的转换
### 进制介绍
对于整数,有四种表示方式:
1. 二进制:0,1 ,满2 进1,以0b 或0B 开头。
2. 十进制:0-9 ,满10 进1。
3. 八进制:0-7 ,满8 进1,以数字0 开头表示。
4. 十六进制:0-9 及A(10)-F(15),满16 进1. 以**0x** 或**0X** 开头表示。此处的A-F 不区分大小写。
### 二进制转十进制
#### 规则
从最低位(右边)开始,将每个位上的数提取出来,乘以2 的(位数-1)次方,然后求和。
### 八进制转十进制
#### 规则
从最低位(右边)开始,将每个位上的数提取出来,乘以8 的(位数-1)次方,然后求和。
### 十六进制转十进制
#### 规则
从最低位(右边)开始,将每个位上的数提取出来,乘以16 的(位数-1)次方,然后求和。
#### 案例
案例:请将 0x23A 转成十进制的数
**0x23A = 10 * 16^0 + 3 * 16 ^ 1 + 2 * 16^2 = 10 + 48 + 512 = 570**
### 十进制转换二进制
#### 规则
将该数不断除以2,直到商为0 为止,然后将每步得到的余数倒过来,就是对应的二进制。
### 十进制转八进制
#### 规则
规则:将该数不断除以8,直到商为0 为止,然后将每步得到的余数倒过来,就是对应的八进制。
### 十进制转十六进制
#### 规则
将该数不断除以16,直到商为0 为止,然后将每步得到的余数倒过来,就是对应的十六进制。
### 二进制转八进制
#### 规则
从低位开始,将二进制数每三位一组,转成对应的八进制数即可。
#### 案例
请将 ob11010101 转成八进制
ob11(3)010(2)101(5) => 0325
### 二进制转十六进制
#### 规则
从低位开始,将二进制数每四位一组,转成对应的十六进制数即可。
#### 案例
请将 ob11010101 转成十六进制
ob1101(D)0101(5) = 0xD5
### 八进制转二进制
#### 规则
将八进制数每1 位,转成对应的一个3 位的二进制数即可。
#### 案例
请将 0237 转成二进制
02(010)3(011)7(111) = 0b10011111
### 十六进制转二进制
#### 规则
将十六进制数每1 位,转成对应的4 位的一个二进制数即可。
#### 案例
请将 0x23B 转成二进制
0x2(0010)3(0011)B(1011) = 0b001000111011
## 七、源码、补码、反码
### 总结
1. 二进制的最高位是符号位:0表示正数」表示负数(老韩口诀:0->0 1-> -)
2. 正数的原码,反码,补码都一样(三码合一)
3. 负数的反码=它的原码符号位不变,其它位取反(0->1,1->0)
4. 负数的补码=它的反码+1,负数的反码=负数的补码-1
5. 0的反码,补码都是0
6. java没旨无符号数,换言之,java中的数都是有符号的
7. 在计算机运算的时候,都是以补码的方式来运算的.
8. 当我们看运算结果的时候,要看他的原码(重点)
## 八、位运算符
### 基本介绍
java 中有7 个位运算(**&、|、^、~、>>、<<和 >>>**)
#### 位运算
位运算分别是 **按位&、按位|、按位异或^、按位取反~**、它们的运算规则是:
1. 按位&:两位全为1,结果为1,否则为0
2. 按位|: 两位有一个为1.结果为1,否则为0
3. 按位异或^: 两位一个为0,,一个为1,结果为1,否则为0
4. 按位取反~:0->1 ,1->0
#### 位运算符
还有三个位运算符 **>>、<<** 和 **>>>** ,运算规则:
1. 算术右移 >>:低位溢出,符号位不变,并用符号位补溢出的高位
2. 算术左移 <<: 符号位不变,低位补0
3. \>>> 逻辑右移也叫无符号右移,运算规则是: 低位溢出,高位补 0
4. 特别说明:没有 <<< 符号
# ⭐第四章 程序控制结构
## 一、程序流程控制介绍
在程序中,程序运行的流程控制决定程序是如何执行的,是我们必须掌握的,主要有三大流程控制语句
1. 顺序控制
2. 分支控制
3. 循环控制
### 顺序控制
#### 基本介绍
程序从上到下逐行进行,中间没有任何判断和跳转
## 二、分支控制 if-else
### 分支控制 if-else介绍
让程序有选择的的执行,分支控制有三种
1. 单分支 if
2. 双分支 if-else
3. 多分支 if-else if -....-else
### 单分支
#### 基本语法
```java
if(条件表达式) {
执行代码块;(可以有多条语句)
}
说明:
当条件表达式为true时,就会执行{ } 的代码,如果为false就不执行,
特别说明:
如果 { } 中只有一条语句,则可以不用{ }
双分支(If02)
基本语法
1 | if(条件表达式) { |
说明:
当条件表达式成立时,即执行 代码块1,否则,执行代码块2
单分支和双分支练习题(IfExercise01)
- 编写程序,声明2 个double 型变量并赋值。判断第一个数大于10.0,且第2 个数小于20.0,打印两数之和
- 定义两个变量int,判断二者的和,是否能被3 又能被5 整除,打印提示信息
- 判断一个年份是否是闰年,闰年的条件是符合下面二者之一:(1)年份能被4 整除,但不能被100 整除;(2)能被400整除
多分支
基本语法
1 | if(条件表达式1) { |
特别说明
- 多分支可以没有else,如果所有的条件表达式都不成立,则一个执行入口都没有
- 如果有else,如果所有的条件表达式都不成立,则默认执行else代码块
多分支流程图
说明:
- 当条件表达式1成立时.即执行代码块1
- 如果表达式1不成立,才去判断表达式2是否成立.
- 如果表达式2成立,就执行代码块 2
- 以此类推,如果所有的表达式都 不成立
- 则执行else的代码块,注意,只能有一个执行入口。
多分支案例演示(If03)
输入保国同志的芝麻信用分:
如果:
- 信用分为100 分时,输出 信用极好
- 信用分为(80,99]时,输出 信用优秀;
- 信用分为[60,80]时,输出 信用一般;
- 其它情况 ,输出 信用 不及格
- 请从键盘输入保国的芝麻信用分,并加以判断
嵌套分支
基本介绍
在一个分支结构中又完整的嵌套了另一个完整的分支结构,里面的分支的结构称为内层分支外面的分支结构称为外层分支。建议: 不要超过3 层 (代码的可读性差)
基本语法
1 | if() { |
应用案例(NestedIf)
加歌手比赛,如果初赛成绩大于8.0 进入决赛,否则提示淘汰。并且根据性别提示进入男子组或女子组。
输入成绩和性别,进行判断和输出信息。[NestedIf.java]
提示:接收字符:
char gender = scanner.next().charAt(0);
简单的出票系统
三、switch分支结构和循环控制(for、while、do..while)
switch分支结构
基本语法
1 | switch(表达式) { |
流程图
快速入门(Switch01)
请编写一个程序,该程序可以接收一个字符,比如:a,b,c,d,e,f,g
a 表示星期一,b 表示星期二 …
根据用户的输入显示相应的信息.要求使用 switch 语句完成
switch注意事项和细节(SwitchDetail)
1.
switch 课堂练习(SwitchExercise)
- 使用 switch 把小写类型的 char 型转为大写(键盘输入)。只转换 a, b, c, d, e. 其它的输出 “other”。
- 对学生成绩大于60 分的,输出”合格”。低于60 分的,输出”不合格”。(注:输入的成绩不能大于100), 提示 成绩/60
- 根据用于指定月份,打印该月份所属的季节。3,4,5 春季 6,7,8 夏季 9,10,11 秋季 12, 1, 2 冬季 [课堂练习, 提示使用穿透 ]
switch 和if 的比较
- 如果判断的具体数值不多,而且符合byte、 short 、int、 char、enum[枚举], String 这6 种类型。虽然两个语句都可以使用,建议使用swtich 语句。
- 其他情况:对区间判断,对结果为boolean 类型判断,使用if,if 的使用范围更广
for循环控制
基本介绍
听其名而知其意,就是让代码可以循环的执行
基本语法
1 | for(循环变量初始化;循环条件;循环变量迭代) { |
说明
- for 关键字,表示循环控制
- for 有四要素: (1)循环变量初始化(2)循环条件(3)循环操作(4)循环变量迭代
- 循环操作 , 这里可以有多条语句,也就是我们要循环执行的代码
- 如果循环操作(语句) 只有一条语句,可以省略 {}, 建议不要省略
for 循环执行流程分析
for循环的注意事项和细节说明(ForDetai)
- 循环条件是返回一个布尔值的表达式
- for(;循环判断条件;) 中的初始化和变量迭代可以写到其它地方,但是两边的分号不能省略。
- 循环初始值可以有多条初始化语句,但要求类型一样,并且中间用逗号隔开,循环变量迭代也可以有多条变量迭代语句,中间用逗号隔开。
for循环练习
打印1~100 之间所有是9 的倍数的整数,统计个数及总和((ForExercise))
完成下面的表达式输出(ForExercise02)
0+5=5
1+4=5
2+3=5
3+2=5
4+1=5
5+0=5
while 循环控制
基本语法
1 | while(循环条件) { |
说明
- while循环也有四要素
- 只是四要素放的位置和for不同
while 循环执行流程分析
while 循环注意事项和细节说明
- 循环条件是返回一个布尔值的表达式
- while 循环是先判断再执行语句
while循环练习题(WhileExercise)
- 打印1—100 之间所有能被3 整除的数 [使用while ]
- 打印40—200 之间所有的偶数 [使用while]
do..while循环控制
基本语法
1 | 循环变量初始化; |
说明
- do while 是关键字,也有循环四要素, 只是位置不一样
- 先执行,再判断,也就是说,一定会至少执行一次
- 最后有一个分号 ;
- while 和 do..while 区别举例: 要账
do..while循环控制流程分析(DoWhile01)
do..while循环注意事项和细节说明
- 循环条件是返回一个布尔值的表达式
- do..while 循环是先执行,再判断, 因此它至少执行一次
do..while循环练习题((DoWhileExercise01)
- 打印1—100
- 计算1—100 的和
- 统计1—200 之间能被5 整除但不能被3 整除的个数
- 如果李三不还钱,则老韩将一直使出五连鞭,直到李三说还钱为止
[System.out.println(“老韩问:还钱吗?y/n”)] do…while . (DoWhileExercise02)
四、多重循环控制(重难点)
介绍
- 将一个循环放在另一个循环体内,就形成了嵌套循环。其中,for ,while ,do…while 均可以作为外层循环和内层循环。【建议一般使用两层,最多不要超过3 层, 否则,代码的可读性很差】
- 实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为false 时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次的循环
- 设外层循环次数为m 次,内层为n 次,则内层循环体实际上需要执行m*n 次。
多重循环执行步骤分析:
多重循环控制应用实例(MulForExercise01)
统计3 个班成绩情况,每个班有5 名同学,
求出各个班的平均分和所有班级的平均分[学生的成绩从键盘输入]
统计三个班及格人数,每个班有5 名同学
打印九九乘法表
金字塔模型
使用for循环完成:(Stars.java)
请编写一个程序,可以接收一个整数,表示层数(totalLevel),打印出金字塔。
*
* *
* *
*********************
五、跳转控制语句
跳转控制语句-break(break01)
基本介绍
break 语句用于终止某个语句块的执行,一般使用在switch 或者循环**[for , while , do-while]**中
使用需求
当循环的次数不知道时(让循环条件一直为true),就可以使用break语句,当某个条件满足时,终止循环
基本语法
1 | while(true) { |
break练习题(BreakExercise)
- 1-100 以内的数求和,求出 当和 第一次大于20 的当前数 【for + break】 (BreakExercise01)
- 现登录验证,有3 次机会,如果用户名为”丁真” ,密码”666”提示登录成功,否则提示还有几次机会,请使用for+break (BreakExercise02)
跳转控制语句-continue(Continue01)
基本介绍
- continue 语句用于结束本次循环,继续执行下一次循环
- continue 语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环 , 这个和前面的标签的使用的规则一样
基本语法
1 | while(循环条件) { |
跳转控制语句-return
基本介绍
- return 使用在方法,表示跳出所在的方法
- 如果 return 写在 main 方法,将退出程序
本章作业
某人有 1 00 , 000 元,每经过一次路口,需要交费,规则如下:
1 )当现金> 50000 时,每次交 5 %
2 )当现金< = 50000 时,每次交 1 000 编程计算该人可以经过多少次路口,
要求:使用 while + break 方式完成实现判断一个整数,属于哪个范围:大于 0 :小于 0 ;等于。 Homework02java
思路:定义 int n = 22 ;使用 if 一 else if 一 else 即可判断一个年份是否为闰年 Homework03java 思路:
判断一个整数是否是水仙花数,所谓水仙花数是指一个 3 位数,其各个位上数字立方和等于其本身。
例如: 153 = 1 * 1 * 1 + 3 * 3 * 3 + 5 * 5 * 5 Homework04.java看看下面代码输出什么
1 | class Demo{ |
输出1-100之间的不能被5整除的数, 每5个一行 Homework 06.java
输出小写的a-z以及大写的Z-A Homework 07.java
求出1-1/2+1/3-1/4…..1/100的和 Homework 08.java
求1+(1+2)+(1+2+3)+(1+2+3+4)+…+(1+2+3+..+100)的结果 Homework 09.java
⭐第五章 数组、排序、查找
一、数组的基本使用
数组介绍
数组可以存放多个同一类型的数据。数组也是一种数据类型,是引用类型。
即:数(数据)组(一组)就是一组数据
数组的使用
使用方式1-动态初始化
数组的定义
数组类型 数组名[] = new 数组类型[大小];
int a[] = new int[3];
解读
创建了一个数组,名字为a,存放了3个int型的数据
数组的引用(使用/访问/获取数组元素)
数组名[下标/索引/index]
比如:你要使用数组a 的第三个数 a[2]
注意:数组的下标从0开始
快速入门( Array02)
使用方式2-动态初始化
先声明数组
语法: 数组类型 数组名[]; 或 数据类型[] 数组名;
创建数组
语法:数组名 = new 数组类型[大小]
a = new int[2];
使用方式3-静态初始化
语法
数组类型 数组名 = {元素值,元素值,…}
例如:int a[] = {3,4,6,7};
如果知道数组有多少元素和具体值,就可以用上面的方法创建数组
数组的注意事项和使用细节(ArrayDetai)
数组是多个相同类型数据的组合,实现对这些数据的统一管理
数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用。
数组创建后,如果没有赋值,有默认值
int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \u0000,boolean false,String null使用数组的步骤 1. 声明数组并开辟空间 2 给数组各个元素赋值 3 使用数组
数组的下标是从0 开始的。
数组下标必须在指定范围内使用,否则报:下标越界异常,比如
int [] arr=new int[5]
,则有效下标是0-4
数组属引用类型,数组型数据是对象(object)
数组的应用案例
- 创建一个char 类型的26 个元素的数组,分别 放置’A’-‘Z’。使用for 循环访问所有元素并打印出来。提示:char 类型数据运算 ‘A’+2 -> ‘C’ ArrayExercise01.java
- 请求出一个数组int[]的最大值 {4,-1,9, 10,23},并得到对应的下标。 ArrayExercise02.java
数组的赋值机制
基本数据类型赋值,这个值就是具体的数据,而且相互不影响。
int n1 = 2; int n2 = n1;
数组在默认情况下是引用传递,赋的值是地址。
看一个案例,并分析数组赋值的内存图(重点, 难点. )。ArrayAssign.javaint[] arr1 = {1,2,3};
int[] arr2 = arr1;
数组赋值的流程图
数组拷贝 (ArrayCopy)
需求
编写代码 实现数组拷贝(内容复制) ArrayCopy.java
将 int[] arr1 = {10,20,30}; 拷贝到 arr2 数组, 要求数据空间是独立的.
1 | public class ArrayCopy { |
数组反转( ArrayReverse)
需求
把数组的元素内容反转。 ArrayReverse.java
arr {11,22,33,44,55,66} {66, 55,44,33,22,11}
方式一:通过找规律反转
1 | ublic class ArrayReverse { |
方式二:使用逆序赋值方式 ( ArrayReverse02)
1 | public class ArrayReverse02 { |
数组添加/扩容(ArrayAdd)
需求
- 实现动态的给数组添加元素效果,实现对数组扩容。ArrayAdd.java
1 | import java.util.Scanner; |
需求二:
- 原始数组使用静态分配 int[] arr = {1,2,3}
- 增加的元素4,直接放在数组的最后 arr = {1,2,3,4}
- 用户可以通过如下方法来决定是否继续添加,添加成功,是否继续?y/n
1 | public class ArrayAdd02 { |
练习题 (ArrayReduce)
有一个数组 {1, 2, 3, 4, 5}, 可以将该数组进行缩减,提示用户是否继续缩减,每次缩减最后那个元素。当只剩下最后一个元素,提示,不能再缩减。
1 | import java.util.Scanner; |
二、数组的排序
排序的介绍
排序是将多个数据,依指定的顺序进行排列的过程
排序的分类
内部排序
将需要处理的所有数据都加载到内部存储器中进行排序。包括(交换式排序法、选择
式排序法和插入式排序法);
外部排序
数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。包括(合并排序法和直接合并排序法)。
冒泡排序法
冒泡排序(Bubble Sorting)的基本思想是:通过对待排序序列从后向前(从下标较大的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就象水底下的气泡一样逐渐向上冒。
案例
我们将五个无序:24,69,80,57,13 使用冒泡排序法将其排成一个从小到大的有序数列
1 | public class BubbleSort02 { |
三、数组的查找
介绍
在java 中,我们常用的查找有两种:
- 顺序查找、
- 二分法查找
顺序查找(SeqSearch)
案例演示
有一个数列:白眉鹰王、金毛狮王、紫衫龙王、青翼蝠王猜数游戏:从键盘中任意输入一个名称,判断数列中是否包含此名称【顺序查找】 要求: 如果找到了,就提示找到,并给出下标值。
1 | import java.util.Scanner; |
四、二维数组
二维数组的应用场景
用二维数组来表示棋盘
二维数组的基本使用(TwoDimensionalArray01 )
用二维数组输出图形
1 | public class TwoDimensionalArray01 { |
什么是二维数组
- 从定义上看:int[ ] [ ]
- 原来的一维数组的每个元素是一维数组, 就构成二维数组
二维数组的理解
- 二维数组的元素个数= arr.length
- 二维数组的每个元素是一维数组, 所以如果需要得到每个一维数组的值
还需要再次遍历 - 如果我们要访问第 (i+1)个一维数组的第 j+1 个值 是arr[i][j];
- arr[i] 表示 二维数组的第 i+1 个元素 比如 arr[0]:二维数组的第一个元素
- arr[i].length 得到 对应的 每个一维数组的长度
使用方式1:动态初始化
基本语法
语法: 类型[][] 数组名=new 类型[大小][大小]
例如: int a[][]=new int[2][3];
二维数组在内存中的型式(TwoDimensionalArray02_)
1 | public class TwoDimensionalArray02 { |
使用方式 2: 动态初始化
- 先声明:类型 数组名[][];
- 再定义(开辟空间)
数组名 = new 类型[大小][大小]
赋值(有默认值,比如 int 类型的就是 0)
使用方式 3: 动态初始化-列数不确定(TwoDimensionalArray02)
需求
创建下面的二维数组,并输出
i/j | j=0 | j=1 | j=2 |
---|---|---|---|
i=0 | 1 | ||
i=1 | 2 | 2 | |
i=2 | 3 | 3 | 3 |
1 | public class TwoDimensionalArray02 { |
使用方式4:静态初始化
基本语法
类型 数组名[][] = {{值 1,值 2..},{值 1,值 2..},{值 1,值 2..}} ;
例如:int[][] arr = {{1,1,1}, {8,8,9}, {100}};
解读
- 定义了一个二维数组 arr
- arr 有三个元素(每个元素都是一维数组)
- 第一个一维数组有 3 个元素 , 第二个一维数组有 3 个元素, 第三个一维数组有 1 个元素
案例
1 |
|
二维数组的应用
杨辉三角(YangHui)
使用二维数组打印一个 10 行杨辉三角
1 | public class YangHui { |
二维数组的使用细节和注意事项
一维数组的声明方式有:
int[] x 或者 int x[]二维数组的声明方式有:
int[][] y 或者 int[] y[] 或者 int y[ ] [ ]二维数组实际上是由多个一维数组组成的,它的各个一维数组的长度可以相同,也可以不相同。
比如: map[][] 是一个二维数组
int map [][] = {{1,2},{3,4,5}}
由 map[0] 是一个含有两个元素的一维数组 ,map[1] 是一个含有三个元素的一维数组构成,我们也称为列数不等的二维数组
本章作业
已知有个升序的数组,要求插入一个元素,该数组顺序依然是升序,比如:
[10, 12,45, 90],添加23后,数组为[10,12,23,45,90] Homework04.java
思路:- 定义一个新数组,遍历原数组时将,在添加到这个新的数组,并将原数组的地址指向新的数组
- 插入完成后,再用冒泡排序完成从小到大的排序
随机生成10个整数(1-100的范围)保存到数组,并倒序打印以及求平均值、
求最大值和最大值的下标、并查找里面是否有8 Homework05.java生成随机数用 Math.random()方法,注意生成的是(0,1)之间的小数, 不包括0和100,
因此生成1-100的整数要 强制转换,并且+1
⭐第六章 面向对象编程(基础)
一、类与对象
类和对象的区别和联系
- 类是抽象的,概念的,代表一类事物,比如人类,猫类.., 即它是数据类型
- 对象是具体的,实际的,代表一个具体事物, 即 是实例
- 类是对象的模板,对象是类的一个个体,对应一个实例
对象在内存中存在形式(重要的)
属性/成员变量/字段
- 从概念或叫法上看: 成员变量 = 属性 = field(字段) (即 成员变量是用来表示属性的)
- 属性是类的一个组成部分,一般是基本数据类型,也可是引用类型(对象,数组)。比如我们前面定义猫类 的 int age 就是属性
1 | public class Object02 { |
注意事项和使用说明(PropertiesDetail)
属性的定义语法同变量,示例:访问修饰符 属性类型 属性名;
这里老师简单的介绍访问修饰符: 控制属性的访问范围有四种访问修饰符 public, proctected, 默认, private
属性的定义类型可以为任意类型,包含基本类型或引用类型
属性如果不赋值,有默认值,规则和数组一致。具体说: int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \u0000,boolean false,String null
1 | public class PropertiesDetail { |
如何创建对象
声明再创建
Cat cat
; //声明对象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
2. 直接创建
```Cat cat = new Cat();```
### 如何访问属性
#### 基本语法
对象名.属性名
```cat.name;```
```cat.age;```
```cat.color```
### 类和对象的内存分配机制(重要)

### 类和对象的内存分配机制
#### Java 内存的结构分析
1. 栈: 一般存放基本数据类型(局部变量)
2. 堆: 存放对象(Cat cat , 数组等)
3. 方法区:常量池(常量,比如字符串), 类加载信息
#### Java 创建对象的流程简单分析
```java
Person p = new Person();
p.name = “jack”;
p.age = 10;先加载Person 类信息(属性和方法信息, 只会加载一次)
在堆中分配空间, 进行默认初始化(看规则)
把地址赋给 p , p 就指向对象
进行指定初始化, 比如 p.name =”jack” p.age = 10
二、成员方法
基本介绍
在某些情况下,我们要需要定义成员方法(简称方法)。比如人类:除了有一些属性外( 年龄,姓名..),我们人类还有一些行为比如:可以说话、跑步..,通过学习,还可以做算术题。这时就要用成员方法才能完成。现在要求对Person 类完善
成员方法入门
- 添加speak 成员方法,输出 “我是一个好人”
- 添加cal01 成员方法,可以计算从 1+..+1000 的结果
- 添加cal02 成员方法,该方法可以接收一个数n,计算从 1+..+n 的结果
- 添加getSum 成员方法,可以计算两个数的和
1 | public class Method01 { |
- 添加cal01 成员方法,可以计算从 1+..+1000 的结果
- public 表示方法是公开的
- int :表示方法执行后,返回一个 int 值
- getSum 方法名
- int num1, int num2) 形参列表,2 个形参,可以接收用户传入的两个数
- return res; 表示把 res 的值, 返回
1 | public void cal01() { |
- 添加getSum 成员方法,可以计算两个数的和
1 | public int getSum(int num1, int num2) { |
方法调用的机制
getSum方法程序执行的过程
为什么需要成员方法
成员方法的好处
- 提高代码的复用性
- 可以将实现的细节封装起来,然后供其他用户来调用即可
成员方法的定义
1 | 访问修饰符 返回数据类型 方法名(形参列表..) { //方法体 |
- 形参列表:表示成员方法输入 cal(int n) , getSum(int num1, int num2)
- 返回数据类型:表示成员方法输出, void 表示没有返回值
- 方法主体:表示为了实现某一功能代码块
- return 语句不是必须的
成员方法的注意事项以及使用细节(MethodDetail)
1 | public class MethodDetail { |
注意事项
访问修饰符
作用是控制方法的使用范围
如果不写默认访问,[有四种: public, protected, 默认, private]
返回数据类型
- 一个方法最多有一个返回值 (如何返回多个结果 返回数组)
- 返回类型可以为任意类型,包含基本类型或引用类型(数组,对象)
- 如果方法要求有返回数据类型,则方法体中最后的执行语句必须为 return 值; 而且要求返回值类型必须和return 的值类型一致或兼容
- 如果方法是void,则方法体中可以没有return 语句,或者 只写 return
方法名
遵循驼峰命名法,最好见名知义,表达出该功能的意思即可, 比如 得到两个数的和 getSum, 开发中按照规范
形参列表
一个方法可以有0个参数,也可以有多个参数,比如 get Sum(int n 1,int n2)
参数类型可以为任意类型,包含基本类型或引用类型,比如 print Arr(int[] [] map)
调用带参数的方法时,一定对应着参数列表传入相同类型或兼容类型的参数!
方法定义时的参数称为形式参数,简称形参;方法调用时的传入参数称为实际参数,简称实参
实参和形参的类型要一致或兼容、个数、顺序必须一致!
方法体
里面写完成功能的具体的语句,可以为输入、输出、变量、运算、分支、循环、方法调用,但里
面不能再定义方法! 即:方法不能嵌套定义
使用细节
调用带参数的方法时,一定对应着参数列表传入相同类型或兼容类型 的参数
1
2
3
4byte b1 = 1;
byte b2 = 2;
a.getSumAndSub(b1, b2);//byte -> int
//a.getSumAndSub(1.1, 1.8);//double ->int(×)实参和形参的类型要一致或兼容、个数、顺序必须一致
方法调用细节说明
- 同一个类中的方法调用:直接调用即可,例如:A类say Ok调用print()
- 跨类中的方法A 类调用B 类方法:需要通过对象名调用,例如:B类say Hello调用print()
- 跨类的方法调用和方法的访问修饰符相关
1 | public class MethodDetail02 { |
成员方法练习题(MethodExercise01)
- 编写类AA ,有一个方法:判断一个数是奇数odd 还是偶数, 返回boolean
- 根据行、列、字符打印 对应行数和列数的字符,比如:行:4,列:4,字符#,则打印相应的效果
1 | public class MethodExercise01 { |
三、成员方法的传参机制
基本数据类型的传参机制
引用数据类型的传参机制
四、方法的递归调用
老鼠出迷宫的问题
思路
- 先创建迷宫,用二维数组表示
int[][] map = new int[8][7];
- 先规定 map 数组的元素值: 0 表示可以走 1 表示障碍物
- 将最上面的一行和最下面的一行,全部设置为1
- 4.将最右面的一列和最左面的一列,全部设置为1
1 | public class MiGong { |
五、方法重载(OverLoad)
方法重载的基本使用
1 | public class OverLoad01 { |
重载的注意事项和使用细节
- 方法名必须相同
- 参数列表:必须不同(参数类型或个数或顺序,至少有一样不同,参数名无要求)
- 返回类型:无要求
实例
没有构成方法重载, 仍然是错误的,因为是方法的重复定义
1 | public void calculate(int n1, int n2) { |
方法的重复定义(只是变量名改变,而参数的类型、个数、顺序没有改变)
1 | public int calculate(int a1, int a2) { |
方法重载的练习题 OverLoadExercise
编写程序,类Methods 中定义三个重载方法并调用。方法名为m。
三个方法分别接收一个int 参数、两个int 参数、一个字符串参数。分别执行平方运算并输出结果,
相乘并输出结果,输出字符串信息。在主类的main ()方法中分别用参数区别调用三个方法定义三个重载方法max(),第一个方法,返回两个int 值中的最大值,
第二个方法,返回两个double 值中的最大值,第三个方法 ,返回三个double 值中的最大值,并分别调用三个方法
1 | public class OverLoadExercise { |
六、可变参数
1.基本概念
java 允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法。就可以通过可变参数实现
2.基本语法
访问修饰符 返回类型 方法名(数据类型… 形参名)
1 | public int tools( int...sums){ |
解读:
- int… 表示接受的是可变参数,类型是int ,即可以接收多个int(0-多)
- 使用可变参数时,可以当做数组来使用 即 nums 可以当做数组
- 处理多个数据遍历,然后运算即可
3.注意事项和使用细节(VarParameterDetail)
- 可变参数的实参可以视为数组
- 可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
- 一个形参列表中只能出现一个可变参数
1 | public class VarParameterDetail { |
一个形参列表中只能出现一个可变参数
错误的写法
1 | public void f3(int... nums1, double... nums2) { |
练习题: VarParameterExercise
有三个方法,分别实现返回姓名和两门课成绩(总分),
返回姓名和三门课成绩(总分),返回姓名和五门课成绩(总分)。
封装成一个可变参数的方法
1 | public class VarParameterExercise { |
七、作用域
作用域的基本使用(VarScope)
1.在java编程中,主要的变量就是属性(全局变量)和局部变量
n 和 name 就是局部变量
n 和 name 的作用域在 cry 方法中2**.局部变量**一般是指在成员方法中定义的变量
1 | public void cry() { |
3.java中作用域的分类
全局变量(也就是属性):作用域为整个 类体
局部变量:也就是出属性之外的变量,作用域为定义它的代码块中!
4.全局变量(属性)可以不赋值,直接使用,因为有默认值
局部变量必须赋值后,才能使用,因为没有默认值
1
2
3
4
5
6
7class Cat {
int age = 10;
double weight; //默认值是0.0
public void cry() {
int age = 10; //局部变量必须赋值(初始化)后才能使用
}
}
1 | public class VarScope { |
作用域的注意事项和使用细节 (VarScopeDetail)
- 属性(全局变量)和局部变量可以重名,访问时遵循就近原则。
- 在同一个作用域中,比如在同一个成员方法中,两个局部变量不能重名
- 属性生命周期较长,伴随着对象的创建而创建,伴随着对象的销毁而销毁。
局部变量,生命周期较短,伴随着它的代码块的执行而创建,
伴随着代码块的结束而销毁。即在一次方法调用过程中
1 | public class VarScopeDetail { |
八、构造方法/构造器
构造器的用途:
创建人类的对象时,是先把一个对象创建好后,再给他的年龄和姓名属性赋值,如
果现在我要求,在创建人类的对象时,就直接指定这个对象的年龄和姓名,该怎么做?
基本语法
1 | [修饰符] 方法名 (形参列表){ |
说明
- 构造器的修饰符可以默认, 也可以是public protected private
- 构造器没有没有返回值
- 方法名和类名必须一样
- 参数列表和成员方法使用规则一致
- 构造器的调用,由系统完成
基本介绍
- 方法名和类名必须相同
- 没有返回值,不能写void
- 在创建对象时,系统会自动的调用该类的构造器完成对象的初始化
快速入门(Constructor01)
1 | public class Constructor01 { |
注意事项和使用细节(ConstructorDetai)
- 一个类可以定义多个不同的构造器,即构造器重载
- 构造器名和类名必须相同
- 构造器没有返回值
- 构造器是完成对象的初始化,并不是创建对象
- 在创建对象时,系统自动调用该类的构造方法
- 如果没有如果没有定义构造器,系统会自动给类生成一个**默认无参构造器(**也叫默认构造器)
- 一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器
1 | public class ConstructorDetail { |
解读
- 如果没有如果没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造器)
1 | Dog() { |
一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器,
如果想要使用无参构造器,需要显示定义,
Dog() {}
构造器练习(ConstructorExercise)
在前面定义的Person 类中添加两个构造器:
第一个无参构造器:利用构造器设置所有人的age 属性初始值都为18
第二个带pName 和pAge 两个参数的构造器:
使得每次创建Person 对象的同时初始化对象的age 属性值和name 属性值。
分别使用不同的构造器,创建对象.
1 | public class ConstructorExercise { |
九、对象创建流程分析
案例
1 | public class test1 { |
流程分析
- 加载Person类信息(Person.class),只会加载一次
- 在堆中分配空间(地址)
- 完成对象初始化
- 默认初始化 age = 0 name = null
- 显示初始化 age = 90 name = null
- 构造器的初始化 age = 20 name = “小倩”
- 将对象在堆中的地址,赋给p(p是对象名,也可以理解为p是对象的引用)
图解
十、this关键字
this入门(this01)
1 | public class This01 { |
补充
检测是否是同一个对象可以用 hashCode() 方法,
可以简单的看为对象的地址(实际上不是对象的地址)
用法: 对象名.hashCode() 例如: this.hashCode()
小结
简单的来说,哪个对象调用,this就代表那个对象
深入理解this
代码:this01
图解
哪个对象调用,this就代表哪个对象
this的注意事项和使用细节(ThisDetail)
- this 关键字可以用来访问本类的属性、方法、构造器
- this 用于区分当前类的属性和局部变量
- 访问成员方法的语法:this.方法名(参数列表);
- 访问构造器语法:this(参数列表); 注意只能在构造器中使用(即只能在构造器中访问另外一个构造器, 必须放在第一条语句)
- this 不能在类定义的外部使用,只能在类定义的方法中使用。
1 | public class ThisDetail { |
this 关键字可以用来访问本类的属性、方法、构造器
访问属性:用法 this.属性名 例如
this.name;
访问成员方法的语法:this.方法名(参数列表);
访问方法: 用法 this.方法名(参数列表) 例如
this.f1();
this练习题
定义Person 类,里面有name、age 属性,并提供compareTo 比较方法,用于判断是否和另一个人相等,提供测试类TestPerson用于测试, 名字和年龄完全一样,就返回true, 否则返回false
1 | public class TestPerson { |
本章作业
1.编写类A01, 定义方法max,实现求某个double数组的最大值,并返回
Homework01.java
1
2.编写类A 02, 定义方法find,实现查找某字符串是否在字符串数组中,并返回索引
如果找不到, 返回-1 .Homework02.java
1
3.编写类Book, 定义方法update Price, 实现更改某本书的价格, 具体:如果价格
>150, 则更改为150, 如果价格>100, 更改为100, 否则不变Homework 03.java
1
4.编写类A03, 实现数组的复制功能copy Arr, 输入旧数组, 返回一个新数组, 元素和
旧数组一样Homework04.java
1
5.定义一个圆类Circle, 定义属性:半径,提供显示圆周长功能的方法, 提供显示圆
面积的方法Homework05.java
1
6.编程创建一个Cale计算类,在其中定义2个变量表示两个操作数, 定义四个方法实
现求和、差、乘、商(要求除数为0的话,要提示)并创建两个对象,分别测试
Homework06.java
1
7.设计一个Dog类, 有名字、颜色和年龄属性, 定义输出方法show() 显示其信息。
并创建对象,进行测试、 【提示this.属性】 Homework 07.java
给定一个Java程序的代码如下所示,则编译运行后, 输出结果是(10, 9, 10) (test2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public class test2 {
int count=9;
public void count1() {
count = 10;
System.out.println("count1= " + count);
}
public void count2() {
System.out.println("count1= " + count++); //后++ 先赋值 后运算
}
//这是test2类的主方法(主函数), 任何一个类,都可以有main方法
public static void main(String[] args) {
//1. new test2() 是匿名对象, 匿名对象只能使用一次,使用后会被销毁
//2. new test2().count1() 创建好匿名对象后就立即调用 count1方法
new test2().count1();
test2 t1 = new test2();
t1.count2();
t1.count2();
}
} 解读
new test2().count1();
- new test2() 是匿名对象, 匿名对象只能使用一次,使用后会被销毁
- new test2().count1() 创建好匿名对象后就立即调用 count1方法
后++ 先赋值,后运算 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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
9. 定义一个Music类,里面有音乐名name、音乐时长times属性,
并有播放play功能和返回本身属性信息的功能方法 getInfo
10. 写出下列代码的运行结果
11. 在测试方法中, 调用method方法,代码如下,编译正确, 试写出method方法的
定义形式, 调用语句为:System.out.println(method(method(10.0, 20.0) , 100) ) ;
Homework11.java
public double method(double d1, double d2) {...}
12. 12.创建一个Employee类,属性有(名字, 性别, 年龄, 职位, 薪水),提供3个构造
方法,可以初始化
(1)(名字,性别,年龄,职位,薪水),
(2)(名字,性别,年龄)
(3) (职位,薪水),要求充分**复用**构造器 Homework 12.java
13. 13.将对象作为参数传递给方法。 Homework 13.java
题目要求:
(1) 定义一个Circle类, 包含一个double型的radius属性代表圆的半径, findArea 方
法返回圆的面积。
(2) 定义一个类PassObject, 在类中定义一个方法printAreas, 该方法的定义如下:
public void print Areas(Circle c, int times) //**方法签名/声明**
(3) 在printAreas方法中打印输出1到times之间的每个整数半径值, 以及对应的面积。
例如, times为5, 则输出半径1, 2, 3, 4, 5, 以及对应的圆面积。
(4) 在main方法中调用print Areas() 方法, 调用完毕后输出当前半径值。程序运行结果
如图所示,提示,如果还是不明确,自己画一个内存图,一定可以搞定

14. tom设计他的成员变量,成员方法,可以实现电脑猜拳,电脑每次都会随机生成
0,1,2 0表示石头, 1表示剪刀, 2表示布
并要可以显示Tom的输赢次数(清单)
# ⭐第七章 面向对象编程(中级)
## 一、包
### 包的三大作用
1. 区分相同名字的类
2. 当类很多时,可以很好的管理类(java API 文档)
3. 控制访问范围
### 包基本语法
```java
package com.chapter
说明
- package 关键字,表示打包
- com.chapter:表示包名
包的本质分析(原理)
包的本质就是创建不同的文件夹/目录来保存文件
包快速入门
包的命名
命名规则
只能包含数字、字母、下划线、小圆点,但不能用数字开头,不能是关键字或保留字
命名规范
一般为小写字母+小圆点
例:
com.公司名.项目名.业务模块名
com.sina.crm.user 用户模块
常用的包
一个包下,包含很多的类,java 中常用的包有:
java.lang.*
lang 包是基本包,默认引入,不需要再引入java.util.*
util 包,系统提供的工具包, 工具类,使用 Scannerjava.net.*
网络包,网络开发java.awt.*
是做java 的界面开发,GUI
如何引入包
语法
import 包
我们引入一个包的主要目的是要使用该包下的类
例如:import java.util.Scanner;
就是引入一个类Scaner
1 |
|
二、访问修饰符
基本介绍
java有四种访问修饰符,用于控制方法和属性(成员变量)的访问权限(范围)
- 公开级别: public 修饰,对外公开
- 受保护级别: protected修饰,对子类和同一个包的类公开
- 默认级别: 没有修饰符,向同一个包的类公开
- 私有级别: private修饰, 只有类本身可以访问,不对外公开
四种访问修饰符的访问范围
访问级别 | 访问控制修饰符 | 同类 | 同包 | 子类 | 不同包 |
---|---|---|---|---|---|
公开 | public | √ | √ | √ | √ |
受保护 | protected | √ | √ | √ | X |
默认 | 没有修饰符 | √ | √ | X | X |
私有 | private | √ | X | X | X |
访问修饰符使用的注意事项
- 修饰符可以用来修饰类中的属性,成员方法以及类(修饰类只能用public 和 默认)
- 只有默认的和public才能修饰类!并且遵循上述访问权限的特点
- 继承(·······)
- 成员方法的访问规则和属性完全一致
1 |
三、面向对象编程三大特性之:封装
基本介绍
面向对象编程有三大特征:封装、继承和多态
封装介绍
封装(encapsulation)就是把抽象出来的数据(属性)和对数据的操作(方法)封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作(方法),才能对数据进行操作。
封装的理解和好处
- 隐藏实现细节:方法(连接数据库<—-调用(传入参数…)
- 可以对数据进行验证,确保数据的安全合理性
封装的实现步骤
将属性进行私有化(private)【不能直接修改属性】
提供一个公开的(public)set方法,用于对属性判断并赋值
1
2
3
4public void setXxx(类型 参数名){ XXX表示某个属性
加入数据验证的业务逻辑
属性 = 参数名;
}提供一个公共的(pulbic)get方法,用于获取属性的值
1
2
3public 数据类型 getXxx(){ 权限判断,Xxx表示某个属性
return xx;
}
例子:
package chapter08.encapsulation; Encapsulation01.java
1 | public class Encapsulation01 { |
封装与构造器
将构造器和setXxx方法结合
1 | //有三个属性的构造器 |
课堂练习
package chapter08.encapsulation; Account.java AccountTest.java
创建程序,在其中定义两个类:Account 和AccountTest 类体会Java 的封装性。
- Account 类要求具有属性:姓名(长度为2 位3 位或4 位)、余额(必须>20)、
- 密码(必须是六位), 如果不满足,则给出提示信息,并给默认值(程序员自己定)
- 通过setXxx 的方法给Account 的属性赋值。
- 在AccountTest 中测试
1 | public class Account { |
1 | public class AccountTest { |
四、继承
为什么需要继承
继承可以提高代码的复用性,让子类不需要重新定义这些属性和方法
继承的基本介绍
继承可以解决代码复用, 让我们的编程更加靠近人类思维. 当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类, 在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends 来声明继承父类即可
继承的示意图:
继承的基本语法
1 | class 子类 extends 父类 { |
说明
- 子类会拥有父类定义的属性和方法
- 父类又叫做超类、基类
- 子类又叫派生类
继承快速入门
package chapter08.extends_
1 | public class Pupil extends Student{ |
1 | public class Graduate extends Student { |
1 | //父类,是pupil 和 Graduate的父类 |
继承带来的好处
- 提高了代码的复用性
- 代码的拓展性和维护性提高了
继承细节
- 子类继承了父类所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问
- 在子类创建对象时,子类必须调用父类的构造器,完成父类的初始化
- 在子类创建对象时,不管使用子类的哪个构造器,默认情况都会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定父类中的构造器完成对父类的初始化工作,否则,会出现编译错误
- 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)
- super关键字在使用时,必须放在行首
- super和this会冲突,因为都必须放在行首
- Object是所有类的父类
- 父类的构造器调用不限于直接父类!将一直往上追溯到顶级父类Object
- 子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制
- 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系
继承的本质(ExtendsTheory)
案例
当创建子类对象时,内存中发生了什么?
1 | public class ExtendsTheory { |
当子类继承时,查找信息有以下关系:
1.首先看子类是否有该属性,如果有且可以访问,就返回信息
2.如果没有,就继续找上级父类(如果父类有该属性,并且可以访问,就返回信息..),直到顶级父类Object
图解
练习
练习1. 下面代码输出什么?
1 | public class ExtendsExercise02 { |
练习2. package chapter08.extends_.exercise;
编写 Computer 类,包含 CPU、内存、硬盘等属性,getDetails 方法用于返回 Computer 的详细信息
编写 PC 子类,继承 Computer 类,添加特有属性【品牌 brand】
编写 NotePad 子类,继承 Computer 类,添加特有属性【color】
编写 Test 类,在 main 方法中创建 PC 和 NotePad 对象,分别给对象中特有的属性赋值,以及从 Computer 类继承的属性赋值,并使用方法并打印输出信息
五、super关键字
基本介绍
super 代表父类的引用,用于访问父类的属性、方法、构造器
基本语法
访问父类的属性,但不能访问父类private 属性
super.属性名
访问父类的方法,不能访问父类的private方法
super .方法名(参数列表)
访问父类的构造器
只能放在构造器的第一行,只能出现一句!
super(参数列表);
super的细节
- 调用父类的构造器的好处(分工明确,父类属性由父类初始化,子类的属性由子类初始化)
- 当子类中有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super,如果没有重名,使用super、this、直接访问是一样的效果!
- super和访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;如果多个父类中都有同名的成员,使用super访问遵循就近原则。A->B->C,当然也需要准数访问权限的相关规则
super和this的比较
五、方法重写/覆盖(override)
基本介绍
简单的说:方法重写(覆盖)就是子类有一个方法和父类某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法
使用事项和使用细节
方法重写也叫方法覆盖,需要满足下面的条件
子类的方法的形参列表,方法名称,要和父类方法的形参列表、方法名称完全一致
子类方法的返回类型和父类的方法返回类型一样,或者是父类返回类型的子类型
比如 父类返回类型时 Object,子类的方法返回类型是String
子类方法不能缩小父类方法的访问权限
public > protected > 默认> private
方法重写和方法重载的比较
六、面向对象编程-多态
多态的基本介绍
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的
多态的具体体现
方法的多态
重写和重载体现多态 (package chapter08.poly.polymethod)
对象的多态(重难点)(polyobject)
- 一个对象的编译类型和运行类型可以不一致
- 编译类型在定义对象时,就确定了,不能改变
- 运行类型时可以变化的
- 编译类型看定义时 = 号的左边,运行类型 看 = 号的右边
例如:Animal animal = new Dog();
[animal编译类型时Animal,运行类型时Dog]
1 |
|
零钱通项目(chapter08.smallchange)
本章作业(chapter08.homework)
房屋出租系统
程序框架图(分层模式)
⭐第八章 面向对象编程(高级)
一、类变量和类方法
类变量
定义
类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个该类的对象去访问他时, 取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量.
语法
定义语法:
访问修饰符 static 数据类型 变量名;
static 访问修饰符 数据类型 变量名;
如何访问变量
类名.类变量名;
对象名.类变量名;
类变量的使用注意事项和细节
什么时候需要使用类变量
当我们需要让某个类的所有对象都共享一个变量时,就可以考虑使用类变量(静态变量):
比如:定义学生类,统计所有学生共交多少钱.
类变量与实例变量的区别
类变量是该类的所有对象共享的,而实例变量是每个对象独享的
类变量通过
类名.类变量名;
或对象名.类变量名;
来访问静态变量实在类加载的时候就创建了(初始化),所以不用实例化对象,也可使用类变量
类变量的生命周期是随着类的加载开始,随着类的消亡二销毁
类方法
类方法也叫静态方法
使用方式
访问修饰符 static 数据返回类型 方法名(){ }
static 访问修饰符 数据返回类型 方法名(){ }
类方法的调用
前提:满足访问修饰符的访问权限
类名.类方法名
或者对象名.类方法名
静态方法经典的使用场景
当方法中不涉及到任何和对象相关的成员,则可以将方法设计成静态方法,提高开发效率
例如:工具类中的方法utils
Math类、Arrays类、Collections 集合类
小结:
在实际开发中,往往会将一些通用的方法,设计成静态方法,这样我们不需要创建对象就可以使用了,
比如打印一些一维数组,冒泡排序,完成某个计算任务
类方法使用注意事项和细节
类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法区
类方法中无this的参数 (不可以在类方法中使用this和super)
普通方法中隐随着this的参数
类方法可以通过类名调用,也可以通过对象名调用
普通方法和对象有关,需要通过对象名调用
例如:
对象名.方法名(参数)
,不能通过类名调用类方法中不允许使用和对象有关的关键字,如this和super.普通方法可以
类方法中只能访问 静态变量 或静态方法
普通成员方法既可以访问 非静态成员,也可以访问静态成员
小结:
静态方法 ,只能访问静态的成员,非静态的方法,可以访问静态成员和非常静态成员
二、深入理解main方法
解释main方法的形式:
public static void main(String[] args) { }
- main方法由java虚拟机调用
- java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public
- java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static
- 该方法接受String类型的数组参数,该数组中保存java命令时传递给所运行的类的参数
- java 执行的程序 参数1 参数2 参数3
0main方法细节(main02)
- 在main不可直接调用非静态的成员(属性和方法), 但可同过new对象来间接调用非静态成员n()方法中,我们可以直接调用main方法所在类的静态方法或静态属性
- main()不可直接调用非静态的成员(属性和方法), 但可同过new对象来间接调用非静态成员
三、 代码块
基本介绍
代码块又被称为初始化快,属于**类中的成员(**是类的一部分),类似于方法,将逻辑语句封装在方法体中,通过{}包围起来.
语法
修饰符 {
代码
}
说明
- 修饰符可选,要么为空, 要么写static
- 代码块分为两类,使用static修饰的为静态代码块, 没有static修饰的,叫普通代码块/非常静态代码块
- 逻辑语句可以为任何逻辑语句(输入、输出、方法调用、循环、判断等)
代码块带来的好处
- 代码块相当于另外一种形式的构造器(对构造器的补充机制), 可以做初始化的操作
- 场景: 如果多个构造器都有重复的语句,可以抽取到代码块中,提高代码的复用率
代码块使用的注意事项和细节
一 CodeBlockDetail01
static代码块也叫静态代码块,作用就是对类进行初始化,而且他随着类的加载而执行,
并且只会执行一次.如果是普通代码块,每创建一个对象,就会执行一次
类什么时候被加载
- 创建对象实例时(new)
- 创建子类对象实例时,父类也会被加载
- 使用类的静态成员时(静态属性,静态方法)
普通的代码块,在创建对象实例时,会被隐式的调用
被创建一次,就会调用一次.如果只是使用类的静态成员时,普通代码块产能不会执行
小结
- static代码块是类加载时,执行,并且只会执行一次
- 普通代码块是在创建对象时调用的,创建一次,调用一次
二 CodeBlockDetail02
- 创建一个对象时,在一个类 调用的顺序是
- 调用静态代码块和静态属性初始化(注意**:静态代码块和静态属性初始化调用的优先级一样**,如果有多个静态代码块和多个静态变量初始化,则按他们定义的顺序调用)
- 调用普通代码块和谱图属性的初始化(普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,则按定义顺序调用)
- 完成自身的构造器
小结
在同一个类中,静态代码块 普通代码块 和 构造器 的优先级为:
静态(成员) > 普通(成员) > 构造器
静态方法和静态代码块按顺序执行(顺序在前的先执行), 普通方法和普通代码块按顺序执行
三 CodeBlockDetail03
- 构造器的 最前面其实隐含了
super();
和调用普通代码块
在创建一个子类对象时, 程序的执行流程如下:
完成类信息的加载
- 首先完成父类静态代码块和静态属性的初始化(两者优先级相同,顺序在前的先加载)
- 其次完成子类静态代码块和静态属性的初始化(两者优先级相同,顺序在前的先加载)
对象的创建
- 完成
父类普通代码块
和普通属性的初始化
- 完成
父类构造器
的初始化, - 最完成子类
普通代码块
和普通属性
的初始化 - 完成
子类构造器
的初始化
- 完成
四、单例设计模式
什么是单例模式
单例: 单个的实例
- 所谓类的设计模式,就是采取一定的方法保证在整个的软件系统中, 对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法
- 单例模式的两种方式: 1) 饿汉式 2) 懒汉式
单例模式—饿汉式
饿汉式的设计方法
- 单例模式–饿汉式
- 将构造器私有化 –> 防止外部直接new对象
- 在类的内部创建一个对象
- 向外部提供一个public的静态方法
单例模式—懒汉式
单例模式–懒汉式
- 将构造器私有化 –> 防止外部直接new对象
- 在类的内部声明一个对象
- 向外部提供一个public的静态方法,在方法体中new 一个对象
饿汉式vs懒汉式
两着的主要区别在与创建对象的时机不同:饿汉式实在类加载就创建了对象实例,
而懒汉式是在使用时才创建
懒汉式存在线程安全问题(饿汉式不存在)
饿汉式存在浪费资源的可能.如果开发者一个对象实例都没有使用,那么饿汉式创建的对象就浪费了,
懒汉式是使用时才创建,不存在这个问题
在javaSE标准类中, java.lang.Runtime就是经典的单例模式
五、final关键字
基本介绍
final可以修饰类/属性/方法和局部变量
在某些情况下, 可能会有需求,就会使用到final
final的使用时机
- 当不希望类被继承时,可以用final修饰
- 当不希望父类的某个方法被子类重写(override)时,可以使用final关键字修饰
- 当不希望类的某个属性的值被修改时,可以使用final修饰
语法(Final01)
final class 类名 {}
public final double TAX_TATE = 0.08;
public static final double TAX_TATE = 0.08;
final使用注意事项和细节
被final修饰的属性又叫做常量,一般用XX_XXX_XX来命名
final修饰的属性在定义时,必须赋初值,并且以后不能修改,赋值可以在以下位置:
- 定义时: 如
public final double TAX_TATE = 0.08;
- 在构造器中
- 在代码块中
- 定义时: 如
如果final修饰的属性是静态的,则初始化的位置只能是:
- 定义时
- 在静态代码块中,不能在构造器中赋值
final类不能继承,但可以实例化对象
如果类不是final类, 但含有final方法, 则该方法虽然不能重写,但可以被继承
六、抽象类
基本介绍
当父类的某些方法需要声明,但是又不确定如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类
当父类的一些方法不能确定时, 可以用abstract来是该类, 这个类就为抽象类
语法
修饰类:
访问修饰符 abstract 类名{ }
修饰方法:
访问权限 abstract 返回类型 方法名(参数列表);
注意: 抽象方法没有方法体
解读抽象类
- 用abstract关键字来修饰一个类时, 这个类就叫抽象类
- 用abstract关键字来修饰一个方法时, 这个方法就是抽象方法
- 抽象类的价值更多作用在于设计,是设计者设计好后, 让子类继承并实现抽象类
- 抽象类,是重要的面试题, 主要用于框架和设计模式
抽象类使用的注意事项和细节
- 抽象类不能被实例化
- 抽象类不一定要包含abstract方法, 也就是说, 抽象类可以没有abstract方法
- 一旦类包含了abstract方法,则这个类必须声明为abstract
- abstract只能修饰类和方法,不能修饰属性和其他的
- 抽象类可以有任意成员,(抽象类本质还是类)
- 抽象类方法不能有方法体
- 如果一个类继承了抽象类, 则它必须实现抽象类的所有抽象方法,除非他自己也声明为抽象类
模板设计模式
基本介绍
抽象类体现的就是一种模板的设计, 抽象类作为多个子类的通用模板,再累在抽象类的基础上进行拓展/改造,单子类总体上会保留抽象类的行为方式.
模板设计模式解决的问题
- 当功能内部一部分实现是确定的,一部分是不确定的. 这时可以把不确定的部分暴露出去,让子类去实现
- 编写一个父类, 父类提供了多个子类的通用方法, 并把一个或多个方法留给其子类实现,就是模板模式
案例: chapter10.abstract_.template;
⭐七、接口
基本介绍
接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候, 再根据具体情况把这些方法写出来
语法
interface 接口名 {
//属性
//抽象方法
}
class 类名 implements 接口 {
自己属性;
自身方法;
必须实现接口的抽象方法
}
小结
接口是更加抽象的抽象的类, 抽象类里的方法可以有方法体,在JDK1.7以前, 接口里的方法都没有发放体
在JDK1.8后,接口类可以有静态方法,默认方法,也就是说接口中可以用方法的具体实现
接口的注意事项和细节
接口不能被实例化
接口中有的方法是public方法,接口中的抽象方法,可以不用abstract修饰
一个普通类实现接口,就必须将该接口的所有方法实现
抽象类实现接口,可以不用实现接口的方法
一个类同时可以实现多个接口(java中的多继承)
接口中的属性,只能是final的,而且是
public static final
例如:
int a = 1;
实际上是pulic static final int a = 1;
(必须初始化)接口中属性的访问形式, 接口名.属性名
接口中不能继承其他类,但是可以继承多个别的接口
例如:
interface A extends B, C{}
接口的修饰符,只能是public和默认
接口Vs继承(chapter10.interface_.interfacevsextends)
接口和继承解决的问题不同
- 接口的价值主要在于: 解决代码的复用性和可维护性
- 接口的价值主要在于: 设计,设计好各种规范(方法), 让其他类去实现这些方法. 即更加的灵活
接口比继承更加灵活
继承是满足is - a 的关系, 二接口只需要满足 like - a的关系
接口在一定程度上实现代码的解耦(即: 接口规范性 + 动态绑定机制)
接口的多态特性(chapter10.interface_.poly)
- 多态参数
- 多态数组
- 接口存在多态传递现象
1 | public class InterfacePolyPass { |
⭐八、内部类
类的成员: 属性、方法、构造器、代码块、内部类
基本介绍
一个类的内部又完整的嵌套了另一个类结构, 被嵌套的类称为内部类,
嵌套其他类的类称为外部类.
内部类的最大特点是可以直接访问私有属性,并且可以体现类与类之间的包含关系
内部类的分类
定义在外部类局部位置上(方法体或代码块中)
- 局部内部类(有类名)
- 匿名内部类(乜有类名)!!!!!!!!!!!!!!!!!!!!!!!!
定义在外部类的成员位置上:
- 成员内部类(没有static修饰)
- 静态内部类(使用stati修饰)
1. 局部内部类
说明: 局部内部类时定义在外部类的局部位置,比如方法中,并且有类名
- 局部内部类是定义在外部类的局部位置, 通常在方法中
- 局部内部类本质仍然是一个类, 但不能使用访问修饰符,可以用final修饰,使其不能继承
- 作用域: 仅仅在它的方法或代码块中
- 局部内部类可以直接访问外部类的所有成员,包括私有的
- 如果外部类和局部内部类的成员都重名时, 默认遵循就近原则,
如想访问外部类的成员, 使用 外部类名.this.成员 去访问 - 若想访问局部内部类的方法,外部类在方法中,可以创建对象,然后调用方法即可
小结
- 局部内部类定义在方法中/代码块中
- 作用域在方法体或代码块中
- 本质是类
1 |
|
⭐🌈2. 匿名内部类!!!★☆★☆★
匿名内部类特点:
- 本质还是类
- 内部类
- 该类没有名字
- 同时也是一个对象
基本语法
1 | new 类或接口(参数列表) { |
注意最后的 ;
不能省略
基于接口的匿名内部类
1 |
|
基于类的匿名内部类
1 | /** |
匿名内部类的注意事项和细节
匿名内部类的语法比较奇特, 因为匿名内部类既是一个类的定义,同时它本身也是一个对象,
因此从语法上看, 他即有定义类的特征,也有创建对象的特征,
可以直接访问外部类的所有成员, 包括私有的
匿名内部类不能添加访问修饰符, 因为它就是一个局部变量
匿名内部类的作用域: 仅仅在定义它的方法或代码块中
外部其他类不能访问匿名内部类(因为匿名内部类地位是一个局部变量)
如果外部类和匿名内部类的成员都重名时, 默认遵循就近原则,
如果想访问外部类的成员, 使用 外部类名.this.成员 去访问
3. 成员内部类
说明: 成员内部类是定义在外部类的成员位置, 并且没有static 修饰
使用细节和注意事项
- 可以直接访问外部类的所有成员,包含私有的
- 可以添加任意访问修饰符(四种), 因为他的地位就是一个成员
- 作用域: 和外部类的其他成员一样, 为整个类体
- 成员内部类访问外部类的方式: 直接访问
- 外部类访问成员内部类的方式: 创建对象, 再访问
- 如果外部类和成员内部类的成员都重名时, 默认遵循就近原则,
如果想访问外部类的成员, 使用 外部类名.this.成员 去访问
在其他外部类创建成员内部类的对象 语法为:
外部类名.成员内部类名 对象名 = 外部类对象名. new 成员内部类名();
第二种:
1 | //第二种, 在外部类中编写一个可以返回对象的方法 |
4. 静态内部类
说明: 静态内部类是定义在外部类的成员位置, 且必须要用statci修饰
- 可以直接访问外部类的所有静态成员,包含私有的
- 可以添加任意访问修饰符(四种), 因为他的地位就是一个成员
- 作用域: 和外部类的其他成员一样, 为整个类体
- 外部类访问静态内部类的方式: 创建对象, 再访问
- 如果外部类和静态内部类的静态成员都重名时, 默认遵循就近原则,
如果想访问外部类的成员, 使用 外部类名.成员 去访问
1 | public class StaticInnerClass { //其他外部类 |
✅第九章 枚举和注解
一、枚举
枚举的基本介绍
枚举: enumeration
枚举是一组常量的集合(对象)
可以这样理解: 枚举属于一种特殊的类, 里面只包含一组有限的特定的对象
枚举的两种实现方式
- 自定义枚举
- 使用enum关键字实现mwju
自定义实现枚举
- 不需要提供set方法, 因为枚举对象通常为只可读
- 对枚举对象/属性 使用
public static + final
共同修饰, 实现底层优化 - 枚举对象通常使用全部大写,常来能的命名规范
- 枚举对象根据需要, 也可能有多个属性
小结:
进行自定义枚举有一下特点:
- 构造器私有化
- 本类内部创建一组对象
- 对外暴露对象, (通过public static final修饰)
- 提供get方法, 但不能提供set方法
enum关键字实现枚举
使用关键字enum代替枚举
pulic static final Season SPRING = new Season(“春天”, “温暖”)
直接使用SPRING(“春天”, “温暖”)
来代替如果有多个常量(对象), 使用
,
来隔开使用enum来实现枚举, 要求将定义常量对象写在前面, 并且对象名(常量名)全部大写
如果使我们使用的是无参构造器,在创建常量时, 可以省略()
枚举的使用细节和注意事项
当我们使用enum关键字来实现一个枚举类时, 默认会继承Enum类, 而且默认是一个final类
传统的
pulic static final Season SPRING = new Season(“春天”, “温暖”);
简化成了
SPRING(“春天”, “温暖”)
,调用的是有两个参数的构造器如果我们使用的是无参构造器,在创建常量时, 可以省略()
枚举对象必须放在枚举类的首行
Eunm类的相关方法
当使用enum关键字时, 会隐式的继承Enum类,我们就可以使用Enum类的方法
- toString方法 : Enum类重写了, 返回对象的名称
- name: 返回当前对象名(常量名),子类中不能重写
- ordinal: 返回当前对象的位置号, 默认从0开始
- values: 返回枚举类中所有的常量(一个数组)
- valueOf: 将字符串转换成枚举对象, 字符串必须为已有的常量, 否则抛出异常
- compareTo: 比较两个枚举常量, 比较的是编号,返回两者对象位置的差值
- 使用enum关键字后,虽然我们不能在继承其他类, 但枚举可以实现接口
二、注解 (Annotation)
注解的基本介绍
注解(Annotation)也被称为元数据(Metadata), 用于修饰解释
包/类/方法/属性/构造器/局部变量等数据信息
和注释一样, 注解不影响程序逻辑, 但注解可以被编译或运行, 相当于嵌入在代码中的补充信息
在JavaSE中, 注解的使用目的比较简单, 例如标记过时的功能, 忽略警告等.
在javaEE中注解占据了更重要的角色, 例如用来配置应用程序的任何切面, 代替Java EE
旧版中所遗留的繁冗代码和XMl配置等
Annotation
说明:
使用Annotation 时要在其前面增加@ 符号, 并把该 Annotation 当成一个修饰符来使用.
用于修饰它支持的程序元素
三个基本的Annotation:
- @OVerride: 限定某个方法, 是重写父类方法, 该注解只能用于方法
- @Deprecated: 用于表示某个程序元素(类/方法等)已过时
- @SuppressWarnings: 抑制编译器警告
Annotation应用案例
@OVerride注解案例
1 | /** |
@Deprected注解案例
- 用于表示某个程序元素(类/方法)已过时
- 可以修饰方法/类/字段/包/参数等等
- @Deprected的作用可以做到新旧版本的兼容和过渡
1 | package chapter11.annotation_; |
@SuppressWarnings注解案例
1 | package chapter11.annotation_; |
元注解
基本介绍:元注解就是修饰注解的注解
元注解的种类
- Retention : 指定注解的作用范围,三种 SOURCE,CLASS,RUNTIME
- Target : 指定注解可以在哪些地方使用
- Documented : 指定该注解是否会在 javadoc 体现
- Inherited : 子类会继承父类注解
✅第十章 异常
异常介绍
基本概念
java语言中, 讲程序执行中发生的不正常的情况称为”异常”.(开发过程中的语法错误和逻辑错误不是异常)
异常的分类
执行过程中所发生的异常事件可以分为两大类
Error(错误): java虚拟机无法解决的严重问题.
如:java系统内部错误,资源耗尽等严重情况,
如: StackOverflowError(栈溢出)和OOM(out of memory),Error是严重错误,程序会错误
Exception: 其他因编程错误或偶然的外在因素导致的一般性问题, 可以使用针对性的代码进行处理.
如空指针访问,试图读取不存在的文件, 网络连接中断等等,
Exception 分为两大类:
- 运行时异常: 程序在运行时, 发生的异常
- 编译时异常: 编程时, 编译器检查出的异常
异常体系图
异常体系图小结
异常分为两大类, 运行时异常和编译时异常
运行时异常,编译器检查不出来, 一般是指程序的逻辑错误, 是开发者应该避免的错误.
java.lang.RuntimeException 类及它的子类都是运行时异常
对于运行时异常,可以不作处理, 因为这类异常很普遍, 若全处理可能会对程序的可读性和运行效率产生影响
编译时异常, 是编译器要求必须处置的异常
常见的异常
常见的运行时异常
- NullPotinterException 空指针异常
- ArithmeticExcetion 数学运算异常
- ArrayIndexOutOfBoundsException 数组下标越界异常
- ClassCastEXception 类型转换异常
- NumberFormatException 数字格式不正确异常
常见运行时异常举例
- NullPointerException 空指针异常
1 | public class NullPointerException { |
- ArithmeticException 数学运算异常
1 | public class ArithmeticException { |
- ArrayIndexOutOfBoundsException 数组下标越界异常
1 | public class ArrayIndexOutOfBoundsException { |
- ClassCastException 类型转换异常
1 | public class ClassCastException { |
- NumberFormatException 数字格式不正确异常
1 | public class NumberFormatException { |
常见的编译异常
介绍: 编译异常是指在编译期间, 就必须处理的异常, 否则代码不能通过编译
案例
1 | public class Exception01 { |
异常处理
介绍: 异常处理就是当异常发生时, 对异常的处理方式
异常处理的方式
try-catch-finally
开发者在代码中捕获发生的异常,自行处理
throws
将发生的异常抛出, 交给调用者(方法)来处理, 最顶级的处理者就是JVM
(简单理解就是踢皮球)
try-catch-finally处理机制示意图
thorws机制处理图
使用try-catch处理异常
说明:
java中提供try和catch块来处理异常, try块中包含可能出错的代码.
catch块用于处理try块中的异常. try…catch块可有多个
基本语法
1 | try{ |
注意事项
如果异常发生, 则异常发生后面的代码不会执行, 直接进入到catch块
如果异常没有发生,则顺序执行try的代码块, 不会进入到catch块
无论发生异常, 都会执行finally块, 通常在这里释放资源,关闭连接
可以有多个catch语句, 捕获不同的异常, 要求父类异常在后, 子类异常在前
如: (Exception在后, NullPointerExcetion在前),如果发生异常, 只会匹配到一个catch
可以进行
try-finally
配合使用, 相当于没有捕获异常, 因此程序可能会直接崩溃/退出
小结:
如果没有出现异常: 则执行try块中的代码, 不执行catch块,如果有finally块, 则会必定执行
如果异常发生, 则异常发生后面的代码不会执行, 直接进入到catch块,如果有finally块, 则会必定执行
使用throws处理异常
基本介绍:
- 如果一个方法(中的语句执行时)可能发生异常, 但是不能确定如何处理异常, 则方法中应当显示的声明抛出异常,表明此方法将不对这些异常进行处理, 而由方法的调用者处理
- 在方法中,声明用throws语句可以声明抛出异常的列表,throws后面的异常类型可以方法中产生的异常类型,也可以是它的父类.
案例:
1 | import java.io.FileInputStream; |
使用的注意事项和细节
- 对于编译异常,程序中必须处理, 比如
try-catch
或throws
- 对于运行时的异常, 程序中如果没有处理, 默认就是用throws方式处理
- 子类中重写父类的方法时, 对抛出异常的规定: 所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出异常类型的子类型
- 在throws过程中, 如果方法try-catch,就相当于处理异常, 可以不必throws
自定义异常
基本概念:
当陈旭忠出现了某些”错误” , 单该错误信息并没有在Throwable子类中描述处理, 这时候可以自己设计异常类, 用于描述该错误信息
自定义异常步骤:
- 定义类: 自定义异常类名继承Exception或RuntimeException
- 如果继承Exception,属于编译异常
- 如果继承RuntimeException,属于运行异常(一般来说,继承RuntimeException)
实例
1 | public class CustomException { |
throw和throws的区别
意义 | 位置 | 后面跟的东西 | |
---|---|---|---|
throws | 异常处理的一种方式 | 发放中声明处 | 异常类型 |
throw | 手动生成异常对象的关键字 | 方法体中 | 异常对象 |
✅第十一章 常用类
一、包装类
包装类的分类
- 针对八种基本数据类型相应的引用类型 —–> 包装类
- 有了类的特点, 就可以调用类中的方法
基本数据类型 | 包装类 | 所属包装类的父类 |
---|---|---|
boolean | Boolean | Object |
char | Character | Object |
byte | Byte | Number |
short | Short | Number |
int | Integer | Number |
long | Long | Number |
float | Float | Number |
double | Double | Number |
包装类和基本数据的转换
- jdk5前手动装箱和拆箱 装箱: 基本类型–>包装类型,反之,拆箱
- jdk5以后(包括5) 支持自动装箱和拆箱
- 自动装箱底层调用的是valueOf方法.如
Integer.valueOf();
案例
1 | public class Integer01 { |
包装类和String类型的相互转换
案例:
1 | /** |
Integer类和Character类的常用方法
说明: 会java API 查文档即可
案例:
1 | /** |
Integer类经典的面试题
1 | /** |
总结:
当基本类型和Integer类型比较时, 判断的是值是否相同
使用==判断两个Integer是否相同时,判断的是是否为同一个对象(地址是否相同),
而使用关键字new ,结果必然是F
Integer i1 = 10;
等价于Integer i1 = Integer.valueOf(10);
即自动装箱默认 使用了
Integer.valueOf(n1)
方法,而在Integer类的valueOF()方法中,当传入的值为-128-127这个范围时, 返回的是数组中的值(即不会new新的对象), 当超过这个范围时, 会返回新的对象
🌈二、String类
深入理解String类和创建对象
String 对象用于保存字符串,也就是一组字符序列
字符串常量, 双引号括起的字符序列 例如:
“你好”,"123", "12.97","boy"
字符串的字符使用 Unicode 字符编码,一个字符(不区分字母还是汉字)占两个字节
String 类有很多构造器,构成了构造器的重载
String s2 = new String(String original); String s3 = new String(char[] a); String s4 = new String(char[] a,int startIndex,int count) String s5 = new String(byte[] b)
String类的结构关系
串行化: 可以在网络传输 Comparable : String对象可以比较大小
代码说明:
1 | /** |
创建String对象两种方式
- 直接赋值
String s = “hello”
- 调用构造器
String s = new String(“helloworld”)
两种方式的区别★★
方式一: 先从常量池查看是否有 “hello”数据空间, 如果有, 直接指向; 如果没有则重新创建, 然后指向,
s最终指向的是常量池的空间地址
方式二: 先在堆中创建对象, 里面维护了value属性, 指向常量池的 hello 空间. 如果常量池没有 “hello”,
重新创建,如果有, 直接通过value指向, 最终指向的是堆中的空间地址
两种方式的内存分布图:
String对象练习题
1 | /** |
intern()方法说明:
当调用intern方法时,如果常量池已经包含与equals(Object)方法确定的相当于此String对象的字符串,则返回来自池的字符串
解读: b.intern方法()最终返回的是常量池的地址(对象)
字符串的特性
- String是一个final类, 代表不可变的字符序列
- 字符串是不可变的. 一个字符串对象一旦被分配, 其内容是不可变的
String面试题
题一
Strng a = “hello” + “abc”;
创建了几个对象? 一个- 解读:
Strng a = “hello” + “abc”;
===> 优化等价于String a = "hellowabc;"
说明: 编译器会做一个优化, 判断创建的常量池对象,是否有应用指向
题二
1 | String a = "hello"; |
创建了几个对象? 3个
解读: 底层是 StringBuilder sb = new StringBuilder(); sb.append(a); sb.apped(b);
sb是在堆中, 并且append实在原来字符串的基础上追加的
String c1 = “ab” + “cd”;
(“ab”, “cd”为常量), 常量相加, 看的是池,
String c = a + b;
变量相加实在堆中 使用debug看源码
题三
答案: `hspand \n hava
1 | /** |
String类的常见方法
一
1 | /** |
二
1 | package chapter13.String; |
🌈三、StringBuffer类
基本介绍
java.lang.StringBuffer
代表可变的字符序列,可以对字符串内容进行增删- 很多方法和String相同, 但StringBuffer是可变长度的
- StringBuffer是一个容器
- StringBuffer是final类, 继承了抽象类AbstractStringBuilder类, AbstractStringBuilder类 属性
char[] value
,存放的字符序列 , 实现了Serializable接口,可以串行化 - Stringbuffer字符内容是存储在 父类的 char[] value, 所以变化(增加/删除)不用每次都跟换地址(即不是每次都创建新对象),因此销量高与String
String 和StringBuffer的比较
String保存的是字符串常量, 里面的值不能更改, 每次String类的更新实际上就是更改地址,效率比较低
peivate final char value[];
StringBuffer保存的是字符串常量, 里面的值可以更改, 每次StringBuffer的更新实际上可以更新内容,不用每次更改地址,效率较高
char[] value;
这个放在堆中
String和StringBuffer的互相转换
1 | /** |
StringBuffer类常见的方法
1 | package chapter13.stringbuffer; |
StringBuffer练习题
1 | /** |
题二: 输入商品名称和价格, 要求答应效果如下:
手机: 123456.69 处理后结果123,456.59 要求: 价格的小数点前面没三位与国内逗号隔开输出
1 | public class StringBufferExercise02 { |
🌈四、StringBuilder类
基本介绍
- StringBuilder一个可变的字符序列,此类提供一个与StringBuff 兼容的API, 但不保证同步(SringBuilder存在线程安全问题),该类被设计用作StringBuffer的一个建议替换,用在字符串缓冲区被单个线程使用的时候. 如果可能, 建议优先采用该类, 因为在大多数实现中, 它比StringBuffer要快
- 在StringBuilder上的主要操作是append和insert方法, 可重载这些方法,以接受任意类型的数据
- StringBuffer 的直接父类 是 AbstractStringBuilder, StringBuffer 实现了 Serializable, 即 StringBuffer 的对象可以串行化
- 在父类中 AbstractStringBuilder 有属性 char[] value,不是 final
该 value 数组存放 字符串内容,引出存放在堆中的 - 因为 StringBuffer 字符内容是存在 char[] value, 所有在变化(增加/删除)
不用每次都更换地址(即不是每次创建新对象), 所以效率高于 String
StringBuilder常用方法
StringBuilder和String方法类似,参考StringBuffer的方法
String/StringBuilder/StringBuffer的效率的比较
- StringBuilder和StringBuffer非常类似, 均代表可变的字符序列, 而且方法也一样
- String: 不可变字符序列, 效率低, 单是服用率高
- StringBuffer: 可变字符序列, 效率较高(增删),线程安全
- StringBuilder: 可变字符序列, 效率最高, 线程不安全
- 如果我们对String做大量的修改操作, 不要使用String
效率测试代码
1 | package chapter13.stringbuilder; |
结论
- 如果字符串存在大量的修改操作, 一般使用StringBuffer或StringBuilder
- 如果字符串存在大量的修改操作,并且在单线程的情况, 使用StringBuilder
- 如果字符串存在大量的修改操作,并且多线程的情况, 使用SringBuffer
- 如果我们字符串很少修改, 被多个对象引用, 使用String,比如配置信息
五、Math类
Math类 常用方法
1 | package chapter13.math; |
七、Array类
Array类的常用方法
基本介绍
Arrays里面包含一系列静态方法, 用于管理或操作数组(排序/搜索)
toString 返回数组的字符串形式
sort排序(自然排序和定制排序)
binarySearch方法, 通过二分搜索进行查找, 要求必须排序好
copyOf数组元素的复制
int index Arrays.binarySearch(arr,3);
fill数组元素的填充
equals比较两个数组元素的呢若能是否完全一致
asLIst将一组值, 转换成list
Arrays.sort()定制排序
1 | /** |
Array常用方法
1 | package chapter13.array; |
1 | package chapter13.array; |
八、System类
System类常用的方法
1 | package chapter13.system; |
九、BigInteger 和 BigDecimal 类
使用场景:
- BigInteger适合保存比较大的整形
- BigDecimal适合报春精度更高的浮点型
BigInteger 和 BigDecima常见方法
BigInteger的四则运算
1 | package chapter13.BigIntegerandBigDecima; |
BigDecima的运算
1 | package chapter13.BigIntegerandBigDecima; |
十、Date类
第一代日期类
节本介绍
- Date: 精确到毫秒, 代表特定的瞬间
- SimpleDateFormat: 格式和解析日期的类
案例使用
1 | package chapter13.date; |
第二代日期类
介绍
- 第二代日期类, 主要就是Calendar类(日历)
- Calendar类是一个抽象类, 他为特定瞬间与一组 YEAE/MONTH/DSY_OF_MONTH等日历字段之间的转换提供了一些方法, 并未日历字段替国内了一些方法
案例使用
1 | package chapter13.date; |
第三代日期类
基本介绍
第一代日期类和第二代日期类的不足分析:
JDK 1.0 中包含了一个java.util.Date类, 但是它的大说书方法已经在JDK 1.1 引入Calendar类之后被弃用了, 二Calendar也存在的问题是:
- 可变性: 想日期和时间这样的类应该是不可变的
- 偏移型: Date中的奶嫩嗯是从1900年开始的,二月份都从0开始
- 格式化: 格式化只对Date有用, Calendar则不行
- 此外, 他们也不是线程安全的; 不能处理润秒的(每隔两天,多出1s)
LocalDate类
LocalDate(日期/年月日) LocalTime(时间/时分秒) LocalDateTime(日期时间/年月日时分秒)在JDK8加入
LocalDate只包含时期, 可以获取日期字段
LocalTime只包含时间, 可以获取时间字段
LocalDateTIme包含日期 + 时间, 可以获取日期和时间字段
案例使用
1 | package chapter13.date; |
DateTimeFormatter 格式日期类
使用方式:
DateTImeFormat daf = DateTimeFormatter.ofPattern(格式);
String str = dtf.format(日期对象);
Instant时间戳
类似于一系列和Date类转换的方式
Instant —-> Date:
Date date = Date.from(instant)
Date —–> Instant:
Instant instant = date.toInstant();
案例使用
1 | package chapter13.date; |