文章目录
- Java基础的学习
- 1、
- 2、MS-DOS(Microsoft Disk Operating System)
- 命令提示符(cmd)
- 3、JRE和DJK
- 4、环境变量的配置
- 5、Java程序开发三步骤:编写、编译、运行[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QemFOnc4-1573821333002)(C:\Users\Think-Pad\Desktop\java\Java程序开发的三步骤.jpg)]
- 6、程序的注释
- 7、关键字的概念与特征
- 8、标识符(驼峰规则)
- 9、常量的概念与分类
- 10、常量的打印输出
- 11、基本数据类型(八种)
- 12、变量的概念与定义格式
- 13、变量的注意事项
- 14、数据类型转换
- 15、算数运算符-四则运算与取模运算
- 16、算数运算符
- 17、赋值运算符
- 18、比较运算符
- 19、逻辑运算符
- 20、三元运算符
- 21、方法入门——方法的调用
- 22、编译器的两点优化
- 第一章 流程控制
- 第二章 判断语句
- 第三章 选择语句
- 第四章 循环语句
- 第五章 IDEA的使用
- 第六章 方法
- 第七章 数组
- 第八章 Java中的内存划分
- 第九章 面向对象思想
- 第十章 API文档的使用
- 第十一章 字符串
- 第十二章 静态static关键字
- 第十三章 继承
- 第十四章 抽象
- 第十五章 接口
- 第十六章 多态
- 第十七章 final关键字
- 第十八章 内部类
- 第十九章 Object类
- 第二十章 包装类
Java基础的学习
成长的第二阶段
这是自己的第二阶段的学习,从2019-9-03开始学习,历经一个多月的时间,把 Java基础课程学习完毕,基本了解了 Java的面对对象编程的思想精髓,了解了Java中的类、接口的用法,这是一个漫长的过程,也是一个煎熬的过程,以后的学习任务也是任重而道远!
笔记太长,分了两次上传。
1、
位(bit):一个数字0或者一个数字1,代表一位。
字节(Byte):每逢8位是一个字节,这是数据存储的最小单位。
1 Byte = 8 bit
1 KB = 1024 Byte
1 MB = 1024 KB
1 GB = 1024 MB
1 TB = 1024 GB
1 PB = 1024 TB
1 EB = 1024 PB
1 ZB = 1024 EB
2、MS-DOS(Microsoft Disk Operating System)
命令提示符(cmd)
启动: Win+R,输出cmd回车
切换盘符 盘符名称:
进入文件夹 cd 文件夹名称
进入多级文件夹 cd 文件夹1\文件夹2\文件夹3
返回上一级 cd…
直接回根路径 cd \
查看当前内容 dir
清屏 cls
退出 exit
3、JRE和DJK
- JRE(Java Runtime Environment): 是Java程序的运行时环境,包含JVM和运行时所需的核心类库。
- JDK(Java Development Kit): 是Java程序开发工具包,包含JRE和开发人员使用的工具。
我们想要运行一个已有的Java程序,那么只需要安装JRE即可
我们想要开发一个全新的Java程序,那么必须安装JDK
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ohnBFLAe-1573821332897)(C:\Users\Think-Pad\Desktop\java\jdk安装步骤.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L1lTWyWO-1573821333000)(C:\Users\Think-Pad\Desktop\java\jdk安装步骤02.jpg)]
4、环境变量的配置
我的电脑右键打开属性 选择高级系统设置 环境变量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GLKDBZPl-1573821333001)(C:\Users\Think-Pad\Desktop\java\jdk安装步骤03.jpg)]
5、Java程序开发三步骤:编写、编译、运行[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QemFOnc4-1573821333002)(C:\Users\Think-Pad\Desktop\java\Java程序开发的三步骤.jpg)]
-
编写源代码
-
编译:cmd中
javac 类名称.java 回车
运行:java 类名称 回车
先编译成class文件,再运行java,运行的是class文件
6、程序的注释
单行注释://这是一行注释信息
多行注释:/*
这是多行注释
这是多行注释 */
也可以用来区块注释
public class HelloWorld{
public static void main(String[] args){
System.out.println(“Hello,World!”);
}
}
注意:* 源代码第一行的第三个单词必须和所有的文件名称完全一样,大小写也要一样
public class 后面代表定义一个类的名称,类是java当中所有源代码的基本组成单位
* 第二行的内容是万年不变的固定写法,代表main方法
这一行代表程序执行的起点(从main开始)
* 第三行代表打印输出语句(其实就是屏幕显示)
希望显示什么东西,就在小括号中填写什么东西
7、关键字的概念与特征
关键字的特点:
- 完全小写字母
- 在增强版的记事本当中有特殊颜色
8、标识符(驼峰规则)
标识符是用来给变量、类、包以及方法来命名的。
** 命名规则:
- 标识符可以包含 英文字母26个(区分大小写)、0-9数字、$(美元符号)和下划线
- 标识符不能以数字开头
- 标识符不能是关键字
** 命名规范:
- 类名规范:首字母大写,后面每个单词首字母大写(大驼峰式)HelloWorld
- 变量名规范:首字母小写,后面每个单词首字母大写(小驼峰式)helloWorld
- 方法名规范:同变量名
9、常量的概念与分类
常量:在程序运行期间,固定不变的量
常量的分类:
1.字符串常量:凡是用双引号引起来的部分,叫做字符串常量。例如:“abc”、“Hello”、“1213”
2.整数常量:直接写上的数字,没有小数点。例如:100、200、0、-250
3.浮点型常量:直接写上的数字,有小数点。例如:2.5、-3.14、0.0
4.字符型常量:凡是用单引号引起来的单个字符,就叫做字符常量。例如:‘A’、‘b’、’中‘
5.布尔常量:只有量中取值 true、false
6.空常量:null 代表没有任何数据。
10、常量的打印输出
- 字符串两个引号之间可以为空
- 字符型常量中两个引号中间必须有且仅有一个字符,没有不行,有两个也不行
- 空常量不能直接用来打印输出
11、基本数据类型(八种)
第一类(字符型):char
第二类(布尔型):boolean
第三类(数值类型):
整数型:byte short int long
浮点型:float double
引用数据类型:
字符型、数组、类、接口、Lambda
注意事项:
-
字符串不是基本类型,而是引用类型。
-
浮点型可能只是一个近似值,并非精确的值
-
数据范围与字节数不一定相关,例如float数据范围比long更广泛,但是float是4字节,long是8字节
-
浮点数当中默认类型是double,如果一定要使用float类型,需要加上一个后缀F
如果是整数,默认为int类型,如果一定要使用long类型,需要加上一个后缀L
推荐使用大写字母后缀
12、变量的概念与定义格式
变量:程序运行期间,内容可以发生改变的量
创建一个变量并使用的格式: 数据类型 变量名称
赋值: 变量名称 = 数据值
一步到位的格式: 数据类型 变量名称 = 数据值
13、变量的注意事项
使用变量的时候,有一些注意事项:
- 如果创建多个变量,那么变量之间的名称就不可能重复
- 对于float和long类型来说,字母后缀F和L不要丢掉
- 如果使用byte或者short类型来说,那么右侧的数据不能超过左侧类型的范围
- 没有进行赋值的变量,不能直接使用;一定要赋值后才能使用
- 变量使用不能超过作用域的范围 【作用域】:从定义变量的一行开始,一直到直接所属的大括号结束为止
- 可以通过一个语句来创建多个变量,但是一般情况下不推荐这么写
14、数据类型转换
当数据类型不一样时,将会发生数据类型转换
自动类型转换(隐式)
1. 特点:代码不需要进行特殊处理,自动完成
2. 规则:数据范围从小到大
强制类型转换(显式)
-
特点:代码需要进行特殊转换的格式,不能自动完成
-
格式:范围小的类型 范围小的变量名 = (范围小的类型) 原本范围大的数据
注意事项:
- 强制类型转换不推荐使用,因为有可能发生精度损失、数据溢出
- byte/short/char这三种类型都可以发生数字运算,例如加法“+”
- char类型参与运算时按照ASCII码进行运算 48-‘0’ 65-‘A’ 97-'a’
- boolean类型不能发生数据转换(也不能按照0和1)
15、算数运算符-四则运算与取模运算
运算符:进行特定操作的符号,例如:+
表达式:用运算符连起来的式子叫做表达式。例如:20 + 5 a + b
四则运算:
加:+
减:-
乘:*
除:/
取模(取余数):%
首先计算得到表达式的结果,然后再打印输出这个结果
被除数 / 除数 = 商 … 余数
对于一个整数的表达式来说,除法用的是整除,整数除以整数,结果仍然是整数,只看商,不看余数
只有对于整数的除法来说,取模运算符才有余数的意义
注意事项:
1. 一旦运算符当中有不同类型的数据,那么结果将会是数据类型范围大的那种
16、算数运算符
加号的多种用法:
四则运算当中的加号“+”有常见的三种用法:
1.对于数值来说,那就是加法
2.对于字符char类型来说,在计算之前,char会被提升成为int,然后再计算
char类型字符和int类型字符之间的对照关系表:ASCII、Unicode
3.对于字符串String(首字母大写,并不是关键字)来说,加号代表字符串连接操作
任何数据类型和字符串进行连接的时候,结果都会变成字符串
自增自减运算符:
自增运算符:++
自减运算符:–
基本含义:让一个变量涨一个数字1,或者让一个变量降一个数字1
使用格式:写在变量名称之前,或者写在变量名称之后。例如:++num,也可以num++
使用方式:
-
单独使用:不和其他任何操作混合,自己独立成为一个步骤。
-
混合使用:和其他操作混合,例如与赋值混合,或者与打印操作混合,等。
使用区别:
-
在单独使用的时候,前++和后++没有任何区别,也就是:++num;和num++;完全一样的。
-
在混合的时候,有【重大区别】
A. 如果是【前++】,那么变量【立刻马上+1】,然后拿着结果进行使用。 【先加后减】
B. 如果是【后++】,那么首先使用变量本来的数值,【然后再让变量+1】。 【先用后加】
注意事项:
只有变量才能使用自增、自减运算符。常量不可能发生改变,所以不能用。
-
17、赋值运算符
赋值运算符分别为:
基本赋值运算符:就是一个等号“=”,代表将右侧的数据交给左侧的变量。
int a = 30;
复合赋值运算符:
+= a += 3 相当于 a = a + 3
-= b -= 4 相当于 b = b - 4
*= c *= 5 相当于 c = c * 5
/= d /= 6 相当于 d = d / 6
%= e %= 7 相当于 e = e % 7
注意事项:
- 只有变量才能使用赋值运算符,常量不能进行赋值。
- 复合赋值运算符其中隐含了一个强制类型转换。
18、比较运算符
比较运算符:
大于: >
小于: <
大于等于: >=
小于等于: <=
相等: == 【两个等号连写才相等,一个等号代表的是赋值】
不相等: !=
注意事项:
-
比较运算符的结果一定是一个boolean值,成立就是true,不成立就是false
-
如果进行多次判断,不能连着写
数学当中的写法,例如:1 < x < 3
程序当中**【不允许】**这种写法
19、逻辑运算符
与(并且) && 全部是true,才是true;否则就是false
或(或者) || 至少有一个是true,就是true;全部是false,才是false
非(取反) ! 本来是true,变成false;本来是false,变成true
与“&&”,或“||”,具有短路效果:如果根据左边已经可以判断得到最终结果,那么右边的代码将不再执行,从而节省一定的性能
注意事项:
-
逻辑运算符只能用于boolean值
-
与、或需要左右各自有一个boolean值,但是取反只要有唯一的一个boolean值即可
-
与、或两种运算符,如果有多个条件,可以连续写
两个条件:条件A && 条件B
多个条件:条件A && 条件B && 条件C
TIPS:
对于 1 < x < 3的情况,应该拆成两个部分,然后使用与运算符连接起来:
int x = 2;
1 < x && x<3
20、三元运算符
一元运算符:只需要一个数据就可以进行操作的运算符。例如:取反!、自增++、自减–
二元运算符:需要两个数据才可以进行操作的运算符。例如:加法+ 、赋值 =
三元运算符:需要三个数据才可以进行操作的运算符。
**格式:**数据类型 变量名称 = 条件判断 ? 表达式A : 表达式B;
流程:
首先判断条件是否成立:
如果成立为true,那么将表达式A的值赋值给左侧的变量;
如果不成立为false,那么将表达式B的值给做左侧的变量;
二者选择其一。
注意事项:
- 必须同时保证表达式A和表达式B都符合左侧数据类型的要求
- 三元运算符的结果必须被使用
21、方法入门——方法的调用
定义一个方法的格式:
public static viod 方法名称(){
方法体;
}
方法名称的命名规则和变量一样,使用小驼峰。
方法体:也就是大括号当中可以包含任意条语句。
注意事项:
-
方法定义的先后顺序无所谓。
-
方法的定义不能产生嵌套包含关系。
-
方法定义好了之后,不会执行的。如果要想执行,一定要进行方法的【调用】。
如何调用方法,格式:
方法名称();
22、编译器的两点优化
对于byte/short/char三种类型来说,如果右侧赋值的数值没有超过范围,那么javac编译器将会自动隐含地为我们补上一个(byte)(short)(cahr)。
1.如果没有超过左侧的范围,编译器补上强转。
-
如果右侧超过了左侧范围,那么直接编译器报错。
在给变量进行赋值的时候,如果右侧的表达式当中全部是常量,没有任何变量,那么编译器javac将会直接将若干个常量表达式计算得到结果。
short result = 13;
右侧的常量结果取值,没有超过左侧的范围,所以正确。
这称为“编译器的常量优化”。
但是注意: 一旦表达式当中有变量参与,那么就不能进行这种优化了。
第一章 流程控制
1.1 根据编写顺序,从上往下执行,按顺序执行
1.2 顺序结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qP8Mg74r-1573821333004)(C:\Users\Think-Pad\Desktop\java\顺序结构.jpg)]
第二章 判断语句
2.1 判断语句1—— if语句
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oLC01oso-1573821333005)(C:\Users\Think-Pad\Desktop\java\if语句.jpg)]
2.2 判断语句2—— if…else语句
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mVRK0ZuT-1573821333006)(C:\Users\Think-Pad\Desktop\java\if-else语句.jpg)]
2.3 判断语句3—— if…else if…else
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KwDWrKCt-1573821333053)(C:\Users\Think-Pad\Desktop\java\if…else if…else语句.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1zo0sIqp-1573821333055)(C:\Users\Think-Pad\Desktop\java\if…else if…else语句 .jpg)]
第三章 选择语句
3.1 选择语句—— switch语句
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4ZGphu8A-1573821333056)(C:\Users\Think-Pad\Desktop\java\switch语句.jpg)]
最后一个break可以省略,但是强烈不建议省略!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-elD38L8W-1573821333057)(C:\Users\Think-Pad\Desktop\java\switch语句 .jpg)]
3.2 case的穿透性
switch语句使用的注意事项:
-
多个case后面的数值不可以重复。
-
switch后面小括号当中只能是下列数据类型:
基本数据类型:byte/short/cahr/int
引用数据类型:String字符串、enum枚举
- switch语句格式可以很灵活:前后顺序可以颠倒,而且break语句还可以省略。
“匹配哪一个case就从哪一个位置向下执行,直到遇到了break或者整体结束为止。”
第四章 循环语句
4.1 循环概念
循环结构的基本组成部分,一般可以分成四部分:
- 初始化语句:在循环开始最初执行,而且只做唯一 一次。
- 条件判断:如果成立,则循环继续,如果不成立,则循环退出。
- 循环体:重复要做的事情内容,若干行语句。
- 步进语句:每次循环之后都要执行的扫尾工作,每次循环之后都要执行一次。
4.2 循环语句1—— for循环
for(初始化表达式;布尔表达式;步进表达式){
循环体;
}
4.3 循环语句2—— while
while循环有一个标准格式,还有一个扩展模式。
标准格式:
while(条件判断){
循环体
}
扩展格式:
初始化语句;
while(条件判断){
循环体;
步进语句;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rVb9uHDx-1573821333058)(C:\Users\Think-Pad\Desktop\java\循环结构.jpg)]
4.4 循环语句3—— do…while
do-while循环的标准格式:
do{
循环体
}while(条件判断);
初始化语句:
do{
循环体
步进语句
}while(条件判断);
4.5 循环语句的区别
三种循环的区别:
- 如果条件从来没有满足过,那么for循环和while循环将会执行0次,但是do-while循环会执行至少一次。
- for循环的变量在小括号当中定义,只有循环内部能用。while循环和do-while循环初始化语句本来就在外面,所以出来循环之后还可以继续使用。
4.6 跳出语句 break continue
break关键字的用法有常见的两种:
-
可以用在switch语句当中,一旦执行,整个switch语句立刻结束。
-
还可以用在循环语句中,一旦执行,整个循环语句立刻结束。打断循环。
关于循环的选择,有一个小建议:
凡是次数确定的场景多用for循环,否则多用while循环。
continue关键字:
另一种循环控制语句是continue关键字。
一旦执行,立刻跳过当前次数循环剩余内容,马上开始下一次循环。
死循环:
永远停不下来的循环,叫做死循环。
死循环的标准格式:
while(ture){
循环体
}
第五章 IDEA的使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Uka9Fym3-1573821333059)(C:\Users\Think-Pad\Desktop\java\IDEA常用的快捷键.jpg)]
第六章 方法
6.1 方法的定义格式
方法其实就是若干语句的功能集合。
方法好比是一个工厂。
参数(原料):就是进入方法的数据。
返回值(产出物):就是从方法中出来的数据。
定义方法的完整格式:
修饰符 返回类型值 方法名称(参数类型 参数名称,…){
方法体
return 返回值;
}
修饰符:现阶段的固定写法,public static
返回值类型:也就是方法最终产生的数据结果是什么类型
方法名称:方法的名字,规则和变量一样,小驼峰
参数类型:进入方法的数据是什么类型
参数名称:进入方法的数据对应的变量名称
ps:参数如果有多个,使用逗号分离
方法体:方法需要做的事,若干行代码
return:两个作用,第一停止当前方法,第二将后面的返回值还给调用处
返回值:也就是方法执行后最终产生的数据结果
注意:return后面的“返回值”,必须和方法名称前面的“返回值类型”,保持对应
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-McAnLrM5-1573821333061)(C:\Users\Think-Pad\Desktop\java\实例.jpg)]
6.2 方法的三种调用格式
方法的三种调用格式:
- 单独调用:方法名称(参数);
- 打印调用:System.out.println(方法名称(参数));
- 赋值调用:数据类型 变量名称 = 方法名称(参数);
注意:此前学习的方法,返回值类型固定写为void,这种写法只能够单独使用,不能进行打印调用或者赋值调用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j05dD9vb-1573821333062)(C:\Users\Think-Pad\Desktop\java\实例.jpg)]
6.3 对比有参数和无参数
有参数:小括号当中有内容,当一个方法需要一些数据条件,才能完成任务时,就是有参数。
例如有两个数字相加,必须知道两个数字各自是多少,才能相加。
无参数:小括号当中留空,一个方法不需要任何数据条件,自己就能独立完成任务,就是无参数。
例如定义一个方法,打印固定10次HelloWorld。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eipd4K6O-1573821333078)(C:\Users\Think-Pad\Desktop\java\对比有无参数.jpg)]
6.4 对比有返回值和无返回值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zCu530pX-1573821333079)(C:\Users\Think-Pad\Desktop\java\对比有无返回值.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LKgeIrT7-1573821333080)(C:\Users\Think-Pad\Desktop\java\实例01.jpg)]
错误写法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WpvVNyXA-1573821333081)(C:\Users\Think-Pad\Desktop\java\错误写法.jpg)]
6.5 练习题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NvQpDNuD-1573821333082)(C:\Users\Think-Pad\Desktop\java\1到100累加.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8uWZ5YeJ-1573821333083)(C:\Users\Think-Pad\Desktop\java\打印指定次数的HelloWorld.jpg)]
方法的注意事项:
使用方法的时候,注意事项:
- 方法应该定义在类当中,但是不能在方法当中再定义方法,不能嵌套。
- 方法定义的前后顺序无所谓。
- 方法定义之后不会执行,如果希望执行,一定要调用:单独调用、打印调用、赋值调用。
- 如果方法有返回值,那么必须写上“return 返回值”,不能没有。
- return后面的返回值数据,必须和方法的返回值类型对应起来。
- 对于一个void没有返回值的方法,不能写return后面的返回值,只能写return自己。
- 对于void方法当中最后一行的return可以省略不写。
- 一个方法当中可以有多个return语句,但是必须保证同时只有一个被执行到 ,两个return不能连写。
方法重载的基本使用:
对于功能类似的方法来说,因为参数列表不一样,却需要记住那么多不同的方法名称,太麻烦。
方法的重载(Overload):多个方法的名称一样,但是参数列表不一样。
好处:只需要记住唯一一个方法名称,就可以实现类似的多个功能。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZCJ6oOXE-1573821333085)(C:\Users\Think-Pad\Desktop\java\方法的重载.jpg)]
方法的重载与下列因素相关:
- 参数个数不同
- 参数类型不同
- 参数的多类型顺序不同
方法重载与下列因素无关:
- 与参数的名称无关
- 与方法的返回值类型无关
println就是一个重载
第七章 数组
7.1 数组的概念
数组的概念:是一种容器,可以同时存放多个数据值。
数组的特点:
- 数组是一种引用数据的类型
- 数组当中的多个数据类型必须统一
- 数组的长度在程序运行期间不可改变
7.2 数组的定义格式
数组的初始化:在内存中建立一个数组,并且向其中赋予一些默认值。
两种常见的初始化方式:
- 动态初始化(指定长度):在创建数组的时候,直接指定数组当中的数据元素的个数。
- 静态初始化(指定内容):在创建数组的时候,不直接指定数据个数多少,而是直接将具体的数据内容进行指定。
动态初始化数组的格式:
数据类型[ ] 数组名称 = new 数据类型[数组长度];
解析含义:
左侧数据类型:也就是数组当中保存的数据,全部是统一的什么类型
左侧的中括号:代表我是一个数组
左侧的数组名称:给数组取一个名字
右侧的new:代表创建数组的动作
右侧数据类型:必须和左边的数据类型保持一致
右侧中括号的长度:也就是数组当中,到底可以保存多少个数据,是一个int数字
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1w70zd1v-1573821333086)(C:\Users\Think-Pad\Desktop\java\数组的定义.jpg)]
静态初始化基本格式:
数据类型[ ] 数组名称 = new 数据类型[ ]{ 元素1,元素2,…};
注意事项:
虽然静态初始化没有直接告诉长度,但是根据大括号里面元素的具体内容,也可以自动推算出来长度。
静态初始化省略格式:
数据类型[ ] 数组名称 = { 元素1,元素2,…};
注意事项:
- 静态初始化没有直接指定长度,但是仍然会自动推算得到长度。
- 静态初始化标准格式可以拆分成为两个步骤。
- 动态初始化也可以拆分成两个步骤。
- 静态初始化一旦使用省略格式,就不能拆分成两个步骤了。
使用建议:
如果不确定数组当中的具体内容,用动态初始化;否则,已经确定了具体的内容,用静态初始化。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NrwHe0xV-1573821333087)(C:\Users\Think-Pad\Desktop\java\数组初始化.jpg)]
7.3 访问数组元素进行获取
直接打印数组名称,得到的是数组对应的:内存地址哈希值。
二进制:01
十进制:0123456789
16进制:0123456789adcdef
访问数组元素的格式:数组名称【索引值】
索引值:就是一个int数字,代表数组当中的编号 。
注意:索引值从0开始,一直到“数组的长度-1”为止。
7.4 访问数组元素进行赋值
使用动态初始化数组时候,其中的元素将会自动拥有一个默认值。规则如下:
如果是整数类型,那么默认值为0
如果是浮点类型,那么默认值为0.0
如果是字符类型,那么默认值为’\u0000’
如果是布尔类型,那么默认值为false
如果是引用类型,那么默认值为null
注意事项:
静态初始化其实也有默认值的过程,只不过系统自动马上将默认值替换成为了大括号当中的具体数值。
第八章 Java中的内存划分
8.1 Java的内存需要划分成为5个部分
-
栈(Stack):存放的都是方法中的局部变量。方法的运行一定要在栈当中运行。
局部变量:方法的参数,或者是方法{}内部的变量
作用域:一旦超出作用域,立刻从栈内存当中消失
- 堆(Heap):凡是new出来的东西,都在堆当中。
堆里面的东西都有一个地址值:16进制
堆内存里面的数据,都有默认值。规则:
如果是整数类型,那么默认值为0
如果是浮点类型,那么默认值为0.0
如果是字符类型,那么默认值为’\u0000’
如果是布尔类型,那么默认值为false
如果是引用类型,那么默认值为null
- 方法区(Method Area):存储.class相关信息,包含方法的信息。
- 本地方法栈(Nation Method Stack):与操作系统相关。
- 寄存器(pc Register):与cpu相关 。
8.2 一个数组的内存图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AWEs2AuS-1573821333088)(C:\Users\Think-Pad\Desktop\java\一个数组的内存图.jpg)]
8.3 两个引用指向同一个数组的内存
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kKoxNZvA-1573821333089)(C:\Users\Think-Pad\Desktop\java\两个引用指向同一个数组的内存.jpg)]
8.4 数组索引越界异常
数组的索引编号从0开始,一直到“数组的长度-1”为止。
如果访问数组元素的时候,索引编号并不存在,那么将会发生数组索引越界异常
8.5 空指针异常
所有的引用类型变量,都可以赋值为一个null值,但是代表其中什么都没有。
数组必须进行new初始化才能使用其中的元素。
如果只是赋值了一个null,没有进行new创建,那么将会发生空指针异常。
8.6 获取数组的长度
获取数组的长度,格式:
数组名称.length
这将会得到一个int数字,代表数组的长度。
数组一旦创建,程序运行期间,长度不可变。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Q8wx2GQ-1573821333270)(C:\Users\Think-Pad\Desktop\java\获取数组的长度.jpg)]
8.7 数组的遍历输出
遍历数组,就是说对数组当中每一个元素进行逐一、挨个儿处理。默认的处理方式就是打印输出。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bDpZszHX-1573821333279)(C:\Users\Think-Pad\Desktop\java\求出数组中的最值.jpg)]
8.8 数组元素反转
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ukIJyBAZ-1573821333321)(C:\Users\Think-Pad\Desktop\java\数组元素反转.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vaHbaQjp-1573821333323)(C:\Users\Think-Pad\Desktop\java\数组元素反转 .jpg)]
8.9 数组作为方法参数
数组可以作为方法参数。
当调用方法的时候,向方法的小括号进行传参,传递进去的其实是数组的地址值。
8.10 数组作为方法返回值
一个方法可以有0、1、多个参数,但是只能有0或者1个返回值,不能有多个返回值。
如果希望一个方法当中产生了多个结果数据进行返回,怎么办?
解决方案:使用一个数组作为返回值类型即可。
任何数据类型都能作为方法的参数类型,或者返回值类型。
数组作为方法的参数,传递进去的其实是数组的地址值。
数组作为方法的返回值,返回的其实也是数组的地址值。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nZZCb8ja-1573821333333)(C:\Users\Think-Pad\Desktop\java\数组作为返回值.jpg)]
第九章 面向对象思想
9.1 面向对象思想的概念
面向过程:当需要实现一个功能的时候,每一个具体的步骤都要亲力亲为,详细处理每一个细节。
面向对象:当需要实现一个功能的时候,不关心具体的步骤,而是找一个已经具有该功能的人,来帮我做事儿。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hUbNu56c-1573821333335)(C:\Users\Think-Pad\Desktop\java\面向对象.jpg)]
9.2 类和对象
-
类: 是一组相关属性和行为的集合。可以看成是一类事物的模板,使用事物的属性特征和行为特征来描述该类事物。
-
**属性:**就是该事物的状态信息。
-
**行为:**就是该事物能够做什么。
-
**对象:**是一类事物的具体体现。对象是类的一个实例,必然具备该类事物的属性和行为。
类与对象的关系:
- 类是对一类事物的描述,是抽象的。
- 对象是一类事物的实例,是具体的。
- 类是对象的模板,对象是类的实体。
9.3 类的定义
成员变量(属性):
String name;// 姓名
int age; // 年龄
成员方法(行为);
public void eat(){} // 吃饭
public void sleep(){} // 睡觉
public void study(){} // 学习
注意事项:
- 成员变量是直接定义在类当中的,在方法外边。
- 成员方法不要写static关键字。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QzNNrGs8-1573821333336)(C:\Users\Think-Pad\Desktop\java\类的定义.jpg)]
9.4 对象的创建及其使用
通常情况下,一个类并不能直接使用 ,需要根据类创建一个对象,才能使用。
-
**导包:**也就是指出需要使用的类在什么位置。
import 包名称.类名称;
import cn.Demo;
对于和当前类属于同一个包的情况,可以省略导包语句不写。
- **创建,**格式:
类名称 对象名 = new 类名称();
Student stu = new Student();
- **使用,**分为两种情况:
使用成员变量:对象名.成员变量名
使用成员方法:对象名.成员方法名(参数)
(也就是,想用谁,就用对象名点儿谁。)
注意事项:
如果成员变量没有进行赋值,那么将会有一个默认值,规则和数组一样。
9.5 一个对象的内存图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oW3PMHv8-1573821333337)(C:\Users\Think-Pad\Desktop\java\一个对象的内存图.jpg)]
9.6 两个对象使用同一个方法的内存图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wwbhK9Sg-1573821333339)(C:\Users\Think-Pad\Desktop\java\两个对象使用同一个方法的内存图.jpg)]
9.7 两个引用指向同一个对象的内存图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jj5d6GWk-1573821333340)(C:\Users\Think-Pad\Desktop\java\两个引用指向同一个对象的内存图.jpg)]
9.8 使用对象类型作为方法的参数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LfgWVYKU-1573821333342)(C:\Users\Think-Pad\Desktop\java\使用对象类型作为方法的参数.jpg)]
9.9 使用对象类型作为方法的返回值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9rtsWsez-1573821333343)(C:\Users\Think-Pad\Desktop\java\使用对象类型作为方法的返回值.jpg)]
9.10 局部变量和成员变量的区别
-
定义的位置不一样【重点】
局部变量:在方法的内部
成员变量:在方法的外部,直接写在类当中
- 作用范围不一样【重点】
局部变量:只有方法当中才能使用,出了方法就不能用
成员变量:整个类都可以通用
- 默认值不一样【重点】
局部变量:没有默认值,如果要想使用,必须手动进行赋值
成员变量:如果没有赋值,会有默认值,规则和数组一样
- 内存的位置不一样(了解)
局部变量:位于栈内存
成员变量:位于堆内存
- 生命周期不一样(了解)
局部变量:随着方法进栈而诞生,随着方法出栈而消失
成员变量:随着对象创建而诞生,随着对象被垃圾回收而消失
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UMTST6jl-1573821333344)(C:\Users\Think-Pad\Desktop\java\成员变量和局部变量的区别.jpg)]
9.11 面向对象三大特征之封装
面向对象三大特征:封装、继承、多态。
封装性在Java当中的体现:
- 方法就是一种封装
- 关键字private也是一种封装
封装就是将一些细节信息隐藏起来 ,对于外界不可见
9.12 private关键字的作用
问题描述:定义person的年龄时,无法阻止不合理的数值被设置进来。
解决方案:用private关键字将需要保护的成员进行修饰。
一旦使用了private进行修饰,那么本类当中仍然可以随意访问。
但是!超出了本类范围之外就不能再直接访问了。
间接访问private成员变量,就是定义一对儿getter/setter方法
必须叫setXxx或者是getXxx命名规则。
对于getter来说,不能有参数,返回值类型和成员变量对应;
对于setter来说,不能有返回值,参数类型和成员变量对应 。
对于基本类型当中的Boolean值,getter方法一定要写成isXxx的形式,而setXxx规则不变。
9.13 this关键字的作用
当方法的局部变量和类的成员变量重名的时候,根据**“就近原则”**,优先使用局部变量。
如果需要访问本类当中的成员变量,需要使用格式:
this.成员变量名
“通过谁调用的方法,谁就是this”
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PbQFOytV-1573821333345)(C:\Users\Think-Pad\Desktop\java\this关键字02.jpg)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GsmoBAOC-1573821333410)(C:\Users\Think-Pad\Desktop\java\this关键字01.jpg)]
9.14 构造方法
构造方法是专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法。
格式:
public 类名称(参数类型 参数名称){
方法体;
}
注意事项:
-
构造方法的名称必须和所在的类名称完全一样,就连大小写也要一样。
-
构造方法不要写返回值类型,连void都不写。
-
构造方法不能return一个具体的返回值。
-
如果没有编写任何构造方法,那么编译器将会默认赠送一个构造方法,没有参数、方法体什么事儿都不做。
public Student(){}
- 一旦编写了至少一个构造方法,那么编译器将不再赠送。
- 构造方法也是可以进行重载的。
重载:方法名称相同,参数列表不同。
9.15 定义一个标准的类
一个标准的类通常要拥有下面四个组成部分:
-
所有的成员变量都要使用private关键字修饰
-
为每一个成员变量编写一对儿getter/setter方法
-
编写一个无参数的构造方法
-
编写一个全参数的构造方法
这样标准的类也叫做Java Bean
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1FJAvtle-1573821333412)(C:\Users\Think-Pad\Desktop\java\一个标准的类.jpg)]
第十章 API文档的使用
10.1 Scanner的使用步骤
Scanner类的功能:可以实现键盘输入数据到程序中。
引用类型的一般使用步骤:
-
导包
import 包路径.类名称;
import java.util.Scanner;
如果需要使用的目标类和当前类位于同一个包下,则可以省略导包语句不写。
只有Java.lang包下的内容不需要导包,其他的包都需要import语句。
- 创建
类名称 对象名 = new 类名称();
- 使用
对象名.成员方法名()
获取键盘输入的一个int数字;int num = sc.nextInt();
获取键盘输入的一个字符串:String str = sc.next();
10.2 匿名对象
匿名对象就是只有右边的对象,没有左边的名字和赋值运算符。
new 类名称();
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wSlUxXAV-1573821333413)(C:\Users\Think-Pad\Desktop\java\使用匿名对象.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-giyEek46-1573821333414)(C:\Users\Think-Pad\Desktop\java\使用匿名对象 .jpg)]
10.3 Random概念和基本使用
Random类用来生成随机数字。使用起来也是三个步骤:
-
导包
import java.util.Random;
- 创建
Random r = new Random(); // 小括号当中留空即可
- 使用
获取一个随机的int数字(范围是int所有范围,有正负两种);int num = r.nextInt();
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QVIFcey7-1573821333415)(C:\Users\Think-Pad\Desktop\java\生成Random随机数.jpg)]
生成指定范围的随机数 :
获取一个随机的int数字(参数代表了范围,左闭右开区间):int num = r.nextInt(3);
实际上代表的含义是:[0,3),也就是0~2
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pk018w6n-1573821333419)(C:\Users\Think-Pad\Desktop\java\Random生成指定范围随机数.jpg)]
生成1~n 之间是随机数:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VmY39ygW-1573821333421)(C:\Users\Think-Pad\Desktop\java\Random生成随机数 .jpg)]
10.4 猜数字游戏
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YdPezW0P-1573821333423)(C:\Users\Think-Pad\Desktop\java\猜数字游戏01.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0ae6ao3d-1573821333424)(C:\Users\Think-Pad\Desktop\java\猜数字游戏02.jpg)]
10.5 对象数组
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gnRyFQi2-1573821333426)(C:\Users\Think-Pad\Desktop\java\对象数组.jpg)]
10.6 ArrayList集合概述和基本使用
数组的长度不可以发生改变。
但是ArrayList集合的长度是可以随意变化的。
对于ArrayList来说,有一个尖括号代表泛型。
泛型:也就是装在集合当中的所有元素,全都是统一的什么类型。
注意:泛型只能是引用类型,不能是基本类型。
注意事项:
对于ArrayList集合来说,直接打印得到的不是地址值,而是内容。
如果内容为空,得到的是空的中括号:[ ]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6xbFQDWF-1573821333427)(C:\Users\Think-Pad\Desktop\java\ArrayList的使用.jpg)]
10.7 ArrayList集合的常用方法和遍历
ArrayList当中的常用方法有:
**public boolean add( E e)😗*向集合当中添加元素,参数的类型和泛型一致。返回值代表添加是否成功。
备注:对于ArrayList 集合来说,add添加动作一定是成功的,所以返回值可用可不用。
但是对于其它集合(今后学习)来说,add添加动作不一定成功。
**public E get (int index)😗*从集合当中获取元素,参数是索引编号,返回值就是对应位置的元素。
public E remove(int index): 从集合当中删除元素,参数是索引值编号,返回值就是被删除掉的元素。
public int size(): 获取集合的尺寸长度,返回值是集合中包含的元素个数。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xsaAOGBY-1573821333429)(C:\Users\Think-Pad\Desktop\java\ArrayList常用方法.jpg)]
ArrayList集合的遍历:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FKERU0Wt-1573821333430)(C:\Users\Think-Pad\Desktop\java\ArrayList集合的遍历.jpg)]
10.8 ArrayList集合存储基本数据类型
如果希望向集合ArrayList当中存储基本数据类型,必须使用基本类型对应的“包装类”。
泛型只能是引用类!
基本类型 包装类(引用类型,包装类都位于java.lang包下)
byte Byte
short Short
int Integer 【特殊】
long Long
float Float
double Double
char Character 【特殊】
boolean Boolean
从 JDK1.5+ 开始,支持自动装箱、自动拆箱。
自动装箱:基本类型 – > 包装类型
自动拆箱:包装类型 – > 基本类型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2wawzNHB-1573821333432)(C:\Users\Think-Pad\Desktop\java\ArrayList储存基本数据类型.jpg)]
10.9 ArrayList练习
1.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PYq7jkxv-1573821333434)(C:\Users\Think-Pad\Desktop\java\ArrayList练习.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zS7v3Gna-1573821333435)(C:\Users\Think-Pad\Desktop\java\ArrayList练习01.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OZjYaMzk-1573821333437)(C:\Users\Think-Pad\Desktop\java\ArrayList练习01 .jpg)]
第十一章 字符串
11.1 字符串的概念和特点
java.lang.String类代表字符串。
API当中说:Java程序中的所有字符串字面值(如"abc")都作为此类的实例实现。
其实就是说:程序当中所有的双引号字符串,都是String类对象。(就算是没有new,也照样是。)
字符串的特点:
- 字符串的内容永不可变。【重点】
- 正是因为字符串不可改变,所以字符串是可以共享使用的。
- 字符串效果上相当于是char[ ]字符数组,但是底层原理是byte[ ]字节数组。
创建字符串的常见3+1种方式。
三种构造方法:
public String(): 创建一个空白字符串,不含任何内容。
public String(char[ ] array): 根据字符数组的内容,来创建对应的字符串。
public String(byte[ ] array): 根据字节数组的内容,来创建对应的字符串。
一种直接创建:
String str = “Hello”; // 右边直接用双引号
注意:直接写上双引号,就是字符串对象。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YleQ7hnS-1573821333438)(C:\Users\Think-Pad\Desktop\java\字符串.jpg)]
11.2 字符串的常量池
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iEEyWFWq-1573821333440)(C:\Users\Think-Pad\Desktop\java\字符串的常量吃池.jpg)]
11.3 字符串的比较相关方法
== 是进行对象的地址值比较,如果确实需要字符串的内容,可以使用两个方法:
public boolean aquals(Object obj): 参数可以是任何对象,只有参数是一个字符串并且内容相同的才会给true;否则返回false。
注意事项:
-
任何对象都能用Object进行接收。
-
equals方法具有对称性,也就是 a.equals(b)和b.equals(a) 效果一样。
-
如果比较双方一个常量一个变量,推荐把常量字符串写在前面。
推荐:“abc”.equals(str) 不推荐:str.equals(“abc”)
public boolean equalsIgnoreCase(String str): 忽略大小写,进行内容比较。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6lfjBqiI-1573821333441)(C:\Users\Think-Pad\Desktop\java\字符串比较.jpg)]
11.4 字符串的获取相关方法
String 当中与获取相关的常用方法有:
public int length(): 获取字符串当中含有的字符个数,拿到字符串长度。
public String concat(String str): 将当前字符串和参数字符串拼接成为返回值新的字符串 。
public char charAt(int index): 获取指定索引位置的单个字符。(索引从0开始。)
public int indexof(String str): 查找参数字符串在本字符串当中首次出现的索引位置,如果没有返回 -1 值。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w00jRZUe-1573821333442)(C:\Users\Think-Pad\Desktop\java\字符串 .jpg)]
11.5 字符串的截取方法
public String substring(int index): 截取从参数位置一直到字符串末尾,返回新字符。
public String substring(int begin, int end): 截取从begin开始,一直到end结束,中间的字符串。
备注: [begin,end), 包含左边,不包含右边。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ijscpedn-1573821333444)(C:\Users\Think-Pad\Desktop\java\字符串的截取方法.jpg)]
11.6 字符串的转换相关方法
String当中与转换相关的常用方法有:
public char[ ] toCharArray(): 将当前字符串拆分成为字符数组作为返回值。
public byte[ ] getByte(): 获取当前字符串底层的字节数组。
public String replace(CharSequence oldString,CharSequence newString);
将所有出现的老字符串替换成为新的字符串,返回替换之后的结果新字符串。
**备注:**CharSequence意思就是说可以接受字符串类型。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lI9knImC-1573821333445)(C:\Users\Think-Pad\Desktop\java\字符串转换.jpg)]
11.7 字符串的分割方法
public String[ ] split(String regex): 按照参数的规则,将字符串切分成为若干部分。
注意事项:
split方法的参数其实就是一个“正则表达式”,今后学习。
今天要注意:如果按照英文句点“.”进行切分,必须写“\ \ .”(两个反斜杠)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xsXFoVEY-1573821333446)(C:\Users\Think-Pad\Desktop\java\字符串的分割.jpg)]
11.8 字符串练习
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pMXD4Pt5-1573821333448)(C:\Users\Think-Pad\Desktop\java\字符串方法练习.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kFaJ9yEs-1573821333449)(C:\Users\Think-Pad\Desktop\java\字符串练习01.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9meJFtTF-1573821333450)(C:\Users\Think-Pad\Desktop\java\字符串方法的练习03.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t9o40LEH-1573821333451)(C:\Users\Think-Pad\Desktop\java\字符串方法的练习04.jpg)]
第十二章 静态static关键字
12.1 静态static关键字概述
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zcVfOCqC-1573821333453)(C:\Users\Think-Pad\Desktop\java\静态static关键字概述.jpg)]
12.2 静态static关键字修饰成员变量
如果一个成员变量使用了static关键字,那么这个变量不再属于对象自己,而是属于所在的类。多个对象共享同一份数据。
12.3 静态static关键字修饰成员方法
一旦使用static修饰成员方法,那么这就成为了静态方法。静态方法不属于对象,而是属于类的。
如果没有static关键字,那么必须首先创建对象,然后通过对象才能使用它。
如果有了static关键字,那么不需要创建对象,直接就能通过类名称进行调用。
无论是成员变量,还是成员方法。如果有了static,都推荐使用类名称进行调用。
静态变量:类名称.静态变量
静态方法:类名称.静态方法() (在同一个类中,可以省略类名称)
注意事项:
-
静态不能直接访问非静态。
原因:因为在内存当中是【先】有的静态内容,【后】有的非静态内容。
“先人不知道后人,但是后人知道先人”
- 静态方法当中不能使用this关键字。
原因:this代表对象,通过谁调用的方法,谁就是当前对象。
12.4 静态static的内存图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uWU6M314-1573821333454)(C:\Users\Think-Pad\Desktop\java\静态static的内存图 .jpg)]
12.5 静态代码块
静态代码块的格式是:
public class 类名称{
static{
// 静态代码块的内容
}
}
特点:当第一次用到本类时,静态代码块执行唯一的一次。
静态内容总是优先于非静态,所以静态代码块方法先执行。
静态代码块的经典用途:
用来一次性的对静态成员变量进行赋值。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uzqJWDNw-1573821333456)(C:\Users\Think-Pad\Desktop\java\静态代码块01.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qnZTBNM6-1573821333457)(C:\Users\Think-Pad\Desktop\java\静态代码块02.jpg)]
12.6 数组工具类Arrays
java.util.Arrays是一个与数组相关的工具类,里面提供了大量静态方法,用来实现数组常见的操作。
public static String toString(数组): 将参数数组变成字符串(按照默认格式:[元素1,元素2,元素3…])
public static void sort(数组): 按照默认升序(从小到大)对数组的元素进行排序。
备注:
- 如果是数值,sort默认按照升序从小到大
- 如果是字符,sort默认值按照字母升序
- 如果是自定义的类型,那么这个自定义的类需要有Comparable或者Comparator接口的支持。(今后学习)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SvYPp7ZI-1573821333458)(C:\Users\Think-Pad\Desktop\java\数组排列.jpg)]
练习:
package cn.code;
import java.lang.reflect.Array;
import java.util.Arrays;
/*
题目:
请使用Arrays相关的API,将一个随机字符串中的所有字符升序排列,并倒序打印。
*/
public class Demo34 {
public static void main(String[] args) {
String str = "rdtyftuyi4865fyugyio";
// 如何进行升序排列:sort
// 必须是一个数组才能用Arrays.sort方法
// String --> 数组,用toCharArray
char[] chars = str.toCharArray();
Arrays.sort(chars); // 升序排列
for (int i = chars.length - 1; i >= 0; i--) {
System.out.println(chars[i]);
}
}
}
12.7 数学工具类Math
package cn.code;
/*
java.util.math类是数学相关的工具类,里面提供了大量的静态方法,完成与数学运算相关的操作。
public static double abs(double num): 获取绝对值。有多种重载。
public static double ceil(double num):向上取整
public static double floor(double num):向下取整
public static long round(double num): 四舍五入
*/
public class Demo35 {
public static void main(String[] args) {
System.out.println(Math.abs(-20.2)); // 20.2
System.out.println(Math.ceil(20.2)); // 21.0
System.out.println(Math.floor(20.2)); // 20.0
System.out.println(Math.round(20.2)); // 20
}
}
练习:
package cn.code;
/*
题目:
计算在-10.8到5.9之间,绝对值大于6或者小于2.1的整数有多少个?
分析:
1. 既然已经确定了范围,for循环
2. 起点位置-10.8应该转换成为-10,两种方法:
2.1 可以使用Math.ceil方法向上(向正方向)取整
2.2 强转成为int,自动舍弃所有小数位
3. 每一个数字都是整数,所以步进表达式应该是num++,这样每次都是+1的
4. 如何拿到绝对值:Math.abs方法
5. 一旦发现了一个数字,需要让计时器++进行统计
备注: 如果使用MAth.ceil方法,-10.8可以变成-10.0,注意double也是可以进行++的。
*/
public class Demo36 {
public static void main(String[] args) {
int count = 0; // 计时器
double a = -10.8;
double b = 5.9;
// 得到a与b之间所有的整数
for (int i = (int) a; i < b; i++) {
int abs = Math.abs(i);
if (abs > 6 || abs < 2.1){
System.out.println(i);
count++;
}
}
System.out.println("总共有:" + count);
}
}
第十三章 继承
13.1 继承的概念
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FOCnTQlR-1573821333460)(C:\Users\Think-Pad\Desktop\java\继承的概念.jpg)]
13.2 继承的格式
main方法:
package cn.code;
/*
在继承的关系中,“子类就是一个父类”。也就是说,子类可以当做父类看待。
例如父类是员工,子类就是讲师,那么“讲师就是一个员工”。关系:is-a
定义父类的格式:(一个普通的类定义)
public class 父类名称{
//...
}
定义子类的格式:
public class 子类名称 extends 父类名称{
//...
}
*/
public class Demo37 {
public static void main(String[] args) {
Demo3702 dem = new Demo3702(); // 创建子类对象
dem.method(); // 中秋节快乐!
}
}
父类方法:
package cn.code;
public class Demo3701 {
public void method(){
System.out.println("中秋节快乐!");
}
}
子类方法:
package cn.code;
import cn.code.Demo.Demo3201;
public class Demo3702 extends Demo3701 {
}
13.3 继承中成员变量的访问特点
main方法:
package cn.code;
/*
在父类的继承关系当中,如果成员变量重名,则创建子类对象时,访问有两种:
直接通过子类对象访问成员变量:
等号左边是谁,就优先用谁,没有则向上找。
间接通过成员方法访问成员变量:
该方法属于谁,就优先用谁,没有则向上找。
*/
public class Demo38 {
public static void main(String[] args) {
Demo3802 zi = new Demo3802();
System.out.println(zi.num); // 865
zi.methZi(); // 中秋节快乐!
zi.methodFu(); // 节日快乐!
}
}
父类方法:
package cn.code;
public class Demo3801 {
int numFu = 51;
int num = 85;
public void methodFu(){
System.out.println("节日快乐!");
}
}
子类方法 :
package cn.code;
public class Demo3802 extends Demo3801{
int numZi = 754;
int num = 865;
public void methZi(){
System.out.println("中秋节快乐!");
}
}
13.4 区分子类方法中重名的三种变量
main方法:
package cn.code;
/*
局部变量: 直接写成员变量名
本类的成员变量: this.成员变量名
父类的成员变量名: super.成员变量名
*/
public class Demo39 {
public static void main(String[] args) {
Demo3902 deo = new Demo3902();
deo.method(); // 65 25 10
}
}
父类方法:
package cn.code;
public class Demo3901 {
int num = 10;
}
子类方法:
package cn.code;
public class Demo3902 extends Demo3901{
int num = 25;
public void method(){
int num = 65;
System.out.println(num);
System.out.println(this.num);
System.out.println(super.num);
}
}
13.5 继承中成员方法的访问特点
main方法:
package cn.code;
/*
在子类的继承关系当中,创建子类对象,访问成员方法的规则:
创建的对象是谁,就优先用谁,如果没有则向上找。
注意事项:
无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类的。
*/
public class Demo40 {
public static void main(String[] args) {
// 创建一个子类的对象
Demo4002 deo = new Demo4002();
// 创建的对象是子类的,所以优先使用子类方法
deo.method(); // 子类重名方法执行啦!
deo.methodZi(); // 子类方法执行啦!
deo.methodFu(); // 父类方法执行啦!
}
}
父类方法:
package cn.code;
public class Demo4001 {
public void methodFu(){
System.out.println("父类方法执行啦!");
}
public void method(){
System.out.println("父类重名方法执行啦!");
}
}
子类方法:
package cn.code;
public class Demo4002 extends Demo4001{
public void methodZi(){
System.out.println("子类方法执行啦!");
}
public void method(){
System.out.println("子类重名方法执行啦!");
}
}
13.6 继承中方法的覆盖重写
重写(Override)
概念:在继承关系当中,方法的名称一样,参数列表也一样。
重写(Override): 方法的名称一样,参数列表【也一样】。 覆盖、覆写。
重载(Overload): 方法的名称一样,参数列表【不一样】。
方法的覆盖重写特点:创建的是子类对象,则优先使用子类方法。
方法覆盖重写的注意事项:
-
必须保证父子类之间方法的名称相同,参数列表也相同。
@Override:写在方法前面,用来检测是不是有效的正确覆盖重写。
这个注解就算是不写,只要满足要求,也是正确的方法覆盖重写。
- 子类方法的返回值必须【小于等于】父类方法的返回值范围。
小拓展提示:java.lang.Object类是所有类的公共最高父类(祖宗类),java.lang.String就是Object的子类。
- 子类方法的权限必须【大于等于】父类方法的权限修饰。
小扩展提示:public > protect > (default) > private
备注:(default) 不是关键字default,而是什么都不写,留空。
13.7 继承中方法的覆盖重写
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-su1znmR8-1573821333461)(C:\Users\Think-Pad\Desktop\java\继承中方法的覆盖重写.jpg)]
main方法:
package cn.code;
public class Demo41 {
public static void main(String[] args){
Demo4102 dem = new Demo4102();
dem.newff(); // 打电话 发短信 看视频
}
}
父类:
package cn.code;
// 定义一个父类
public class Demo4101 {
// 原有的功能
// 定义方法
public void call(){
System.out.println("打电话");
}
public void sendMessage(){
System.out.println("发短信");
}
}
子类:
package cn.code;
// 定义一个子类
public class Demo4102 extends Demo4101{
public void newff(){
// 使用父类的方法用super
super.call();
super.sendMessage();
System.out.println("看视频");
}
}
13.8 继承中构造方法的访问特点
继承关系中,父子类构造方法的访问特点:
- 子类构造方法当中有一个默认隐含的“super()”调用,所以一定是先调用的父类构造,后执行的子类构造。
- 子类构造可以通过super关键字来调用父类重载构造。
- super的父类构造调用,必须是子类构造方法的第一个语句。不能一个子类构造调用多次super构造。
总结:
子类必须调用父类构造方法,不写则赠送super();写了则用写的指定的super调用,super只能有一个,还必须是第一个。
只有子类构造方法才能调用父类构造方法。
13.9 super关键字的三种用法
子类:
package cn.code;
/*
super关键字的用法有三种:
1. 在子类的成员方法中,访问父类的成员变量。
2. 在子类的成员方法中,访问父类的成员方法。
3. 在子类的构造方法中,访问父类的构造方法。
*/
public class Demo42 extends Demo4201{
// 在子类的构造方法中,访问父类的构造方法。
public Demo42(){
super();
}
public void methodZi(){
System.out.println(super.num); // 访问父类的成员变量。
super.method(); // 访问父类的成员方法。
}
}
父类:
package cn.code;
public class Demo4201 {
int num = 845;
public Demo4201(){
System.out.println("中秋节快乐!");
}
public void method(){
System.out.println("节日快乐!");
}
}
13.10 this关键字的三种用法
package cn.code;
/*
super关键字用来访问父类内容,而this关键字用来访问本类内容。用法也有三种:
1. 在本类的成员方法中,访问本类的成员变量。
2. 在本类的成员方法中,访问本类的另一个成员方法。
3. 在本类的构造方法中,访问本类的另一个构造方法。
在第三种用法当中要注意:
A. this(...)调用也必须是构造方法的第一个个语句,唯一一个。
B. super和this两种构造调用,不能同时使用。
*/
public class Demo43 {
int num = 666;
public void showNum(){
int num = 888;
System.out.println(num); // 调用局部变量
System.out.println(this.num); // 调用本类的成员变量
}
// 在本类的构造方法中,访问本类的另一个构造方法。
public Demo43(){
this(55);
}
public Demo43(int num){
this(4,5);
}
public Demo43(int a, int b)
}
13.11 super与this关键字图解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YYcuyEwB-1573821333463)(C:\Users\Think-Pad\Desktop\java\super与this关键字图解.jpg)]
13.12 继承的三个特点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sSdZ3rcZ-1573821333464)(C:\Users\Think-Pad\Desktop\java\继承的三个特点.jpg)]
第十四章 抽象
14.1 抽象的概念
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o4l3mJ0u-1573821333465)(C:\Users\Think-Pad\Desktop\java\抽象的概念.jpg)]
14.2 抽象方法和抽象类
main方法:
package cn.code;
/*
抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束。
抽象类:抽象方法所在的类,必须是抽象类才行。在class之前写上abstract即可。
如何使用抽象类和抽象方法:
1. 不能直接创建new抽象类对象。
2. 必须用一个子类来继承抽象父类。
3. 子类必须覆盖重写抽象父类当中所有的抽象方法。
覆盖重写(实现):子类去掉抽象方法的abstract关键字,然后补上方法体大括号。
4. 创建子类对象进行使用。
*/
public class Demo44 {
public static void main(String[] args) {
Demo4402 deo = new Demo4402();
deo.eat(); // 猫吃鱼
}
}
抽象类:
package cn.code;
public abstract class Demo4401 {
public abstract void eat(); // 定义一个抽象方法 用abstract关键字
}
子类:
package cn.code;
public class Demo4402 extends Demo4401{
// 定义一个子类继承抽象类
public void eat(){
System.out.println("猫吃鱼");
}
}
14.3 使用抽象类的注意事项:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dkR7Fzpx-1573821333467)(C:\Users\Think-Pad\Desktop\java\使用抽象类的注意事项.jpg)]
main方法:
package cn.code;
public class Demo45 {
public static void main(String[] args) {
Demo4503 dem = new Demo4503();
dem.eat(); // 狗吃骨头
dem.sleep(); // 呼呼呼
}
}
最高级抽象类:
package cn.code;
// 创建一个最高级抽象类
public abstract class Demo4501 {
public abstract void eat();
public abstract void sleep();
}
子抽象类:
package cn.code;
// 创建一个子抽象类
public abstract class Demo4502 extends Demo4501 {
@Override
public void eat(){
System.out.println("狗吃骨头");
// public abstract void sleep();
}
}
子类:
package cn.code;
// 建立一个子类
public class Demo4503 extends Demo4502{
@Override
public void sleep(){
System.out.println("呼呼呼");
}
}
14.4 发红包案例
main方法:
package cn.code.Demo01;
import java.util.ArrayList;
public class mainRedPacket {
public static void main(String[] args) {
Manager manager = new Manager("群主",100);
Member one = new Member("成员A",0);
Member two = new Member("成员B",0);
Member three = new Member("成员C",0);
manager.show();
one.show();
two.show();
three.show();
System.out.println("================");
// 群主发红包,20元3包
ArrayList<Integer> redlist = manager.send(20,3);
// 三个普通成员收红包
one.recive(redlist);
two.recive(redlist);
three.recive(redlist);
// 显示各自余额
manager.show();
one.show();
two.show();
three.show();
/* 运行结果:
我叫:群主,我有 100
我叫:成员A,我有 0
我叫:成员B,我有 0
我叫:成员C,我有 0
================
我叫:群主,我有 80
我叫:成员A,我有 8
我叫:成员B,我有 6
我叫:成员C,我有 6*/
}
}
用户类:
package cn.code.Demo01;
public class User {
private String name; // 姓名
private int money; // 余额,也就是当前用户拥有的钱数
public User() {
}
public User(String name, int money) {
this.name = name;
this.money = money;
}
// 展示一下用户有多少钱
public void show(){
System.out.println("我叫:"+ name + ",我有 " + money);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
群主类:
package cn.code.Demo01;
import java.util.ArrayList;
// 群主
public class Manager extends User {
public Manager() {
}
public Manager(String name, int money) {
super(name, money);
}
// 定义一个方法用来表示群主发红包
public ArrayList<Integer> send(int totalMonney, int count){
// 首先要有一个集合用来存储若干个红包的金额
ArrayList<Integer> redList = new ArrayList<>();
// 看一下群主有多少钱 进行判断
int leftMoney = super.getMoney(); // 群主余额
if (leftMoney < totalMonney ){
System.out.println("余额不足!");
return redList; // 返回空集合
}
// 扣钱,其实就是重新设置余额
super.setMoney(leftMoney - totalMonney);
// 发红包需要平均分成count份
int avg = totalMonney / count;
int mod = totalMonney % count; // 余数,也就是甩下的零头
// 除不开的零头,包在最后一个包中
// 下面把红包一个一个放到集合中
for (int i = 0; i < count - 1; i++) {
redList.add(avg);
}
// 最后一个红包
int last = avg + mod;
redList.add(last);
return redList;
}
}
成员类:
package cn.code.Demo01;
import java.util.ArrayList;
import java.util.Random;
// 成员类
public class Member extends User {
public Member() {
}
public Member(String name, int money) {
super(name, money);
}
// 定义一个方法表示成员收红包
public void recive(ArrayList<Integer> list){
// 从多个红包中随机抽取一个给我自己
// 随机获取一个集合当中的索引编号
int index = new Random().nextInt(list.size());
// 根据索引,从集合中删除,并且得到被删除的红包,留给自己
int d = list.remove(index);
// 当前成员本来有多少钱
int money = super.getMoney();
// 加法,并且重新设置回去
super.setMoney(money + d );
}
}
第十五章 接口
15.1 接口的定义基本格式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ns8A2hiQ-1573821333469)(C:\Users\Think-Pad\Desktop\java\接口.jpg)]
接口就是多个类的公共规范。
接口是一种引用数据类型,最重要的内容就是其中的 – 抽象方法。
如何定义一个接口的格式:
public interface 接口名称{
// 接口内容
}
备注:换成了关键字interface之后,编译生成的字节码文件仍然是:.java --> .class
如果是Java7. 那么接口中可以包含的内容有:
- 常量
- 抽象方法
如果是 Java 8. 还可以额外包含有:
-
默认方法
-
静态方法
如果是 Java9. 还可以额外包含有:
- 私有方法
15.2 接口的抽象方法定义
接口:
package cn.code.Demo002;
/*
在任何版本的Java中,接口都能定义抽象方法。
格式:
public abstract 返回值类型 方法名称(参数列表);
注意事项:
1. 接口当中的抽象方法,修饰符必须是两个固定的关键字: public abstract
2. 这两个关键字修饰符,可以选择性的省略。
3. 方法的三要素,可以随意定义。
*/
public interface MyInterFaceAbstract {
// 以下均为抽象方法,都正确
public abstract void methodA();
abstract void methodB();
public void methodC();
void methodD();
}
继承接口:
package cn.code.Demo002;
public class MyInterFaceAbstractImpl implements MyInterFaceAbstract{
@Override
public void methodA() {
System.out.println("这是第一个方法!");
}
@Override
public void methodB() {
System.out.println("这是第二个方法!");
}
@Override
public void methodC() {
System.out.println("这是第三个方法!");
}
@Override
public void methodD() {
System.out.println("这是第四个方法!");
}
}
main方法:
package cn.code.Demo002;
/*
接口使用步骤:
1. 接口不能直接使用,必须有一个“实现类”来“实现”该接口。
格式:
public class 实现类名称 implements 接口名称{
// ...
}
2. 接口的实现类必须覆盖重写(实现)接口中所有的抽象方法。
实现:去掉abstract关键字,加上方法体大括号。
3. 创建实现类的对象,进行使用。
注意事项:
如果实现类没有覆盖重写接口中所有的抽象方法,那么这个实现类自己就必须是抽象类。
*/
public class Interface {
public static void main(String[] args) {
/* MyInterFaceAbstract inter = new MyInterFaceAbstract() {
}*/ // 错误写法
MyInterFaceAbstractImpl abs = new MyInterFaceAbstractImpl();
abs.methodA(); // 这是第一个方法!
abs.methodC(); // 这是第三个方法!
}
}
15.3 接口的默认方法
接口:
package cn.code.Demo002;
/*
从Java 8 开始,接口里允许定义默认方法。
格式:
public default 返回值类型 方法名称(参数列表){
方法体
}
备注:接口当中的默认方法,可以解决接口升级的问题。
*/
public interface MyInterfaceDefult {
// 这是一个抽象方法
public abstract void methodAbs1();
// 新添一个抽象方法 后面的继承类会报错
// public abstract void methodAbs2();
// 这是一个默认方法
public default void methodDefault(){
System.out.println("默认方法执行啦!");
}
}
实现类A:
package cn.code.Demo002;
public class MyInterfaceDefaultA implements MyInterfaceDefult{
@Override
public void methodAbs1() {
System.out.println("实现了抽象方法:AAA");
}
}
实现类B:
package cn.code.Demo002;
public class MyInterfaceDefaultB implements MyInterfaceDefult{
@Override
public void methodAbs1() {
System.out.println("实现了抽象方法:BBB");
}
public void methodDefault(){
System.out.println("实现了B的覆盖重写");
}
}
main方法:
package cn.code.Demo002;
/*
1. 接口的默认方法,可以通过接口实现类对象,直接调用。
2. 接口的默认方法,也可以被接口实现类进行覆盖重写。
*/
public class InterfaceDefault {
public static void main(String[] args) {
MyInterfaceDefaultA a = new MyInterfaceDefaultA();
a.methodAbs1(); // 实现了抽象方法:AAA 调用抽象方法,实际运行的是右侧实现类。
a.methodDefault(); // 默认方法执行啦! 调用默认方法,如果实现类当中没有,会向上找接口。
System.out.println("==============");
MyInterfaceDefaultB b = new MyInterfaceDefaultB();
b.methodAbs1(); // 实现了抽象方法:BBB
b.methodDefault(); // 实现了B的覆盖重写
}
}
15.4 接口的静态方法
接口:
package cn.code.Demo002;
/*
从Java 8 开始,接口当中允许定义静态方法。
格式:
public static 返回值类型 方法名称(参数列表){
方法体
}
提示:就是将abstract或者default换成static即可,带上方法体。
*/
public interface MyInterfaceStatic {
public static void method(){
System.out.println("这是一个接口的静态方法!");
}
}
实现类:
package cn.code.Demo002;
public class MyInterfaceStaticImpl implements MyInterfaceStatic {
}
main方法:
package cn.code.Demo002;
/*
注意:不能通过接口实现类的对象来调用接口当中的静态方法。
正确用法:通过接口名称,直接调用其中的静态方法。
格式:
接口名称.静态方法名(参数);
*/
public class InterfaceStatic {
public static void main(String[] args) {
MyInterfaceStaticImpl inter = new MyInterfaceStaticImpl();
// inter.method; // 错误写法!
// 直接通过接口名称来调用静态方法
MyInterfaceStatic.method(); // 这是一个接口的静态方法!
}
}
15.5 接口的私有方法
接口:
package cn.code.Demo002;
/*
问题描述:
我们需要抽取一个共有方法,用来解决两个默认方法之间重复代码的问题。
但是这个共有方法不应该让实现类使用,应该是私有化的。
解决方案:
从Java 9 开始,接口当中允许定义私有方法。
1. 普通私有方法,解决多个默认方法之间重复代码问题
格式:
private 返回值类型 方法名称(参数列表){
方法体
}
2. 静态私有方法,解决多个静态方法之间重复代码问题
格式:
private static 返回值类型 方法名称(参数列表){
方法体
}
*/
public interface MyInterfacePrivate {
public default void methodDefault1(){
System.out.println("默认方法1");
methodCommon();
}
public default void methodDefault2(){
System.out.println("默认方法2");
methodCommon();
}
public default void methodCommon(){
System.out.println("aaaaaaaa");
System.out.println("bbbbbbbb");
System.out.println("cccccccc");
/* private void methodCommon(){
System.out.println("aaaaaaaa");
System.out.println("bbbbbbbb");
System.out.println("cccccccc");
*/
}
}
实现类:
package cn.code.Demo002;
public class MyInterfacePrivateImpl implements MyInterfacePrivate {
public void methodAnother(){
// 直接访问到了接口中的默认方法,这是错误的!
// methodCommon();
}
}
15.6 接口的常量定义和使用
接口:
package cn.code.Demo002;
/*
接口当中可以定义“成员变量”,但是必须使用public static final三个关键字进行修饰。
从效果上看,这其实就是接口的【常量】。
格式:
public static final 数据类型 常量名称 = 数据值;
备注:
一旦使用final关键字进行修饰,说明不可改变。
注意事项:
1. 接口当中的常量,可以省略public static final,注意:不写也照样是这样。
2. 接口当中的常量,必须进行赋值,不能不赋值。
3. 接口中常量的名称,使用完全大写字母,用下划线进行分割。(推荐命名规则)
*/
public interface MyInterfaceConst {
public static final int A = 45;
}
main方法:
package cn.code.Demo002;
public class InterfaceConst {
public static void main(String[] args) {
System.out.println(MyInterfaceConst.A); // 45
}
}
15.7 接口的内容小结
在Java 9+ 版本中,接口的内容可以有:
-
成员变量其实是常量,格式:
[public] [static] [final] 数据类型 常量名称 = 数据值;
注意:
常量必须进行赋值,而且一旦赋值不能改变。
常量名称完全大写,用下划线进行分割。
- 接口中最重要的就是抽象方法,格式:
[public] [abstract] 返回值类型 方法名称(参数列表);
注意:实现类必须覆盖重写接口所有的抽象方法,除非实现类是抽象类。
- 从Java 8 开始,接口里允许定义默认方法,格式:
[public] defult 返回值类型 方法名称(参数列表){方法体}
注意:默认方法也可以被覆盖重写
- 从Java 8 开始,接口里允许定义静态方法,格式:
[public] static 返回值类型 方法名称(参数类型){方法体}
注意:应该通过接口名称进行调用,不能通过实现类对象调用接口静态方法
- 从Java 9 开始,接口里允许定义私有方法,格式:
普通私有方法:private 返回值类型 方法名称(参数列表){方法体}
静态私有方法:private static 返回值类型 方法名称(参数列表){方法体}
注意:private的方法只有接口自己才能调用,不能被实现类或别人使用。
15.8 继承父类并实现多个接口
使用接口的时候,需要注意:
-
接口是没有静态代码块或者构造方法的。
-
一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。
格式:
public class MyInterfaceImpl implement MyInterfaceA,MyInterfaceB{
// 覆盖重写所有抽象方法
}
- 如果实现类所有实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。
- 如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类。
- 如果实现类所实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写。
- 一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法。
15.9 接口之间的多继承
- 类与类之间是单继承的,直接父类只有一个。
- 类与接口之间是多实现的。一个类可以实现多个接口。
- 接口与接口之间是多继承的。
注意事项:
- 多个父接口当中的抽象方法如果重复,没关系。
- 多个父接口当中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写,【而且带着default关键字】。
第十六章 多态
16.1 多态的概念
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H5en4Z6t-1573821333471)(C:\Users\Think-Pad\Desktop\java\多态.jpg)]
16.2 多态的格式与使用
main方法:
package cn.code.Demo003;
/*
代码当中体现多态性,其实就是一句话:父类引用指向子类对象。
格式:
父类名称 对象名 = new 子类名称();
或者:
接口名称 对象名 = new 实现类名称();
*/
public class Demo01Multi {
public static void main(String[] args) {
// 使用多态的写法
// 左侧父类的引用,指向了右侧子类的对象
Fu obj = new Zi();
obj.method(); // 子类方法!
obj.methodFu(); // 父类特有方法!
}
}
父类:
package cn.code.Demo003;
public class Fu {
public void method(){
System.out.println("父类方法!");
}
public void methodFu(){
System.out.println("父类特有方法!");
}
}
子类:
package cn.code.Demo003;
public class Zi extends Fu {
@Override
public void method() {
System.out.println("子类方法!");
}
}
16.3 多态中成员变量的使用特点
父类:
package cn.code.Demo004;
public class Fu /*extends Object*/ {
int num = 45;
public void method(){
System.out.println(num);
}
}
子类:
package cn.code.Demo004;
public class Zi extends Fu {
int num = 85;
@Override
public void method() {
System.out.println(num);
}
}
main方法:
package cn.code.Demo004;
/*
访问成员变量的两种方式:
1. 直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找。
2. 间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找。
*/
public class MultiField {
public static void main(String[] args) {
// 使用多态的写法,父类引用指向子类对象
Fu obj = new Zi();
System.out.println(obj.num); // 45
// System.out.println(obj.age); // 错误写法
System.out.println("=====================");
// 子类没有覆盖重写,就是父:45
// 子类覆盖重写,就是子:85
obj.method();
}
}
16.4 多态中成员方法的使用特点
父类:
package cn.code.Demo004;
public class Fu /*extends Object*/ {
public void method(){
System.out.println("父类方法!");
}
public void methodFu(){
System.out.println("父类特有方法!");
}
}
子类:
package cn.code.Demo004;
public class Zi extends Fu {
@Override
public void method() {
System.out.println("子类方法!");
}
}
main方法:
package cn.code.Demo004;
/*
在多态的代码当中,成员方法的访问规则是:
看new的谁,就优先用谁,没有则向上找。
口诀:编译看左边,运行看右边。
对比一下:
成员变量:编译看左边,运行看左边。
成员方法:编译看左边,运行看右边。
*/
public class MultiMethod {
public static void main(String[] args) {
Fu obj = new Zi(); // 多态
obj.method(); // 子类方法! 父子都有,优先用子
obj.methodFu(); // 父类特有方法! 子类没有,父类有,向上找到父类
// obj.methodZi(); // 错误写法
}
}
16.5 使用多态的好处
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d3bb6sMC-1573821333472)(C:\Users\Think-Pad\Desktop\java\使用多态的好处.jpg)]
16.6 对象的向上转型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-njIzC7cu-1573821333474)(C:\Users\Think-Pad\Desktop\java\对象的向上转型.jpg)]
抽象类:
package cn.code.Demo004;
// 定义一个抽象类
public abstract class Animal {
public void eat(){};
}
实现类:
package cn.code.Demo004;
// 实现抽象类
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼!");
}
}
main方法:
package cn.code.Demo004;
public class Demo01Main {
public static void main(String[] args) {
// 对象的向上转型,就是:父类引用指向子类对象。
Animal animal = new Cat();
animal.eat(); // 猫吃鱼!
}
}
16.7 对象的向下转型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z9tcb6IX-1573821333475)(C:\Users\Think-Pad\Desktop\java\对象的向下转型.jpg)]
main方法:
package cn.code.Demo004;
/*
向上转型一定是安全的,没有问题的,正确的。但是也有一个弊端:
对象一旦向上转型为父类,那么久无法调用子类原本特有的内容。
解决方案:用对象的向下转型【还原】。
*/
public class Demo01Main {
public static void main(String[] args) {
// 对象的向上转型,就是:父类引用指向子类对象。
Animal animal = new Cat();
animal.eat(); // 猫吃鱼!
// animal.CatchMouse(); // 错误写法!
// 向下转型,进行“还原”动作
Cat cat = (Cat)animal;
((Cat) animal).CatchMouse(); // 猫抓老鼠!
// 下面是错误的向下转型
// 本来new的时候是一只猫,现在非要当做狗
// Dog dog = (Dog)animal; // java.lang.ClassCastException 类型转换异 编译器不报错,运行报错
}
}
抽象类:
package cn.code.Demo004;
// 定义一个抽象类
public abstract class Animal {
public void eat(){};
}
实现类:
package cn.code.Demo004;
// 实现抽象类
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼!");
}
public void CatchMouse(){
System.out.println("猫抓老鼠!");
}
}
package cn.code.Demo004;
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃骨头!");
}
}
16.8 用instanceof关键字进行联系判断
抽象类:
package cn.code.Demo004;
// 定义一个抽象类
public abstract class Animal {
public void eat(){};
}
实现类:
package cn.code.Demo004;
// 实现抽象类
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼!");
}
public void CatchMouse(){
System.out.println("猫抓老鼠!");
}
}
package cn.code.Demo004;
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃骨头!");
}
public void CatchHouse(){
System.out.println("狗看家!");
}
}
main方法:
package cn.code.Demo004;
/*
如何才知道一个父类引用的对象,本来是什么子类?
格式:
对象 instanceof 类名称
这将会得到一个Boolean值结果,也就是判断前面对象能不能当做后面类型的实例。
*/
public class Demo02Instanceof {
public static void main(String[] args) {
Animal animal = new Dog();
animal.eat(); // 狗吃骨头!
// 如果希望调用子类的特有方法,需要向下转型
// 判断一下父类引用animal本来是不是Dog
if (animal instanceof Dog){
Dog dog = (Dog)animal;
dog.CatchHouse(); // 狗看家!
}
if (animal instanceof Cat){
Cat cat = (Cat)animal;
cat.CatchMouse();
}
}
}
16.9 笔记本USB接口案例
main方法:
package cn.code.Demo005;
public class DemoMain {
public static void main(String[] args) {
// 首先创建一个笔记本电脑
Computer computer = new Computer();
computer.powerOn();
// 准备一个鼠标,供电脑使用
// Mouse mouse = new Mouse();
// 首先进行向上转型
USB usbMouse = new Mouse(); // 多态方法
// 参数是USB类型,我正好传递进去的就是USB鼠标
computer.usbDevice(usbMouse);
// 创建一个USB键盘
Keyboard keyboard = new Keyboard(); // 没有使用多态写法
// 方法参数是USB类型,传递进去的是实现类对象
computer.usbDevice(keyboard); // 正确写法!
computer.powerOff();
}
}
USB接口:
package cn.code.Demo005;
public interface USB {
public abstract void open();
public abstract void close();
}
实现类:
package cn.code.Demo005;
public class Computer {
public void powerOn(){
System.out.println("笔记本电脑开机");
}
public void powerOff(){
System.out.println("笔记本电脑关机");
}
// 使用USB设备的方法,使用接口作为方法的参数
public void usbDevice(USB usb){
usb.open(); // 打开设备
if (usb instanceof Mouse){
Mouse mouse = (Mouse)usb; // 向下转型
mouse.click();
}
else if (usb instanceof Keyboard){
Keyboard keyboard = (Keyboard)usb;
keyboard.type();
}
usb.close(); // 关闭设备
}
}
package cn.code.Demo005;
// 鼠标就是一个USB设备
public class Mouse implements USB {
@Override
public void open() {
System.out.println("打开鼠标");
}
@Override
public void close() {
System.out.println("关闭鼠标");
}
public void click(){
System.out.println("点击鼠标");
}
}
package cn.code.Demo005;
// 键盘就是一个USB设备
import cn.code.Demo01.User;
public class Keyboard implements USB {
@Override
public void open() {
System.out.println("打开键盘");
}
@Override
public void close() {
System.out.println("关闭键盘");
}
public void type(){
System.out.println("键盘输入");
}
}
第十七章 final关键字
final关键字代表最终、不可改变的。
常见的四种方法:
- 可以用来修饰一个类
- 可以用来修饰一个方法
- 还可以用来修饰一个局部变量
- 还可以用来修饰一个成员变量
17.1 final关键字用于修饰类
final类:
package cn.code.Demo006;
/*
当final关键字用来修饰一个类的时候,格式:
public final class 类名称{
// ...
}
含义:当前这个类不能有任何子类。(太监类)
注意:一个类如果是final的,那么其中所有的成员方法都无法进行覆盖重写(因为没儿子)。
*/
public final class Myclass /*extends Object */ {
public void method(){
System.out.println("方法执行!");
}
}
继承类:
package cn.code.Demo006;
/*
不能使用一个final类来作为父类
*/
public class MySubClass /*extends Myclass*/ {
}
17.2 final关键字用于修饰成员方法
父类:
package cn.code.Demo006;
/*
当final关键字用来修饰一个方法的时候,这个方法就是最终方法,也就是不能被覆盖重写。
格式:
修饰符 final 返回值类型 方法名称(参数列表){
// 方法体
}
注意事项:
对于类、方法来说,abstract关键字和final关键字不能同时使用,因为没矛盾。
*/
public class Fu {
public final void methodFu(){
System.out.println("父方法执行!");
}
public/* final abstract*/ void method(){
System.out.println("======");
}
}
子类:
package cn.code.Demo006;
public class Zi extends Fu {
// 报错
/*@Override
public void methodFu() {
System.out.println("子类方法执行!");
}*/
}
17.3 final关键字用于修饰局部变量
final类:
package cn.code.Demo006;
public class Demo01Final {
public static void main(String[] args) {
int num = 15;
System.out.println(num); // 15
num = 65;
System.out.println(num); // 65
// 一旦使用final用来修饰局部变量,那么这个变量就不能进行更改。
// “一次赋值,终生不变”
final int num1 = 68;
System.out.println(num1);
// num1 = 56; // 错误写法
// 正确写法!只要保证有唯一一次赋值即可
final int num3;
num3 =653;
// 对于基本类型来说,不可变说的是变量当中的数据不可改变
// 对于引用类型来说,不可变说的是变量当中的地址值不可改变
Student student1 = new Student("周杰伦");
System.out.println(student1); // cn.code.Demo006.Student@4554617c
System.out.println(student1.getName()); // 周杰伦
student1 = new Student("五月天");
System.out.println(student1);
System.out.println(student1.getName()); // 五月天
final Student student2 = new Student("阿信");
// 错误写法!final的引用类型变量,其中的地址值不可改变。
// student2 = new Student("陈绮贞");
System.out.println(student2.getName()); // 阿信
student2.setName("陈奕迅");
System.out.println(student2.getName()); // 陈奕迅
}
}
student类:
package cn.code.Demo006;
public class Student {
private String name;
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(String name) {
this.name = name;
}
}
17.4 final关键字用于修饰成员变量
package cn.code.Demo006;
/*
对于成员变量来说,如果使用final关键字,那么这个变量也照样是不可变的。
1. 由于成员变量具有默认值,所以用了final之后必须手动赋值,不会再给默认值了。
2. 对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值。二者选其一。
3. 必须保证类当中所有重载的构造方法,都最终会对final的成员变量进行赋值。
*/
public class Person {
private final String name /*= "鹿晗"*/;
public Person() {
name = "关晓彤 ";
}
public String getName() {
return name;
}
/* public void setName(String name) {
this.name = name;
}*/
public Person(String name) {
this.name = name;
}
}
17.5 四种权限修饰符
java中有四种权限修饰符:
public > protected > (default) > private
同一个类(我自己) YES YES YES YES
同一个包(我邻居) YES YES YES NO
不同包子类(我儿子) YES YES NO NO
不同包非子类(陌生人) YES NO NO NO
注意事项:(default)并不是关键字“default”,而是根本不写。
第十八章 内部类
18.1 成员内部类的定义
package cn.code.Drmo007;
/*
如果一个事物的内部包含一个事物,那么这就是一个类内部包含另一个类。
例如:身体和心脏的关系。又如:汽车和发动机的关系。
分类:
1. 成员内部类
2. 局部内部类(包含匿名内部类)
成员内部类的定义格式:
修饰符 class 外部类名称{
修饰符 class 内部类名称{
// ...
}
// ...
}
注意:内用外,随意访问,需要内部类对象。
*/
public class Demo01InnerClass { // 外部类
// 外部的成员变量
private String name;
public void method(){
System.out.println("外部类的方法!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 成员内部类
public class Heart{
public void beat(){ // 成员内部类的方法
System.out.println("我叫" + name);
System.out.println("心脏跳动!");
}
}
}
18.2 成员内部类的使用
main方法:
package cn.code.Drmo007;
/*
如何使用成员内部类?有两种方式:
1. 间接方式:在外部类的方法当中,使用内部类;然后main只是调用外部类的方法。
2. 直接方式:公式:
类名称 对象名 = new 类名称();
【外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();】
*/
public class Demo02InnerClass {
public static void main(String[] args) {
Demo01InnerClass dem = new Demo01InnerClass();
dem.method();
/* 外部类的方法!
我叫null
心脏跳动!*/
}
}
public class Demo01InnerClass { // 外部类
// 外部的成员变量
private String name;
public void method(){
System.out.println("外部类的方法!");
Heart heart = new Heart();
heart.beat();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 成员内部类
public class Heart{
public void beat(){ // 成员内部类的方法
System.out.println("我叫" + name);
System.out.println("心脏跳动!");
}
}
}
18.3 内部类的同名变量访问
package cn.code.Drmo007;
/*
如果出现了重名现象,那么格式是:外部类名称.this.内部类成员变量名
*/
public class Outer {
int num = 45; // 外部类的成员变量
public class Inner /*extends Object*/ {
int num = 89; // 内部类的成员变量
public void methodInner(){
int num = 652; // 内部方法的局部变量
System.out.println(num); // 内部方法的局部变量,就近原则
System.out.println(this.num); // 内部类的成员变量
System.out.println(Outer.this.num); // 外部类的成员变量
}
}
}
18.4 局部内部类
package cn.code.Drmo007;
/*
如果一个类是定义在一个方法内部的,那么这就是一个局部内部类。
“局部”:只有当前所属的方法才能使用它,出了这个方法外面就不能用了。
定义格式:
修饰符 class 外部类名称 {
修饰符 返回值类型 外部类名称(参数列表){
class 局部内部类名称{
// ...
}
}
}
小结一下类的权限修饰符:
public > protectde > (default) > private
定义一个类的时候,权限修饰符规则:
1. 外部类:public / (default)
2. 成员内部类:public / protectde / (default) / private
3. 局部内部类:什么都不写
*/
public class Outer01 {
public void methodOuter(){
class Inner{
public void methodInner(){
System.out.println("奇妙能力歌");
}
}
Inner inner = new Inner();
inner.methodInner();
}
}
18.5 局部内部类的final问题
package cn.code.Drmo007;
/*
局部内部类,如果希望访问所在方法的局部变量,那么这个局部变量必须是【有效final的】。
备注:从Java 8+ 开始,只要局部变量事实不变,那么final关键字可以省略。
原因:
1. new出来的对象在堆内存当中。
2. 局部变量是跟着方法走的,在栈内存当中。
3. 方法运行结束之后,立刻出栈,局部变量就会立刻消失。
4. 但是new出来的对象会在堆当中持续存在,直到垃圾回收消失。
*/
public class MyOuter {
public void methodOuter(){
final int num = 845;
class Inner{
public void methodInner(){
System.out.println(num);
}
}
}
}
18.6 匿名内部类
接口:
package cn.code.Drmo007;
public interface MyInterface {
public abstract void method();
}
main方法:
package cn.code.Drmo007;
/*
如果接口实现类(或者是父类的子类)只需要使用一次,
那么这种情况下就可以省略掉该类的定义,而改为使用【匿名内部类】。
匿名内部类的定义格式:
接口名称 对象名 = new 接口名称(){
// 覆盖重写所有抽象方法
};
*/
public class DemoMain {
public static void main(String[] args) {
// 使用匿名内部类
MyInterface obj = new MyInterface() {
@Override
public void method() {
System.out.println("匿名内部类实现了方法!");
}
};
obj.method(); // 匿名内部类实现了方法!
}
}
18.7 匿名内部类的注意事项
接口:
package cn.code.Drmo007;
public interface MyInterface {
public abstract void method1();
public abstract void method2();
}
main方法:
package cn.code.Drmo007;
/*
如果接口实现类(或者是父类的子类)只需要使用一次,
那么这种情况下就可以省略掉该类的定义,而改为使用【匿名内部类】。
匿名内部类的定义格式:
接口名称 对象名 = new 接口名称(){
// 覆盖重写所有抽象方法
};
对格式“new 接口名称(){...}”进行解析:
1. new代表创建对象的动作
2. 接口名称就是匿名内部类需要实现哪个接口
3. {...}这才是匿名内部类的内容
另外还要注意几点问题:
1. 匿名内部类,在【创建对象】的时候,只能使用唯一一次。
如果希望多次创建对象,而且类的内容一样的话,那么就必须使用单独定义的实现类了。
2. 匿名对象,在【调用方法】的时候,只能调用唯一一次。
如果希望同一个对象,调用多次方法,那么必须给对象起个名字。
3. 匿名内部类是省略了【实现类/子类名称】,但是匿名对象是省略了【对象名称】
强调:匿名内部类和匿名对象不是一回事!!!
*/
public class DemoMain {
public static void main(String[] args) {
// 使用匿名内部类,但不是匿名对象,对象名称就叫objA
MyInterface objA = new MyInterface() {
@Override
public void method1() {
System.out.println("匿名内部类实现了方法!111-A");
}
@Override
public void method2() {
System.out.println("匿名内部类实现了方法!222-A");
}
};
objA.method1();
objA.method2();
// 使用了匿名内部类,而且省略了对象名称,也是匿名对象
new MyInterface() {
@Override
public void method1() {
System.out.println("匿名内部类实现了方法!111-B");
}
@Override
public void method2() {
System.out.println("匿名内部类实现了方法!222-B");
}
}.method1();
// 因为匿名对象 无法调用第二次方法,所以需要再创建一个匿名内部类的匿名对象
new MyInterface() {
@Override
public void method1() {
System.out.println("匿名内部类实现了方法!111-B");
}
@Override
public void method2() {
System.out.println("匿名内部类实现了方法!222-B");
}
}.method2();
}
}
18.8 类作为成员变量类型
package cn.code.Drmo007;
// 游戏当中的英雄角色类
public class Hero {
private String name; // 英雄的名字
private int age; // 英雄的年龄
private Weapon weapon; // 英雄的武器
public Hero(String name, int age, Weapon weapon) {
this.name = name;
this.age = age;
this.weapon = weapon;
}
public void attack(){
System.out.println("年龄为" + age + "的" + name + "拿着" + weapon.getCode() + "去攻击敌人!");
}
public Hero(String name) {
this.name = name;
}
public Hero() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Weapon getWeapon() {
return weapon;
}
public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}
}
package cn.code.Drmo007;
public class Weapon {
private String code; // 武器的代号
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Weapon(String code) {
this.code = code;
}
public Weapon() {
}
}
package cn.code.Drmo007;
public class DemoMain01 {
public static void main(String[] args) {
// 创建一个英雄角色
Hero hero = new Hero();
// 为英雄角色设置名字和年龄
hero.setName("亚瑟");
hero.setAge(100);
// 创建一个武器对象
Weapon weapon = new Weapon("M24");
// 为英雄配武器装备
hero.setWeapon(weapon);
hero.attack(); // 年龄为100的亚瑟拿着M24去攻击敌人!
}
}
18.9 接口作为成员变量类型
接口:
package cn.code.Drmo007;
public interface Skill {
void use(); // 释放技能的抽象方法
}
package cn.code.Drmo007;
public class Hero01 {
private String name; // 英雄的名称
private Skill skill; // 英雄的技能
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void attack(){
System.out.println("我叫" + name + ",开始释放技能" );
skill.use();
System.out.println("释放技能完毕!");
}
public Skill getSkill() {
return skill;
}
public void setSkill(Skill skill) {
this.skill = skill;
}
public Hero01(String name) {
this.name = name;
}
public Hero01() {
}
}
main方法:
package cn.code.Drmo007;
public class DemoMain02 {
public static void main(String[] args) {
Hero01 hero01 = new Hero01();
hero01.setName("孙尚香"); // 设置英雄名称
// 设置英雄技能 可以单独定义实现类
// 也可以改成使用匿名内部类
/* Skill skill = new Skill() {
@Override
public void use() {
System.out.println("jiu~jiu~jiu");
}
};
hero01.setSkill(skill);
hero01.attack();*/
// 进一步简化,同时使用匿名内部类和匿名对象
hero01.setSkill(new Skill() {
@Override
public void use() {
System.out.println("jiu~~~");
}
});
hero01.attack();
/*
我叫孙尚香,开始释放技能
jiu~~~
释放技能完毕!
*/
}
}
18.10 接口作为方法的参数和或返回值
package cn.code.Drmo007;
import java.util.ArrayList;
import java.util.List;
/*
java.util.List正是ArrayList所实现的接口。
*/
public class DemoMain03 {
public static void main(String[] args) {
// 左边是接口名称,右边是实现类名称,这就是多态写法
List<String> list = new ArrayList<>();
List<String> result = addNames(list);
for (int i = 0; i < result.size(); i++) {
System.out.println(result.get(i));
}
}
public static List<String> addNames(List<String> list){
list.add("迪丽热巴");
list.add("古力娜扎");
list.add("马尔扎哈");
list.add("欧阳娜娜");
return list;
}
}
第十九章 Object类
19.1 Object类的toString方法
package cn.code.Drmo007.Demo008;
import javafx.scene.transform.Scale;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
/*
java.lang.Object
类Object是层次结构的根(父)类。
每个类(Person,Student...)都使用Object作为超(父)类。
所有对象(包括数组)都实现这个类的方法。
*/
public class Demo01ToString {
public static void main(String[] args) {
/*
Person类默认继承了Object类,所以可以使用Object类当中的toString方法
String toString() 返回该对象的字符串表示。
*/
Person person = new Person("陈粒",18);
String s = person.toString();
System.out.println(s);
// 直接打印对象的名字,其实就是调用对象的toString person = person.toString();
System.out.println(person);
// 看一个类是否重写了toString,直接打印这个类的对象即可,如果没有重写toString方法那么打印的是对象的地址值
Random r= new Random();
System.out.println(r); // 地址值
Scanner sc = new Scanner(System.in);
System.out.println(sc); // 地址值
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
System.out.println(list); // [1, 2, 3, 4]
}
}
package cn.code.Drmo007.Demo008;
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
/*
直接打印对象的地址值没有意义,需要重写Object类当中的toString方法
打印对象的属性(name,age)
*/
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
19.2 Object类的equals方法
package cn.code.Drmo007.Demo008;
/*
person类默认继承了Object类,所以可以使用Object类的equals方法
boolean equals(Object obj) 指示其他那个对象是否与此对象“相等"。
equals方法源码:
public boolean equals(Object obj){
return (this == obj);
}
参数:
Object obj:可以传递任意的对象
== 比较运算符,返回的是一个布尔值 true false
基本数据类型:比较的是值
引用数据类型:比较的是两个对象的地址值
this是谁?哪个对象调用的方法,方法中的this就是哪个对象;p1调用的equals方法所以this就是p1
obj是谁?传递过来的参数p2
this == obj --> p1 == p2
*/
public class Demo02Equals {
public static void main(String[] args) {
Person p1 = new Person("迪丽热巴",20);
Person p2 = new Person("欧阳娜娜",19);
System.out.println("p1:"+ p1);
System.out.println("p2:" + p2);
p1 = p2;
boolean a = p1.equals(p2);
System.out.println(a); // true
}
}
package cn.code.Drmo007.Demo008;
import java.util.Objects;
public class Demo03Objects {
public static void main(String[] args) {
// String s1 = "abc";
String s1 = null;
String s2 = "Abc";
// boolean a = s1.equals(s2);
// System.out.println(a); // NullPointerException null是不能调用方法的,就会抛出空指针异常
/*
Objects类的equals方法:对两个对象进行比较,防止空指针异常
public static boolean equal(Object a,Object b){
return (a == b) ||(a != null && a.equals(b));
}
*/
boolean b= Objects.equals(s1,s2);
System.out.println(b); // false
}
}
19.3 重写Object类的equals方法
/*
Object类的equals方法,默认比较的是两个对象的地址值,没有意义
所以我们要重写equals方法,比较两个对象的属性(name,age)
问题:
隐含着一个多态
多态的弊端:无法使用子类特有的内容(属性和方法)
Object obj = p2 = new Person("迪丽热巴",19);
解决:可以使用向下转型(强转)把obj类型转换为person
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
// getClass() != o.getClass() 使用反射技术,判断o是否是Person类型 等效于 obj instanceof person
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
19.4 毫秒值的概念和作用
package cn.code.Demo008;
/*
java.util.Date:表示时间和日期的类
类 Date 表示特定的瞬间,精确到毫秒。
毫秒:千分之一秒 1000毫秒 = 1 秒
特定的瞬间:一个时间点,一刹那时间
毫秒值的作用:可以对时间和日期进行计算
2099-01-03 到 2088-01-01 中间一共有多少天
可以日期转换为毫秒计算,计算完毕,再把毫秒值转换为日期
把日期转化为毫秒:
当前的日期:2088-01-01
时间原点(0毫秒):1970-01-01 00:00:00 (英国格林威治)
就是计算当前日期到时间原点之间一共经历了多少毫秒
注意:
中国属于东八区,会把时间增加8个小时
1970-01-01 08:00:00
把毫秒转换为日期:
1天 = 24 X 60 = 86400 秒 = 86400000毫秒
*/
public class Demo01Date {
public static void main(String[] args) {
System.out.println(System.currentTimeMillis()); // 1568899718679
}
}
19.5 Date类的构造方法和成员方法
package cn.code.Demo008;
import java.util.Date;
public class Demo02Date {
public static void main(String[] args) {
demo03();
}
/*
Date类的空参数构造方法
Date()获取当前系统的日期和时间
*/
public static void demo01(){
Date date = new Date();
System.out.println(date);
}
/*
Date类的带参数构造方法
Date(Long date):传递毫秒值,把毫秒值转换为Date日期
*/
private static void demo02() {
Date date = new Date(0L);
System.out.println(date); // Thu Jan 01 08:00:00 CST 1970
date = new Date(1568899718679L);
System.out.println(date); // Thu Sep 19 21:28:38 CST 2019
}
/*
Long getTime() 把日期转换为毫秒值(相当于System.currentTimeMillis()方法)
返回自 1970-01-01 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
*/
private static void demo03() {
Date date = new Date();
long time = date.getTime();
System.out.println(time); // 1568901229085
}
}
19.6 DateFormat类的format方法和parse方法
package cn.code.Demo008;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
java.text.DateFormat:是日期/时间格式化子类的抽象类
作用:
格式化(也就是日期 -> 文本)、解析(文本 -> 日期)
成员方法:
String format(Date date) 按照指定的模式,把Date日期,格式化为符合模式的字符串
Date parse(String source) 把符合模式的字符串,解析为Date日期
DateFormat类是一个抽象类,无法直接创建对象使用,可以使用DateFormat类的子类
java.text.SimpleDateFormat extends DateFormat
构造方法:
SimpleDateFormat(String pattern)
用给定的模式和默认语言环境的日期格式符号构造 SimpleDateFormat
参数:
String pattern:传递指定的模式
模式:区分大小写的
y 年
M 月
d 日
H 时
m 分
s 秒
写对应的模式,会把模式替换为对应的日期和时间
“yyyy-MM-dd HH:mm:ss”
注意:
模式中的字母不能更改,连接模式的符号可以改变
“yyyy年MM月dd日 HH时mm分ss秒”
*/
public class Demo01DateFormat {
public static void main(String[] args) throws ParseException {
demo02();
}
/*
使用DateFormat类当中的方法parse,把文本解析为日期
使用步骤:
1. 创建SimpleDateFormat对象,构造方法中传递指定的模式
2. 调用SimpleDateFormat对象中的方法parse,把符合构造方法中模式的字符串,解析为Date日期
注意:
public Date parse(String sourse) throws ParseException
parse方法声明了一个异常叫ParseException
如果字符串和构造方法的模式不一样,那么程序就会抛出此异常
调用一个抛出了异常的方法,就必须的处理这个异常,要么throws继续抛出这个异常,要么try catch 自己处理
*/
private static void demo02() throws ParseException {
// 1. 创建SimpleDateFormat对象,构造方法中传递指定的模式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
// 2. 调用SimpleDateFormat对象中的方法parse,把符合构造方法中模式的字符串,解析为Date日期
Date date = sdf.parse("2019年09月20日 10时30分22秒");
System.out.println(date);
}
/*
使用DateFormat类中的方法format,把日期格式化为文本
使用步骤:
1. 创建SimpleDateFormat对象,构造方法中传递指定的模式
2. 调用SimpleDateFormat对象中的方法format,按照构造方法中指定的模式,把Date日期格式化为符合模式的字符串(文本)
*/
private static void demo01() {
// 1. 创建SimpleDateFormat对象,构造方法中传递指定的模式
SimpleDateFormat sdf = new SimpleDateFormat();
// 2. 调用SimpleDateFormat对象中的方法format,按照构造方法中指定的模式,把Date日期格式化为符合模式的字符串(文本)
// String format(Date date) 按照指定的模式,把Date日期,格式化为符合模式的字符串
Date date = new Date();
String d = sdf.format(date);
System.out.println(date);
System.out.println(d);
}
}
练习:计算一个人已经出生了多少天
package cn.code.Demo008;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
/*
练习:
请使用日期时间相关的API,计算出一个人已经出生了多少天。
分析:
1. 使用Scanner类中的方法next,获取出生日期
2. 使用DateFormat类中的方法parse,把字符串的出生日期,解析为Date格式的出生日期
3. 把Date格式的出生日期,转换为毫秒值
4. 获取当前的日期,转换为毫秒值
5. 使用当前日期的毫秒值 - 出生日期的毫秒值
6. 把毫秒差值转换为天(s/1000/60/60/24)
*/
public class Demo02Text {
public static void main(String[] args) throws ParseException {
// 1. 使用Scanner类中的方法next,获取出生日期
Scanner sc = new Scanner(System.in);
System.out.println("请输入您的出生日期,格式:yyyy-MM-dd");
String bir = sc.next();
// 2. 使用DateFormat类中的方法parse,把字符串的出生日期,解析为Date格式的出生日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date birs = sdf.parse(bir);
// 3. 把Date格式的出生日期,转换为毫秒值
long birsTime = birs.getTime();
// 4. 获取当前的日期,转换为毫秒值
long timeToday = new Date().getTime();
// 5. 使用当前日期的毫秒值 - 出生日期的毫秒值
long time = timeToday - birsTime;
// 6. 把毫秒差值转换为天(s/1000/60/60/24)200
System.out.println(time/1000/60/60/24); // 7037
}
}
19.7 Calendar类的常用成员方法
package cn.code.Demo008;
import java.util.Calendar;
import java.util.Date;
/*
Calendar类的常用常用方法:
public int get(int filed): 返回给定日历字段的值。
public void set(int field,int value): 将给定的日历字段设置为给定值 。
public abstract void add (int field,int amount): 根据日历的规则,为给定的日历字段添加或减去指定的时间量。
public Date getTime(): 返回一个表示Calendar时间值(从历元到现在的毫秒偏移量)的Date对象。
成员方法的参数:
int field: 日历类的字段,可以使用Calendar类的静态成员变量获取
public static final int YEAR = 1; 年
public static final int MONTH = 1; 月
public static final int DATE = 1; 月中的某一天
public static final int DAY_OF_MONTH = 1; 月中的某一天
public static final int HOUR = 1; 时
public static final int MINUTE = 1; 分
public static final int SECOND = 1; 秒
*/
public class Demo02Calendar {
public static void main(String[] args) {
demo04();
}
/*
public Date getTime(): 返回一个表示此Calendar时间值(从历元到现在的毫秒偏移量)的Date对象。
把日历对象,转换为日期对象
*/
private static void demo04() {
// 使用getInstance方法获取Calendar对象
Calendar c = Calendar.getInstance();
Date date = c.getTime();
System.out.println(date);
}
/*
public abstract void add (int field,int amount): 根据日历的规则,为给定的日历字段添加或减去指定的时间量。
把指定的字段增加/减少指定的值
参数:
int field: 传递指定的日历字段(YEAR,MONTH...)
int amount: 增加/减少指定的值
正数:增加
负数:减少
*/
private static void demo03() {
// 使用getInstance方法获取Calendar对象
Calendar c = Calendar.getInstance();
// 把年增加2年
c.add(Calendar.YEAR,2);
// 把月份减少3个月
c.add(Calendar.MONTH,-3);
// 把日期增加5天
c.add(Calendar.DATE,5);
int year = c.get(Calendar.YEAR);
System.out.println(year);
int month = c.get(Calendar.MONTH);
System.out.println(month);
int date = c.get(Calendar.DATE);
System.out.println(date);
}
/*
public void set(int field,int value): 将给定的日历字段设置为给定值。
参数:
int field: 传递指定的日历字段(YEAR,MONTH...)
int value: 给指定字段设置的值
*/
private static void demo02() {
// 使用getInstance方法获取Calendar对象
Calendar c = Calendar.getInstance();
// 设置年为2035
c.set(Calendar.YEAR,2035);
// 设置月为9月
c.set(Calendar.MONTH,9);
// 设置日为9日
c.set(Calendar.DATE,9);
// 同时设置年月日,可以使用set的重载方法
c.set(2022,06,15);
int year = c.get(Calendar.YEAR);
System.out.println(year);
int month = c.get(Calendar.MONTH);
System.out.println(month);
int date = c.get(Calendar.DATE);
System.out.println(date);
}
/*
public int get(int field): 返回给定日历字段的值。
参数:传递指定的日历字段(YEAR,MONTH...)
返回值:日历字段代表的具体的值
*/
private static void demo01() {
// 使用getInstance方法获取Calendar对象
Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
System.out.println(year);
int month = c.get(Calendar.MONTH);
System.out.println(month);
int date = c.get(Calendar.DATE);
System.out.println(date);
}
}
19.8 System类的常用方法
package cn.code.Demo009;
import java.util.Arrays;
/*
java.long.System类中提供了大量的静态方法,可以获取与系统相关的信息或系统级操作,在System类的API文档中,常用方法有:
public static long currenTimeMills(): 返回值以毫秒值为单位的当前时间。
public static void arraycopy(Object str,int srcPos,object dest, int destPos, int lengthh): 将数组中指定的数据拷贝到另一个数组中。
*/
public class Demo01System {
public static void main(String[] args) {
demo02();
}
/*
public static void arraycopy(Object str,int srcPos,object dest, int destPos, int length): 将数组中指定的数据拷贝到另一个数组中。
参数:
src - 源数组
srcPOS - 源数组中的起始位置(起始索引)
dest - 目标数组
destPos - 目标数据中的起始位置
length - 要复制的数组元素的数量
练习:
将src数组中的前3个元素,复制到dest数组的前3个位置上
复制元素前:
src数组元素[1,2,3,4,5],dest数组元素[6,7,8,9,10]
复制元素后:
src数组元素[1,2,3,4,5],dest数组元素[1,2,3,9,10]
*/
private static void demo02() {
// 定义源数组
int[] src = {1,2,3,4,5};
// 定义目标数组
int[] dest = {6,7,8,9,10};
System.out.println("复制前:" + Arrays.toString(dest)); // 复制前:[6, 7, 8, 9, 10]
// 使用System类中的arraycopy把src数组(源数组)中的前3个元素,复制到dest数组(目标数组)的前3个位置上
System.arraycopy(src,0,dest,0,3);
System.out.println("复制后:" + Arrays.toString(dest)); // 复制后:[1, 2, 3, 9, 10]
}
/*
public static long currenTimeMills(): 返回值以毫秒值为单位的当前时间。
用来测试程序的效率
验证for循环打印数字1-9999所需要的时间(毫秒)
*/
private static void demo01() {
// 程序执行前,获取一次毫秒值
long s = System.currentTimeMillis();
// 执行for循环
for (int i = 0; i < 9999; i++) {
System.out.println(i);
}
// 程序执行后,获取一次毫秒值
long e = System.currentTimeMillis();
System.out.println("共用时:" + (e - s) + "毫秒");
}
}
19.9 StringBuilder的原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-za2efLr4-1573821333479)(C:\Users\Think-Pad\Desktop\java\StringBuilder.jpg)]
19.10 StringBuilder的构造方法和append方法
package cn.code.Demo009;
/*
StringBuilder的常用方法:
piblic StringBuilder append(...): 添加任意类型数据的字符串形式,并返回当前对象自身。
*/
public class Demo02StringBuilder {
public static void main(String[] args) {
// 创建StringBuildrer对象
StringBuilder bu1 = new StringBuilder();
// 使用append方法往StringBuildrer中添加数据
// append方法返回值的是this
/* StringBuilder bu2 = bu1.append("abc");
System.out.println(bu1); // abc
System.out.println(bu2); // abc
System.out.println(bu1 == bu2); // true*/
// 使用append方法无需接受返回值
bu1.append("abc");
bu1.append(true);
bu1.append(5);
bu1.append(8.6);
bu1.append('中');
System.out.println(bu1); // abctrue58.6中
// 链式编程:方法返回值是一个对象,可以继续调用方法
bu1.append("abc").append(5).append(9.4).append('中'); // abctrue58.6中
}
}
第二十章 包装类
20.1 包装类的概念
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3osmlyIk-1573821333480)(C:\Users\Think-Pad\Desktop\java\包装类的概念.jpg)]
20.2 装箱与拆箱
package cn.code.Demo009;
import javax.sound.midi.Soundbank;
/*
装箱:把基本类型的数据,包装到包装类中(基本类型的数据 -> 包装类)
构造方法:
Integer(int value)构造一个新分配的 Integer 对象,它表示指定的 int 值。
Integer(String s)构造一个新分配的 Integer 对象,它表示String参数所指示的int值。
传递的字符串,必须是基本类型的字符串,否则会抛出异常“100”正确 “a”抛异常
静态方法:
static Integer valueOf(int i) 返回一个表示指定的int值的Integer实例。
static Integer valueOf(String s) 返回保存指定的String 的值的Integer对象。
拆箱:在包装类取出基本类型的数据(包装类 -> 基本类型的数据)
成员方法:
intValue() 以 int 类型返回该 Integer 的值
*/
public class Demo01Integer {
public static void main(String[] args) {
// 装箱:把基本类型的数据,包装到包装类中(基本类型的数据 -> 包装类)
// 构造方法
Integer int1 = new Integer(1);
System.out.println(int1); // 1 重写了toString方法
// 静态方法:
Integer int2 = Integer.valueOf(4);
System.out.println(int2); // 4
// Integer int3 = Integer.valueOf("c");
// System.out.println(int3); // NumberFormatException 数字格式化异常
// 拆箱:在包装类中取出基本类型的数据(包装类 -> 基本类型的数据)
int i = int1.intValue();
System.out.println(i); // 1
}
}
20.3 自动装箱与自动拆箱
package cn.code.Demo009;
import java.util.ArrayList;
/*
自动装箱与自动拆箱:基本类型的数据和包装类之间可以制动互相转换
JDK1.5之后出现的新特性
*/
public class Demo02Integer {
public static void main(String[] args) {
/*
自动装箱:直接把int类型的整数赋值包装箱
Integer in = 1;就相当于 Integer in = new Integer(1);
*/
Integer in = 1;
/*
自动装箱:in 是包装类,无法直接参与运算,可以自动转换为基本数据类型,再进行计算
in + 2;就相当于 in.intValue() + 2 = 3
in = in.intValue() + 2 = 3
*/
in = in +2;
System.out.println(in); // 3
ArrayList<Integer> list = new ArrayList<>();
/*
ArrayList集合无法直接储存整数,可以储存Integer包装类
*/
list.add(1); // --> 自动装箱 list.add(new Integer(1));
Integer a = list.get(0); // 自动拆箱 list.get(0).intValue();
System.out.println(a); // 1
}
}
20.4 基本类型与字符串类型
package cn.code.Demo009;
/*
基本类型与字符串类型之间的相互转换
基本类型 -> 字符串(String)
1. 基本类型的值 + "" 最简单的方法(工作中常用)
2. 包装类的静态方法toString(参数),不是Object类的toString()重载
static String to String(int i)返回一个表示指定整数的String对象。
3. String类的静态方法valueOf(参数)
static String vlueOf(int i) 返回int参数的字符串表示形式。
字符串(String) -> 基本类型
使用包装类的静态方法parseXXX("字符串");
Integer类:static int pareseInt(String s)
Double类:static double pareseDouble(String s)
*/
public class Demo03Integer {
public static void main(String[] args) {
// 基本类型 -> 字符串(String)
int i1 = 100;
String s1 = i1 + "";
System.out.println(s1 + 200); // 100200
String s2 = Integer.toString(100);
System.out.println(s2 + 200); // 100200
String s3 = String.valueOf(100);
System.out.println(s3 + 200); // 100200
// 字符串(String)-> 基本类型
int i = Integer.parseInt(s1);
System.out.println(i - 10); // 90
int a = Integer.parseInt("a");
System.out.println(a); // NumberFormatException
}
}
20.5 Collection集合概述
-
集合:集合是Java中提供的一种容器,可以用来存储多个数据。
集合和数组的区别:
-
数组的长度是固定的。集合的长度是可变的。
-
数组中存储的是同一类型的元素,可以存储基本数据类型。集合存储的都是对象。而且对象的类型可以不一致。在开发的中一般当对象多的时候,使用集合进行存储。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PQURPLkz-1573821333482)(C:\Users\Think-Pad\Desktop\java\Collection.jpg)]
20.6 Collection集合常用功能
package cn.code.Demo009;
import java.util.ArrayList;
import java.util.Collection;
/*
java.util.Collection接口
所有单列集合的最顶层的接口,里边定义了所有单列集合共性的方法
任意的单列集合都可以使用Collection接口中的方法
共性的方法:
public boolean add(E e): 把给定的对象添加到当前集合中。
public void clean(): 清空集合中所有的元素。
public boolean remove(E e): 把给定的对象在当前集合中删除。
public boolean contains(E e): 判断当前集合中是否包含给定的对象。
public boolean isEmpty(): 判断当前集合是否为空。
public int size(): 返回集合中元素的个数。
public Object[] toArray(): 把集合中的元素,存储到数组中。
*/
public class Demo01Collection {
public static void main(String[] args) {
// 创建集合对象,可以使用多态
Collection<String> coll = new ArrayList<>();
System.out.println(coll); // 重写了toString方法 []
/*
public boolean add(E e): 把给定的对象添加到当前集合中。
返回值是一个Boolean值,一般都返回true,所以可以不用接收
*/
boolean b1 = coll.add("张三");
System.out.println("b1 = " + b1); // b1 = true
System.out.println(coll); // [张三]
coll.add("田七");
coll.add("王五");
coll.add("赵柳");
coll.add("李四");
System.out.println(coll); // [张三, 田七, 王五, 赵柳, 李四]
/*
public boolean remove(E e): 把给定的对象在当前集合中删除。
返回值是一个Boolean值,集合值存在元素,删除元素,返回true
集合中不存在元素,删除失败,返回false
*/
boolean b2 = coll.remove("李四");
System.out.println("b2 = " + b2);
System.out.println(coll);
/*
public boolean contains(E e): 判断当前集合中是否包含给定的对象。
包含返回true
不包含返回false
*/
boolean b3 = coll.contains("王五");
System.out.println(b3);
/*
public boolean isEmpty(): 判断当前集合是否为空。集合为空返回true,集合不为空,返回false
*/
boolean b4 = coll.isEmpty();
System.out.println(b4);
/*
public int size(): 返回集合中元素的个数。
*/
int b5 = coll.size();
System.out.println(b5);
/*
public Object[] toArray(): 把集合中的元素,存储到数组中。
*/
Object[] arr = coll.toArray();
for (int i = 0; i < coll.size() - 1; i++) {
System.out.println(arr[i]);
}
/*
public void clean(): 清空集合中所有的元素。
*/
coll.clear();
System.out.println(coll); // []
System.out.println(coll.isEmpty()); // true
}
}
20.7 迭代器的代码实现
package cn.code.Demo009;
import javax.sound.midi.Soundbank;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
java.util.Iterator接口:迭代器(对集合进行遍历)
有两个常用的方法
boolean hasNext() 如果仍有元素可以迭代,则返回true
判断集合中还有没有下一个元素,有就返回true,没有就返回false
E next() 返回迭代的下一个元素
取出集合的下一个元素
Iterator迭代器是一个接口,我们无法直接使用,需要使用Iterator接口的实现类对象,获取实现类的方法比较特殊
Collection接口中有一个方法,叫iterator(),这个方法返回的就是迭代器的实现类对象
Iterator<E> iterator() 返回在此 collection 的元素上进行迭代的迭代器
迭代器的使用步骤(重点):
1. 使用集合中的方法iterator() 获取迭代器的实现类对象,使用Iterator接口接收(多态)
2. 使用Iterator接口中的方法hasNext判断还有没有下一个元素
3. 使用Iterator接口中的方法next取出集合中的下一个元素
*/
public class Demo01Iterator {
public static void main(String[] args) {
// 创建一个集合对象
Collection<String> coll= new ArrayList<>();
// 往集合中添加元素
coll.add("周杰伦");
coll.add("陈粒");
coll.add("欧阳娜娜");
coll.add("五月天");
/*
1. 使用集合中的方法iterator() 获取迭代器的实现类对象,使用Iterator接口接收(多态)
注意:
Iterator<E>接口也是有泛型的,迭代器的泛型跟着集合走,集合是什么泛型,迭代器就是什么泛型
*/
// 多态 接口 实现类对象
Iterator<String> it = coll.iterator();
/*
发现使用迭代器取出集合中元素代码,是一个重复的过程
所以我们可以使用循环优化
不知道集合中有多少元素,使用while循环
循环结束的条件,hasNext方法返回false
*/
while(it.hasNext()){
System.out.println(it.next());
}
for (Iterator<String> it2 = coll.iterator();it2.hasNext();){
System.out.println(it2.next());
}
// 2. 使用Iterator接口中的方法hasNext判断还有没有下一个元素
boolean b = it.hasNext();
System.out.println(b);
// 3. 使用Iterator接口中的方法next取出集合中的下一个元素
String next = it.next();
System.out.println(next);
}
}
20.8 迭代器的原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MEP7FJya-1573821333484)(C:\Users\Think-Pad\Desktop\java\迭代器的原理.jpg)]
20.9 增强for循环
package cn.code.Demo009;
import java.util.ArrayList;
/*
增强for循环:底层使用的也是迭代器,使用for循环的格式,简化了迭代器的书写
是JDK1.5之后出现的新特性
Collection<E>extends Iterable<E>: 所有的单列集合都可以使用增强for
public interface Iterable<T>实现这个接口允许对象成为“foreach”语句的目标
增强for循环:用来遍历集合和数组
格式:
for(集合/数组的数据类型 变量名: 集合名/数组名)
sout(变量名);
*/
public class Demo02Foreach {
public static void main(String[] args) {
demo2();
}
// 使用增强for循环遍历集合
private static void demo2() {
ArrayList<String> list = new ArrayList<>();
list.add("杜海涛");
list.add("何炅");
list.add("谢娜");
list.add("张杰");
for (String a: list){
System.out.println(a);
}
}
// 使用增强for循环遍历数组
private static void demo1() {
int[] a = {1,2,3,};
for(int b: a){
System.out.println(b);
}
}
}