文章目录
- 第一章、java环境搭建
- 1.1、Java介绍
- 1.1.1、 Java开发平台
- 1.1.2、 Java开发环境搭建
- 1.1.3 、Java专业术语
- 1.1.4、 第一个Java程序
- 1.1.5、 练习
- 1.2、main方法
- 1.3、变量
- 1.3.1、 变量介绍
- 1.3.2 、练习
- 1.3.3、 变量名规范
- 1.3.4 、注释
- 1.4、数据类型
- 1.4.1、 整数
- 1.4.2、 直接量
- 1.4.3 、小数
- 1.4.4、 布尔类型
- 1.4.5、 字符
- 1.5、数据类型转换
- 第二章、运算符
- 2.1、算数运算符
- 2.2、比较运算符
- 2.3、自增减运算符
- 2.4、逻辑运算符
- 2.5、三目运算符
- 2.6、赋值运算符
- 2.7、运算符优先级
- 第三章、分支结构
- 3.1、流程控制介绍
- 3.2、单路分支
- 3.3、双路分支
- 3.4、多路分支
- 3.5、switch...case多路分支
- 3.6、练习
- 第 4 章、循环结构
- 4.1、循环介绍
- 4.2、for循环
- 4.3、课堂练习:
- 4.4、无限循环
- 4.5、while循环
- 4.6、do...while循环
- 4.7、break、continue
- 4.8、练习:
- 第 5 章、嵌套循环
- 5.1、打印矩形
- 5.2、打印三角形
- 5.3、打印图形
- 5.4、练习:
- 第 6 章、数组
- 6.1、数组介绍
- 6.2、数组相关概念
- 6.3、声明数组
- 6.3.1、 动态初始化数组
- 6.3.2、 静态初始化数组
- 6.4、数组操作
- 6.4.1、练习:
- 6.5、练习
- 6.6、多维数组
- 6.7、数组特点
- 6.8、练习
- 第 7 章、数组练习
- 7.1、二分查找
- 7.2、冒泡排序
- 7.2.1、 冒泡排序流程:
- 7.2.2 、优化:
- 7.3、数组练习
- 第 8 章、面向对象(一)
- 8.1、包
- 8.2.1、 包的介绍
- 8.2.2、 创建包:
- 8.2.3、包导入
- 8.2.4、 系统包
- 8.2eclipse、安装与使用
- 8.3、类与对象
- 8.3.1、 定义类
- 8.3.2、 实例化对象
- 8.3.3、 引用的概念
- 8.3.4、 访问对象成员
- 8.4、内存空间
- 8.5、null
- 第 9 章、面向对象(二)
- 9.1、成员方法介绍
- 9.2、形参
- 9.3、实参
- 9.4、返回值
- 9.5、局部变量
- 9.6、方法传参细节
- 9.7、构造方法
- 9.8、this关键字
- 第 10 章、面向对象(三)
- 10.1、方法重载
- 10.2、方法重载的意义
- 10.3、递归
- 10.4、递归练习
- 10.5、静态成员介绍
- 10.6、注意事项
- 10.7、静态代码块
- 第 11 章、内部类与Java常用API(一)
- 11.1、内部类介绍
- 11.2、匿名内部类
- 11.3、Java常用的包
- 11.4、Object类
- 11.5、包装类
- 11.6、装箱、拆箱
- 第 12 章、Java 常用API(二)
- 12.1、Integer类
- 12.2、java.math包
- 12.3、String类
- 练习
- 12.4、String缓冲类
- 12.5、Date类
- 12.6、SimpleDateFormat类
- 练习
- 12.7、Calendar类
- 12.7.1、 获取方式
- 12.7.2、 常用方法:
- 12.7.3、 get/set方法
- 12.7.4、 add方法
- 12.7.5、 getTime方法
- 第 13 章、集合概述
- 13.1、集合介绍
- 13.2、集合分类
- 13.3、泛型
- 13.4、泛型标识符
- 13.5、Collection集合常用方法
- 13.6、Collection集合遍历
- 13.6.1、 迭代器
- 13.6.2、 增强版for循环
- 13.7、练习
- 第 14 章、List集合
- 14.1、List集合概述
- 14.2、面试题
- 14.3、ArrayList
- 14.4、LinkedList
- 14.5、List接口方法
- 第 15 章、Set集合
- 15.1、Set接口概述
- 15.2、HashSet
- 15.3、自然排序
- 15.4、自定义排序
- 练习:
- 第 16 章、Map接口
- 16.1、Map集合介绍
- 16.2、Map集合常用的方法:
- 16.3、课堂练习:
- 16.4、HashMap存储结构
- 第 17 章、学生信息管理系统![在这里插入图片描述](https://s2.51cto.com/images/blog/202312/25125501_65890b25883b339564.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)
- 17.1、声明Student类
- 17.2、搭建学生管理系统的界面
- 17.3、添加学生
- 17.4、查询所有学生
- 17.5、修改学生信息
- 17.6、删除学生
- 17.7、退出管理系统
第一章、java环境搭建
1.1、Java介绍
1.1.1、 Java开发平台
Java SE(java standard edition),java平台标准版,主要编写桌面应用程序
Java EE(java enterprise edition),java平台企业版,用于构建企业级应用。所谓企业级应用是指那些为商业组织、大型企业而创建的应用系统,例如:电信的“计费系统”、银行的“网银系统”、企业中的“客户关系管理系统”等等。
Java ME(java micro edition), java平台微型版,随着Android智能平台的迅速普及,java me已经走向淘汰
1.1.2、 Java开发环境搭建
jdk,Java Development Kit,Java开发工具包,里面包含Java开发用到的工具类
jre,Java Runtime Environment,Java运行时环境,运行java代码所需要的环境
下载:
http://www.oracle.com/technetwork/java/javase/downloads/java-archive-downloads-javase7-521261.html 先卸载:
控制面板----卸载程序—
安装:
注意:安装路径不能有中文、特殊字符(中文字符)
安装jre
测试一下:
打开cmd控制台:
右击开始按钮----运行----输入cmd----确定
说明windows操作系统没有找到java开发环境需要配置环境变量
操作系统在运行时,需要的一些配置参数,默认情况下,当我们运行一个软件时,会先去环境变量的Path中找该软件所在的目录
配置环境变量:
如果提示下面的内容,说明安装成功
1.1.3 、Java专业术语
- jdk,Java Development Kit,Java开发工具包,里面包含Java开发用到的工具类
- jre,Java Runtime Environment,Java运行时环境,运行java代码所需要的环境
- JVM,Java Virtual Machine,Java虚拟机
- javac.exe,java编译器,用于将高级源代码文件转换为字节码文件
- java.exe,java解释执行器,用于将字节码文件通过java虚拟机解释并执行起来
1.1.4、 第一个Java程序
编写java代码的步骤:
1.新建记事本文档,将文件名修改为:xxx.java
注意:java的文件名要采用驼峰法的命名,每个单词的首字母必须大写
2.使用记事本打开该文件,并编写HelloWorld类
3.先编译
将高级的源代码解释成计算机能够识别的字节码文件(二进制文件)
javac 文件名
4.执行执行编译的结果
java 文件名(不包含后缀)
1.1.5、 练习
1.卸载java开发环境、删除java环境变量、删除创建的文件夹
2.重新安装java开发环境
要求:
jdk安装到D:/java_env/java8/jdk目录下
jre安装到D:/java_env/java8/jre目录下
如果没有D盘,把上述路径中的D改为C
然后添加到环境变量
3. 创建Dog类文件,并在该文件中输出”小狗汪汪叫”
1.2、main方法
1.语法格式
public static void main(String[] args){
}
1.3、变量
1.3.1、 变量介绍
度,尺子
量,容器
衡,称,重量单位
量,古代的一种容器
在java中,变量就是存储数据的容器,由于该容器的内容可以变化,所以称为变量
1 + 1 = ?
a + b = ? a代表数字的:是一个变量
变量,本质上就是在内存中申请的一块区域,通过变量名找到这个区域
由于变量中存储的内容不同,所占内存空间的大小也就不一样,在java中通过数据类型约束内存空间的大小、结构
例如:
String 类型表示字符串,只能存储字符类型的数据
int表示整数类型,只能存储整数类型的数据
double表示小数,只能存储小数类型的数据
1 ==> 1
2 == 10
3 == 11
4 == 100
255 == 11111111
Int类型 表示一般用的整数 ==> 32位 , 255255255*255
声明变量语法:
数据类型 变量名 = 初始值;
初始值可以省略
=,表示赋值运算符,表示将将=右边的数据存储到左边的容器(变量)里面
例如:
int age = 20; 表示将20存储到age变量
输出变量里面的内容
System.out.println(age);
1.3.2 、练习
有3瓶酒,1瓶红酒,1瓶白酒,要求使用java变量的相关知识,将白酒和红酒对调一下
1.3.3、 变量名规范
变量名采用小写,尽量使用英文单词,或拼音代替
变量名不要使用java中的关键字,例如:public、class、void等
望文知意,通过变量名知道变量的作用、意义
1.3.4 、注释
java中的注释分为:
注释是给程序员看的,对代码进行说明,java编译器会忽略注释的内容
单行注释: // 注释的内容(// 和 注释内容之间有且只有一个空格)
多行注释: /* 注释的内容 */
1.4、数据类型
在java中数据类型,有2种:
1.基本数据类型:包括:整数、小数、布尔、字符
2.引用数据类型(数组、对象、接口等)
1.4.1、 整数
了解计算机中单位:
1TB = 1024GB
1GB = 1024MB
1MB= 1024KB(Kilo千)
1KB =1024Byte(字节)
byte,在内存中占1个字节(Byte),表示范围:-128 ~ 127
short,在内存中占2个字节,大概3万多
int,在内存中占4个字节,20多亿
long,在内存中占8个字节
通常int使用比较多
1.4.2、 直接量
byte b1 = -128, -128称为直接量
对于整数类型的直接量,默认是int类型,而int类型表示的范围:20多亿
如果希望表达的是Long类型的话,在直接量的后面加上L 或 l(小写的L)
1.4.3 、小数
float,占4个字节
double,占8个字节
对于小数类型的直接量,默认是double类型,如果希望表达的是float类型,需要在小数后面加上 F 或 f
1.4.4、 布尔类型
boolean
在java语言中,用于描述真假信息的数据类型是:boolean,只有两个值:
.true、false
.在内存中占1个字节空间
1.4.5、 字符
char
在java中,char类型(字符类型)描述单个字符,例如:’a’ ‘中’等
注意:字符类型必须使用 单引号 包裹
计算机底层只认识 01 二进制,整数 10 容易计算二进制数字
但是字符a如何计算二进制
并不是把a字符存储到内存中,而是在ASCII码表中建立字符和整数映射关系
a----97
计算机存储时,存储的是97,将来获取的也是97,再通过97映射关系找到对应的a字符
1.5、数据类型转换
自动类型转换
从小范围向大范围的转换,这个是编译过程自动完成的
强制类型转换
语法格式:目标类型 变量名 = (目标类型)原变量;
例如:
int a = 5;
double d1 = (double)a;
第二章、运算符
2.1、算数运算符
( + -* / %)
%,两数相除,取余数,例如: 10 % 3 = 1
/,除法运算,注意:结果和参与运算数字的类型保持一致
例如:int a = 10; int b = 3; a / b = 3;
+法运算,除了表示 四则运算之外,还用来表示字符串连接
小练习:
2.2、比较运算符
比较运算符:> < == >= <= !=
比较运算符的结果,都是布尔类型,例如:
5 > 3,理解:5是否大于3
2.3、自增减运算符
++,自增运算符,让当前的变量的值 + 1
–,自减运算符,当前变量的值 – 1
前++,前–,先值增,再运算
后++,后–,先运算,再值增
2.4、逻辑运算符
逻辑运算符有3个:
&&
逻辑与“并且”,运算符两边的条件都成立的时候,整个表达式的结果才成立
同真为真,一假为假
|| 逻辑或“或者”,运算符两边的条件有一个成立,整个表达式的结果就成立
一真为真,同假为假
! 取反,真为假,假为真
逻辑运算符,存在短路特性:
其中,对于逻辑与来说,如果第一个条件为false,则后面的表达式不再执行
其中,对于逻辑或来说,第一条件为true时,则后面的表达式不再执行
2.5、三目运算符
语法格式:条件表达式 ? 表达式1 : 表达式2;
描述:如果 ? 前面的条件表达式成立(true),则执行表达式1,如果前面的表达式不成立,则执行表达式2
举例:
小孩子如果大于等于18岁,则可以光明正大上网,如果小于18岁,则偷偷摸摸上网;
小练习:
1.提示用户输入一个正整数,判断并输出是否为二位数
2.提示用户输入考试成绩,判断并提示成绩是否及格
3.提示用户输入一个整数,并判断该整数是负数还是非负数
2.6、赋值运算符
=,将 = 右边的值 赋值给左边的变量
java还提供了如下赋值运算符:
+=、-=、*=、/=、%=
以 += 为例进行演示
int a = 10;
a += 5; // 将a变量 + 5之后,再赋值给a变量,等价于:a = a + 5;
经典面试题:
比较 a += 5 和 a = a + 5的区别
a += 5,隐含了强制类型转换,严格来说等价于:a = (byte)(a + 5)
2.7、运算符优先级
同一级别中, * / 优先级要高于 + -
乘除优先级 > 加减 > 赋值运算符
int c = 5 + 2 * 4;
可以使用 () 提升优先级,例如:
int c = (5+2) * 4
就会先运算() 里面的表达式
第三章、分支结构
3.1、流程控制介绍
Java三大语句结构:顺序结构、分支结构、循环结构
代码在执行过程汇总,可能会遇到各种不同的情况,每一种情况,我们就称为一个分支。
分支分为:单路分支、双路分支、多路分支
3.2、单路分支
代码执行过程中,只遇到一种情况,只做一次判断
语法格式:
if(条件表达式){
语句块;
}
如果条件表达式成立(条件表达式的结果为 true),则执行语句块
举例演示:
小练习:
提示用户输入四个整数,然后求出其中的最大值并打印
3.3、双路分支
双路分支,代码在执行过程中,有两种情况
语法格式:
if(条件表达式){
// 代码块1
}else{
// 代码块2
}
执行流程:
1.先判断条件表达式是否成立(是否为true)
2.如果成立(true),则执行代码块1
3.如果不成立(false),则执行代码块2
举例说明:
3.4、多路分支
代码在执行过程中,出现多种情况,称为多路分支
语法格式:
if(条件表达式1){
//代码块1
}else if(条件表达式2){
//代码块2
}else if(条件表达式3){
//代码块3
}…
else{
// 代码块4
}
执行流程:
1.先判断条件表达式1是否成立(true)
2.如果成立,则执行代码块1
3.如果不成立,则执行条件表达式2
4.如果条件2成立,则执行代码块2,如果不成立,则继续判断条件3
5.以此类推
6.如果上述条件都不成立,则执行else里面的代码
代码演示
如果我现在有超过50000块钱,我就去泰国旅游
如果我现在有超过5000块钱,我就去大草原大口吃肉,大碗喝酒
如果现在有超过1000块钱,去小树林一日游
如果连1000都没有,好好撸代码
3.5、switch…case多路分支
switch(condition ){
case 值1:
代码块1;
break;
case 值2:
代码块2;
break;
…
default:
代码块3;
break;
}
执行流程:
1.先判断switch中condition条件的值
2.如果condition的值等于值1,则执行第一个case语句块
3.如果condition的值等于值2,则执行第二个case语句块
4…
5.如果case值都不等于condition变量,则执行default
if、else 和 switch case的区别
if(age > 18),if的条件表示:区间、范围
switch…case 固定的几个点,例如:方向、星期()
如果case中,没有break,会一直向下执行,直到遇到break为止,这种情况我们称为”case 穿透”
3.6、练习
提示用户输入一个表示年份的整数,判断这一年是否是闰年。
如何判断 一个年份是否是闰年:
- 如果这个年份能够被4 整除,且不能被100 整除,则这一年是闰年。
例 如,1996 年是闰年,而相应的,1993 年就不是闰年。 - 如果这个年份能够被100 整除,则这个数必须要能被400 整除,才是闰 年。
例如,2000 年是闰年,1900 年不是闰年。
第 4 章、循环结构
4.1、循环介绍
循环,又称 重复执行
计算机最强大的功能之一就是:帮我们做一些重复性的工作
for循环,又称为计数循环,明确要循环多少次
while循环,又称为条件循环,只要符合while里面的条件,就重复执行
4.2、for循环
语法格式:
for(初始变量; 条件表达式; 初始变量修改表达式){
代码块1;
}
代码块2
执行流程:
1.先在内存中初始一个变量
2.判断初始变量是否符合条件表达式
2.1符合条件,执行代码块1; 修改初始变量
2.2不符合条件,退出循环,执行代码块2
代码演示:
4.3、课堂练习:
计算1-100之间数字的和
计算1-10之间的累积并打印出来(123*…10)
打印所有三位数的水仙花数(所谓的水仙花数是指,一个数字的个位、十位、百位的立方和等于这个数本身)
4.4、无限循环
无限循环,又称为 ”死循环”
for(;😉{},像这种没有指定循环条件的循环,我们称为 无限循环 或 “死循环”
无限循环,通常要结合break使用
模拟猜数字的游戏
4.5、while循环
while单词,意思:当…时候、 只要…
while循环,称为条件循环
语法格式:
while(条件表达式){
代码块1;
// 条件修改代码块
}
代码块2;
执行流程:
1.判断条件表达式是否成立(true)
2.如果成立,执行代码块1,然后修改条件
3.执行修改之后的条件和条件表达式进行比较…
4.如果条件不成立,则退出循环,执行代码块2
代码演示:
使用while循环,输出1 到 100 直接的奇数
也可以通过while循环实现无限循环(死循环):
while(true){
}
4.6、do…while循环
语法格式:
do{
先执行一次
}while(条件表达式);
执行流程:
一上来先执行do里面的代码块,再判断条件
4.7、break、continue
break和continue相同点是:都是跳出循环
不同点在于:
break,跳出整个for循环,for循环结束
continue,跳出本次循环,后续的循环继续
4.8、练习:
使用for循环打印1 -20之间的整数,遇到5的倍数时,提示此数是5的倍数,遇到3的倍数时,提示此数是3的倍数,如果是5和3的倍数,提示此数是5和3的倍数
第 5 章、嵌套循环
5.1、打印矩形
循环里面,再嵌套循环
嵌套循环输出上面的星星
5.2、打印三角形
第一行 1颗星 4个空白
第二行 2颗星 3个空白
第三行 3颗星 2个空白
第四行 4颗星 1个空白
第五行 5颗星 0个空白
5.3、打印图形
使用循环打印下面的图形
print()
println()换行
5.4、练习:
有红白黑3种球若干个,其中红白球25个,白黑球共31个,红黑球共28个,求这三种球各有多少个?
鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,问鸡翁、鸡母、鸡雏各几何?
反向输出一个正整数,不确定是几位数,例如:123反向输出为321
第 6 章、数组
6.1、数组介绍
变量,一个变量只能存储一个数据,例如:int a = 10; char s = ‘中’
数组,用来存储多个数据的
数组,本质上就是在内存中申请的一段连续空间,用来存储多个数据类型相同的数据。
6.2、数组相关概念
数组名,指向数组在内存空间中的地址,通过数组名找到该空间
数组元素,数组中存储的数据、内容
数组长度,数组中元素的个数,通过数组名.length 属性获取
数组下标,每个数组元素在数组中的编号(序号),该编号是从0开始
我们通过下标对数组元素进行操作
数组特点:
一旦声明数组,则长度是固定的,不能增加、不能删除
6.3、声明数组
在java中,声明数组有2种方式:
6.3.1、 动态初始化数组
先创建数组,并分配空间,然后再分别为数组中的元素赋值
语法格式:
数据类型[] 数组名 = new 数据类型[数组长度];
例如:声明一个int类型的数组,初始长度为5
int[] arr = new int[5];
6.3.2、 静态初始化数组
所谓的静态初始化数组,就是声明数组的同时,指定该数组的元素
语法格式:
数据类型[] 数组名 = {元素1,元素2…};
例如:
int[] arr = {1,3,5,7,9};
6.4、数组操作
对数组的操作,是通过下标进行操作的
数组元素访问:数组名[下标];
修改数组元素的值:数组名[下标] = 新的值;
6.4.1、练习:
声明一个double类型的数组,长度为5,将第三个元素设置为3.14,然后打印该元素的值
6.5、练习
声明一个数组,长度为5,初始值为:[10,20,30,40,50]
查找数组中值为30的元素并把下标打印出来,并将元素30改为300
最后,输出所有元素的值
方式2:通过静态数组实现
6.6、多维数组
java支持多维数组,不过最常用的二维数组
二维数组,就是一维数组元素的值为一维数组的,例如:
{
{},
{}
}
三维数组,数组元素为二维数组的
{
{
{},{},{}
}
}
一维数组,展现形式是一条线,例如:{10,20,30,40,50}
二维数组,展现形式是面(x轴、y轴)x轴控制行数,y轴控制列数
二维数组的声明方式:
数据类型[][] 数组名称 = new 数据类型[行数][列数]
行数,控制二维数组有几个元素
列数,控制每一行里面的元素个数
如:int[][] arr = new int[2][6]; 声明一个具有2行6列的二维数组
6.7、数组特点
- 数组是引用数据类型
- 数组的长度是固定的,也就是说可以存储固定个数的数据
- 数组中的元素的类型必须一致,也就是说数组中存储的多个数据的数据类型一致
6.8、练习
根据用户输入的班级人数来确定数组的长度,再输入每个学生的考试成绩并保存到一维数组中,然后,根据该数组的所有成绩计算出本班的最高分、总分以及平均分,最后打印出来。
先遍历二维数组
![在这里插入图片描述]()
自定义三维数组,并遍历三维数组(循环输出每个元素的值)
第 7 章、数组练习
7.1、二分查找
二分查找,又称为折半查找
举例:图书馆借书,出门时警报灯响了,排查是哪本书有问题?
如果按照线性查找,则一本一本的排查,效率较低
推荐使用二分查找,先将书拆分成2部分,分别比较(排查),
在从排查的结果中再拆分成2部分
例如:从下面的数列中查找90
10 20 30 50 60 80 90
算法流程:
1.假设给定的数列是有序的
2.从数列中查找中间元素,并保存
3.拿目标元素和中间元素进行比较
4.如果目标元素大于中间元素,则去中间元素的右边查找
5.如果目标元素小于中间元素,则去中间元素的左边查找
6.重复执行步骤3,采用递归的思想
代码演示:
二分查找,查找失败时,要给定出口
测试:
使用while循环优化
使用递推实现
递归,方法内部调用方法自己
7.2、冒泡排序
冒泡排序,是用来对数组元素进行排序的
7.2.1、 冒泡排序流程:
算法流程:
a. 比较相邻位置两个元素的大小,若第一个元素比第二个元素大,则交换两个元素的位置
b. 从开始的第一对一直比较到结尾的最后一对,最后的元素将是这组元素的最大值
c. 重复步骤b持续对越来越少的元素进行比较,直到处理完毕所有元素为止(任何相邻位置的两个元素都不需要交换为止)
7.2.2 、优化:
如果给定的一组数据就是有序的,没必要遍历所有轮
7.3、数组练习
1.给定一个数组,判断数组中所有元素是否全部小于0
2.统计数组中重复元素出现的次数
3.定义一个方法,获取某个数组中的最小值
第 8 章、面向对象(一)
8.1、包
8.2.1、 包的介绍
为了更好地组织类,防止类名的命名冲突,Java 提供了包机制,可以理解为包就是给类名增加的命名空间。
包的作用:
1、把功能相似或相关的类或接口组织在同一个包中,方便查找和使用。
2、如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
3、包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。
8.2.2、 创建包:
Java 中使用 package 语句定义包,package 语句应该放在源文件的第一行
Java 包的命名规则如下:
包名全部由小写字母(多个单词也全部小写)。
如果包名包含多个层次,每个层次用“.”分割,比如:com.baidu.oop.Test1
其中,com.baidu 是公司域名的反写
其中,oop,是项目名称或模块名称
其中,Test1 是类名
自定义包不能 java 开头。
8.2.3、包导入
如果使用不同包中的其它类,需要使用该类的全名(包名+类名)。代码如下:
example.Test test = new example.Test();
其中,example 是包名,Test 是包中的类名,test 是类的对象。
为了简化编程,Java 引入了 import 关键字,import 可以向某个 Java 文件中导入指定包层次下的某个类或全部类。
import 语句位于 package 语句之后,类定义之前。一个 Java 源文件只能包含一个 package 语句,但可以包含多个 import 语句。
使用 import 导入单个类的语法格式如下:
import 包名+类名;
上面语句用于直接导入指定类,例如导入前面的 example.Test 类,代码如下:
import example.Test;
使用 import 语句导入指定包下全部类的用法按如下:
import example.*;
上面 import 语句中的星号(*)只能代表类,不能代表包,表明导入 example 包下的所有类。
8.2.4、 系统包
Java SE 提供了一些系统包,其中包含了 Java 开发中常用的基础类。
8.2eclipse、安装与使用
解压之后将可执行文件,添加到桌面快捷方式
双击快捷方式打开文件
需要选择一个工作目录(代码保存目录)
新建Java工程
File----New—Java Project
新建、执行Java文件
新建Java文件
新建Java文件,需要先创建包
eclipse中快捷键基本使用:
alt + /, 补全代码
syso + alt+/,补全System.out.println();
执行java文件
当我们使用eclipse编写完代码之后,eclipse自动进行代码编译(javac )
我们不需要再次编译,直接执行即可
右击Java文件----Run as-----Java Application
eclipse调整字体大小
8.3、类与对象
类:是对于同一类事物的抽象,例如:人类、猫类、客户类、雇员类…
对象:是对一个类的具体的表现,例如:刘邦、项羽…
类与对象关系:
类,是对象的模板,一个类可以构造多个对象
对象,是类的实体
例如:可以把类, 看做是做蛋糕的模子, 对象看做是模子造出来的蛋糕
蛋糕长什么样子,取决于模子(类)
8.3.1、 定义类
定义类的语法格式:
修饰符 class 类名{
}
例如:
public class Person{
}
Java类包含5种成员:成员变量、方法、构造器、初始化块、内部类(包括接口、枚举)5种成员。目前重点掌握:成员变量、成员方法、构造器
成员变量,用来描述类的特征、属性的
声明成员变量的语法格式:
修饰符 数据类型 变量名 = 初始值; // 初始值可以省略,建议不写
例如:
public class Person{
public String name;
public String gender;
public int age;
}
8.3.2、 实例化对象
语法格式:new 类名();
构造对象,本质上是在内存的堆区开辟一块空间,来保存对象的成员变量信息
如下图所示:
8.3.3、 引用的概念
我们通过new 类名() 这种方式构造的对象,称为匿名对象,也就是没有名字的对象。
为了能够标识该对象,我们需要声明变量,来指向对象在堆区的地址
当我们使用引用数据类型定义的变量名,记录对象在堆区中的内存地址时,通常称为引用。
除8种基本数据类型之外,用类名、数组名、接口声明的变量,称为引用类型变量,简称引用。
语法格式:
引用数据类型 变量名 = new 类名();
例如:
Person p = new Person();
称为,声明一个Person类型的引用p,指向在堆区new的Person对象
8.3.4、 访问对象成员
访问对象的成员变量:引用名.成员变量名
例如:System.out.print(p.name);
修改对象的成员变量:引用名.成员变量 = 值;
例如:p.name = “西施”;
8.4、内存空间
8.5、null
null,空的,引用没有指向堆区的任何对象
假设我们调用空对象的成员信息时,会报一个NullPointerException(空指针异常)
代码演示:
第 9 章、面向对象(二)
9.1、成员方法介绍
成员方法,就是在类体中定义的方法,作用是对特定功能代码的封装
语法格式:
修饰符 返回值类型 方法名(形参列表){
}
方法的作用:
方法就是对特定逻辑功能代码的打包,从而实现代码的复用,提高代码的可维护性。
多个对象会生成多个成员属性,但是多个对象访问的成员方法是相同的
9.2、形参
形参,声明方法时定义的参数变量,用来接收方法调用者传递进来的真实数据
语法格式:
方法名(数据类型 变量名){
}
形参列表,是指,如果需要接收多个数据,需要使用 逗号将多个形参连接
例如:
数据类型 变量1,数据类型 变量2…
public String buyBread(String name, double price){
}
9.3、实参
实参,真实的参数,调用方法时,传递到方法内部的真实数据
语法格式:
引用名.成员方法(真实的数据列表); 多个数据用逗号隔开
注意:形参和实参要一一对应
例如:
p.buyBread(“法式小面包”, 5.00);
9.4、返回值
返回值,就是由方法体内,向方法的调用者返回的数据
例如:返回的数据为int类型,那么返回值类型就是int
返回的数据是String类型,那么返回值类型就是String
如果没有返回值,返回值类型就是void
在方法内部使用return关键字返回结果
例如:
public String buyBread(){
return “面包”;
}
9.5、局部变量
局部变量,是在方法体内、方法体上(形参)声明的变量
语法格式:
public void buyBread(){
double price = 3.14; //局部变量
}
成员变量,是在类体中定义的变量
public class Person{
public int age = 30; //成员变量
}
作用范围不同:
局部变量:方法体内
成员变量:类体中
在内存中的位置:
局部变量:栈区
成员变量:堆区
生命周期:
局部变量:调用方法时创建,方法执行完毕自动销毁
成员变量:随着对象的创建而创建,随着对象的消失而消失
9.6、方法传参细节
当基本数据类型作为参数传递到方法体内时,采用值拷贝,所以形参的改变不会影响到实参
当引用数据类型作为参数传递到方法体内时,采用引用传递,所以形参的改变会影响到实参
图解说明:
代码演示:
9.7、构造方法
构造方法,就是在类中和类名同名的方法,而且没有返回值的方法
其作用,就是用来给成员变量初始值的
其特点,当我们实例化一个对象时,会自动的执行构造方法
构造方法分为:无参构造方法、有参构造方法
其中,无参构造方法,没有形式参数的构造方法
如果没有写无参构造方法,java的编译器会自动添加无参构造方法,如果自定义了构造方法,则编译器不再提供
其中,有参构造方法,就是有形式参数的构造方法
1.没有构造方法时,要想给成员变量初始值,需要先构造对象,然后在给属性赋值,如果属性比较多,代码就显得很繁琐
2.通过构造方法给成员变量初始值
9.8、this关键字
this,这个,在编程中,this特指当前对象,正在构造的对象
上面name=name,将name形参赋值给成员变量name,但是用户读起来容易产生歧义,所以通常使用this关键字加以区分
第 10 章、面向对象(三)
10.1、方法重载
overload,重载
概念:在一个类中,可以声明多个同名的方法,然后通过参数的不同加以区分,这就称为方法的重载
参数不同体现在如下方面:参数个数不同、参数数据类型不同、参数的顺序不同
当我们在调用方法时,编译器会根据传递的实参加以区分,例如:
package com.zhentao.oop;
public class Payment {
//参数个数不同
public void pay(){
System.out.println("默认现金支付方式...");
}
//参数类型不同
public void pay(String payment){
System.out.println(payment);
}
public void pay(int num){
System.out.println(num);
}
//参数顺序不同
public void pay(String payment,int num){
System.out.println(payment+num);
}
public void pay(int num,String payment){
System.out.println(payment+num);
}
public static void main(String[] args) {
Payment p = new Payment();
p.pay();
p.pay("微信支付...");
p.pay("支付宝支付", 200);
}
}
10.2、方法重载的意义
方法重载的意义在于,只需要记住一个方法名就可以调用各种不同的版本来实现不同的效果
10.3、递归
在方法内部,调用该方法本身,就称为递归调用,而该方法称为递归方法(函数)
以阶乘为例进行演示
1!= 1
2!= 2 * 1!
3!= 3 * 2!
4!= 4 * 3!
5!= 5*4!
…
使用java计算n的阶乘
注意事项:使用递归时,必须指定一个出口(递归结束的条件),否则陷入死循环
package com.zhentao.oop;
public class JieCheng {
// 自定义方法,计算n的阶乘,并将结果返回
/**
* 1!= 1
2!= 2 * 1!
3!= 3 * 2!
4!= 4 * 3!
5!= 5 * 4!
...
* 假设传递的是5
* jiecheng(5)
* 5 * jiecheng(4)
* 5 * 4 * jiecheng(3)
* 5 * 4 * 3 * jiecheng(2)
* 5 * 4 * 3 * 2 * jiecheng(1)
*/
public int jieCheng(int n){
if(n == 1){
return 1; // return 返回结果,后面的代码则不再执行
}
return n*jieCheng(n-1);
}
public static void main(String[] args) {
JieCheng jc = new JieCheng();
int res = jc.jieCheng(5);
System.out.println(res);
}
}
10.4、递归练习
菲波那切数列是指:1 1 2 3 5 8 13 21 …
从第三项开始,每项的值等于前两项的和,第一项、第二项为1
计算菲波那切数列第n项的数值
package com.zhentao.oop;
/**
*
* 菲波那切数列是指:1 1 2 3 5 8 13 21 ...
从第三项开始,每项的值等于前两项的和,第一项、第二项为1
计算菲波那切数列第n项的数值
例如:第6项值 = getNum(5)+ getNum(4)
getNum(4)+ getNum(3)+ getNum(3)+getNum(2)
getNum(3) + getNum(2)+getNum(2)+getNum(1)+ getNum(3)...
getNum(2) + getNum(1)+ getNum(2)+getNum(2)+getNum(1)....
*/
public class Fibonacci {
//自定义方法,接收一个整数类型的参数,要计算的数列的值
public int getNum(int n){
if(n == 1 || n == 2){
return 1;
}
return getNum(n-1)+getNum(n-2);
}
public static void main(String[] args) {
Fibonacci f = new Fibonacci();
int res = f.getNum(6);
System.out.println(res);
}
}
1.静态方法和静态属性
a)语法格式 使用static关键字
b)通过类和对象都可以访问
c)无论实例化了多少个对象,它们访问的静态属性和方法都是同一个
10.5、静态成员介绍
通常情况下,成员变量隶属于对象层级的,一个对象拥有独立的一份,如果多个对象存在相同的成员变量(属性),会造成内存空间的浪费,画图说明:
为了节省内存空间,我们可以使用static关键字修饰成员变量,此时该成员变量就隶属于类层级,随着类的加载完毕而准备就绪的,所以为多个对象之间所共享
画图说明:
语法格式:
修饰符 static 数据类型 成员变量名 = 初始值;
例如:
public static String country = “蜀国”;
修饰符 static 返回值类型 成员方法名(形参列表){
方法体;
}
例如:
public static void main(String[] args){
}
访问静态成员语法格式:
对象.成员变量 / 成员方法();
类名.成员变量 / 成员方法();
直接 写 成员变量 / 成员方法
10.6、注意事项
1.对于非静态的成员方法(没有static关键字修饰的),既可以访问静态的,也可以访问非静态的
2.对于静态的成员方法中,只能访问静态的,不能访问非静态的
根本原因:静态的成员隶属于类层级的,随着类的编译结束而被装载到方法区的,而此时还未创建对象。
3.不能在静态的上下文环境中,使用this关键字
10.7、静态代码块
在java中,允许直接在 { } 里面编写代码,称为代码块
在类体中定义的代码块,称为构造块,构造块的代码在每次构造对象都执行一次
使用static修饰的代码块,称为静态代码块,当类被加载到方法区时执行一次
第 11 章、内部类与Java常用API(一)
11.1、内部类介绍
内部类,就是在一个类的内部声明的类,该类称为内部类,该类所在的类称为外部类。
语法格式:
修饰符class 类名{
class 类名{
}
}
内部类的作用:
当一个类仅仅为了某一个类服务时,可以将该类声明在这个类的内部,可以直接访问外部类的私有成员,不用提供set、get方法
代码演示:
11.2、匿名内部类
匿名内部类,没有名字的内部类,通常用于构建接口、父类类型的对象
需求:
1.已知有一个接口A
2.在测试类中有一个方法show,接收一个A接口类型的数据
3.如何实现
方式一:
先创建实现类(子类)对象
方式二:
由于实现类的书写比较复杂,我们可以通过匿名内部类的方式简化实现类的书写
总结:
当使用接口类型的引用作为方法的形参时,实参的传递方式有2种:
自定义类实现接口并重写方法,此时实参传递该自定义的对象即可
直接new接口对象并通过匿名内部类实现
11.3、Java常用的包
java.lang包,java中的核心包,该包中的所有类由java虚拟机自动导入,如:String类、System类…
java.util包,java的工具包,该包中提供了大量的工具类和集合类,如:Scanner类、Random类
java.io包,提供了有关数据流的输入、输出, 如:FileInputStream类、FileOutputStream类
java.net包,是java中的网络包,该包中提供了有关网络编程的类信息。
java.sql包,包含操作数据库的所有类和接口
其实,java程序员在编程时,可以使用大量的类库,因此java编程要记得很多,对编程能力的本身要求不是特别的高
11.4、Object类
Object是所有类层次结构的根类,所有的类都继承自该类
Object类常用的方法:
equals(Object obj),判断指定的参数是否和当前对象相等(内存地址)
getClass(),返回此 Object 的运行时类。
hashCode(), 返回该对象的哈希码值(内存地址编号,对应一块内存空间)
toString(),返回该对象的字符串表示。
课堂练习
- 默认对象的比较是按照内存地址比较,需求是:按照Student对象的学号比较,如果学号相同,就认为这两个对象相同
- toString方法,默认输出对象的字符串表现,需求是:打印该对象所有的成员变量信息,例如:”[name=张三, id=1001]”
11.5、包装类
包装类是什么?为什么要使用包装类?
1.有些场合(例如,集合),需要的所有元素都必须是对象类型,java的8大基本数据类型的数据如何保存?
2.基本数据类型使用起来很方便,但是没有对应的方法,操作起来不方便,此时也可以使用包装类将其包装成对象,这样,就可以使用该对象里面提供的方法了
常用的包装类:
int => 采用java.lang.Integer类包装(重点)
double => 采用java.lang.Double类包装
long => 采用java.lang.Long类包装
boolean =》 采用java.long.Boolean类包装
char =》 采用java.long.Character类包装
11.6、装箱、拆箱
装箱
顾名思义,就是将基本类型的数据使用包装类包装成对象
语法格式:包装类类型 变量名 = new 包装类();
例如:Integer i = new Integer(10);
拆箱
就是,从包装的对象中,获取基本类型的数据
由于包装类型的对象在参与计算时,需要频繁的装箱、拆箱
从JDK1.5开始,支持自动装箱、自动拆箱
例如:
第 12 章、Java 常用API(二)
12.1、Integer类
java.lang.Integer类主要用于对
Integer(int/String),构造方法,将整数/字符串包装成整数对象,又称为”装箱”
valueOf(),静态方法,将整数包装成Integer对象
intValue(),返回对象的整数数值,又称为”拆箱”
static int parsetInt(String s),将参数类型的字符串转换为整数并返回
12.2、java.math包
java.math包主要提供了2个类:
BigDecimal、BigInteger
其中,BigDecimal是用来解决基本数据类型中小数参与运算时精度丢失的问题
例如:
我们可以使用java.math包中的BigDecimal类解决小数运算精度不足
BigDecimal类提供的常用方法:
add(),加
subtract(),减
multiply(),乘
divide(),除
BigInteger类,为了解决int、long 类型保存的数值范围有限的问题的
理论上,内存有多少,BigInteger就能占多少空间
12.3、String类
java.lang.String用于封装字符串序列
Java字符串在内存中采用UNICODE编码方式,任何一个字符对应两个字节的定长编码
String类提供的常用方法:
contains(),判断字符串是否包含某内容
charAt(int index),根据参数指定的下标返回对应位置的字符
int length(),返回字符串的长度
boolean equals(Object anObject) - 用于判断调用字符串和参数字符串是否相等。
boolean equalsIgnoreCase(String anotherString) - 判断是否相等但忽略大小写。
boolean endsWith(String suffix) - 判断当前字符串是否以suffix为结尾。
boolean startsWith(String prefix) - 判断当前字符串是否以prefix为开头。
String toLowerCase() - 用于将所有字符都转换为小写。
String toUpperCase() - 用于将所有字符都转换为大写。
String trim() - 忽略两边的空白字符。
int indexOf(int ch) - 用于根据参数指定的字符来返回对应的下标。
- 若参数指定的字符不存在,则返回-1.
int indexOf(String str) - 查找参数指定字符串第一次出现的位置。
int lastIndexOf(int ch) - 查找ch在当前字符串中最后一次出现的位置。
int lastIndexOf(String str) - 用于查找参数指定字符串最后一次出现的位置。
String substring(int beginIndex) - 用于获取从参数指定位置开始的子字符串。
String substring(int beginIndex, int endIndex)
- 用于获取从beginIndex位置开始到endIndex位置之间的子字符串。
valueOf (int i),返回int参数的字符串表现
package com.zhentao.wrap;
public class TestString {
public static void main(String[] args) {
String str = "helloworld";
//获取指定位置处的字符,字符串的位置是从0开始的
System.out.println(str.charAt(5));
String str2 = "HELLOWORLD";
System.out.println(str.equals(str2)); //false
// equalsIgnoreCase , 比较字符串是否相等(忽略大小写)
System.out.println(str.equalsIgnoreCase(str2));//true
// endsWith, 判断字符串是否是以 xxx 结尾
String str3 = "index.html";
System.out.println(str3.endsWith(".html"));
// startsWith,判断字符串是否以xxx开头
System.out.println(str3.startsWith("index"));
String str4 = " hello ";
System.out.println(str4.length());
System.out.println(str4.trim().length());
// indexOf(),获取指定的字符串在整体中第一次出现的位置
String str5 = "helloworld";
System.out.println(str5.indexOf("l"));
// lastIndexOf(),获取指定的字符串在整体中最后一次出现的位置
System.out.println(str5.lastIndexOf("l"));
//substring(beginIndex),字符串截取,默认从开始截取到末尾
String res = str5.substring(5);
System.out.println(res);
//substring(int beginIndex, int endIndex)
System.out.println(str5.substring(0, 5));
//valueOf(),返回int的字符串表现
String a = String.valueOf(123);
System.out.println(a);
}
}
练习
1.已知有一个字符串”helloworld”,将每个字符保存到数组中,作为数组元素存在
2.String类中的equals方法与Object类中的equals方法的不同点
3.有一个三位数,个位、十位、百位的立方和等于这个数本身,请问这个数是多少?(要求使用java字符串相关的方法实现)
12.4、String缓冲类
字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串
一旦声明String对象,那么在内存中的序列就固定了,如果后期对该字符串进行操作(运算),则会拷贝一个新的字符串参与运算,这样会浪费内存空间,如下图所示:
java的设计者给我们提供了2个类,解决上面的问题:
Java.lang.StringBuilder和StringBuffer类是用于描述可变字符序列的
其中,StringBuffer类是早期提供的,支持线程安全,但是效率低
其中,StringBuilder类是后期提供的,不支持线程安全,效率高,建议大家使用该类
StringBuilder常用方法:
java.lang.StringBuilder(String ) 有参构造方法,根据参数创建可变字符串对象
int capacity() - 用于获取调用对象的容量并返回。初始容量为字符串长度+16
int length() - 用于获取长度(字符的个数)并返回。
StringBuilder insert(int offset, String str) - 在offset位置插入str字符串
StringBuilder append(String str) – 在源字符串后面附加str字符串
StringBuilder delete(int start, int end) – 删除从start开始到end结束的字符串
StringBuilder replace(int start, int end, String str) – 将从start开始到end结束的内容替换为str
StringBuilder reverse() – 将源字符串反转
12.5、Date类
java.util.Date类,用来操作日期的
java.util.Date类的常用方法:
Date(),无参构造方法,获得当前的日期对象(精确到当前的毫秒1000毫秒==1秒
Date(time),有参构造方法,根据时间参数获得对应的日期对象
getTime(),用来获得当前的时间戳。(当前距离1970年1月1日0时0分0秒的到现在的毫秒数。1000毫秒==1秒
setTime(long time) - 用于根据参数指定的毫秒数来调整时间。
12.6、SimpleDateFormat类
Date类默认是按照西方人的习惯显示时间,不符合中国人的习惯。
我们可以使用SimpleDateFormat类进行格式化
java.text.SimpleDateFormat类,用来格式化日期对象的,通俗的说就是调整日期格式
SimpleDateFormat(pattern),有参构造方法,根据参数指定的格式来格式化日期
常见的pattern格式如下:
y 年份
M 月份
d 月份中的天数
H 小时
m 分钟
s 秒数
常用方法:
format(),格式化,将日期对象格式化为字符串
parse(),将字符串解析成日期对象
练习
1.使用SimpleDateFormat类, 把2019-03-04 转换 为 2019年03月04日。
2.请使用日期相关API,计算一个人已经出生了多少天?
思路:
提示用户输入生日:格式为2019-01-01
获取当前日期对象,格式为2020-01-01
获取时间戳
12.7、Calendar类
Calendar是日历类,该类将所有可能用到的时间信息封装为静态成员变量,方便获取。
12.7.1、 获取方式
Calendar为抽象类,由于语言敏感性,Calendar类在创建对象时并非直接创建,而是通过静态方法创建,返回子类对象,如下:
Calendar静态方法
public static Calendar getInstance():使用默认时区和语言环境获得一个日历
例如:
import java.util.Calendar;
public class Demo06CalendarInit {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
}
}
12.7.2、 常用方法:
根据Calendar类的API文档,常用方法有:
public int get(int field):返回给定日历字段的值。
public void set(int field, int value):将给定的日历字段设置为给定值。
public abstract void add(int field, int amount):根据日历的规则,为给定的日历字段添加或减去指定的时间量。
public Date getTime():返回一个表示此Calendar时间值(从历元到现在的毫秒偏移量)的Date对象。
Calendar类中提供很多成员常量,代表给定的日历字段:
字段值 含义
YEAR | 年 |
MONTH | 月(从0开始,可以+1使用) |
DAY_OF_MONTH | 月中的天(几号) |
HOUR_OF_DAY | 时(24小时制) |
HOUR | 时(12小时制) |
MINUTE | 分 |
SECOND | 秒 |
DAY_OF_WEEK | 周中的天(周几,周日为1,可以-1使用) |
12.7.3、 get/set方法
get方法用来获取指定字段的值,set方法用来设置指定字段的值,代码使用演示:
import java.util.Calendar;
public class CalendarUtil {
public static void main(String[] args) {
// 创建Calendar对象
Calendar cal = Calendar.getInstance();
// 设置年
int year = cal.get(Calendar.YEAR);
// 设置月
int month = cal.get(Calendar.MONTH) + 1;
// 设置日
int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
System.out.print(year + "年" + month + "月" + dayOfMonth + "日");
}
}
import java.util.Calendar;
public class Demo07CalendarMethod {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2020);
System.out.print(year + "年" + month + "月" + dayOfMonth + "日"); // 2020年1月17日
}
}
12.7.4、 add方法
add方法可以对指定日历字段的值进行加减操作,如果第二个参数为正数则加上偏移量,如果为负数则减去偏移量。代码如:
import java.util.Calendar;
public class Demo08CalendarMethod {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
System.out.print(year + "年" + month + "月" + dayOfMonth + "日"); // 2018年1月17日
// 使用add方法
cal.add(Calendar.DAY_OF_MONTH, 2); // 加2天
cal.add(Calendar.YEAR, -3); // 减3年
System.out.print(year + "年" + month + "月" + dayOfMonth + "日"); // 2015年1月18日;
}
}
12.7.5、 getTime方法
Calendar中的getTime方法并不是获取毫秒时刻,而是拿到对应的Date对象。
import java.util.Calendar;
import java.util.Date;
public class Demo09CalendarMethod {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
Date date = cal.getTime();
System.out.println(date); // Tue Jan 16 16:03:09 CST 2018
}
}
小贴士:
西方星期的开始为周日,中国为周一。
在Calendar类中,月份的表示是以0-11代表1-12月。
日期是有大小关系的,时间靠后,时间越大。
第 13 章、集合概述
13.1、集合介绍
一般地,我们将研究的对象称为元素,多个元素组成的整体叫集合。
过去,我们在内存中存储多个元素是通过数组来实现的。
但是数组在存储数据方面有一些弊端:
1.数组初始化以后,长度就不可变了,不便于扩展
2.数组中提供的属性和方法少,不便于进行添加、删除、插入等操作,且效率不高。
3.数组存储的数据是有序的、可以重复的。
在Java中,集合本质上也是一段内存空间,用来存储多个对象
集合特点:
1.集合一旦定义,内存空间不固定,而且可以动态调整
2.集合还可用于保存具有映射关系的 关联数组。
13.2、集合分类
在Java中,集合分为两大类:Collection集合、Map集合
其中,Collection集合的基本单位是:单个元素,例如{“张三丰”}
其中,Map集合的基本单位是:单对元素,例如{name=>张三丰}
在实际开发时,很少直接使用Collection和Map,因为他俩是接口,通常使用该接口的子接口、或实现类。
13.3、泛型
目前,集合中虽然可以存放不同类型的数据,其原因是将所有元素都包装成Object类型,但从集合中取出元素并表达真实类型时,需要进行强制类型转换,过程比较繁琐,而且该转换可能引发类型转换异常
为了避免上述错误的发生,从jdk1.5开始,加入了泛型机制,也就是在集合名词的后面,使用<数据类型>的方法明确该集合中元素的类型,若放入其他类型则编译报错。
语法格式:
集合接口/实现类<引用数据类型> = new 集合实现类<引用数据类型>();
例如:
List list = new ArrayList< Person >();
明确指定list集合中只能存储Person类型的数据,那么将来取数据时,取出的必然是Person类型的数据,不用再强制类型转换
13.4、泛型标识符
T:类型(Type)
E:元素(Element),多用于java集合框架
K:关键字(Key)
N:数字(Number)
V:值(Value)
ArrayList al=new ArrayList(); 指定集合元素只能是T类型;T 代表一种类型
Object由于它是所有类的父类,所以会强制类型转换,而T从一开始在编码时(注意是在写代码时)就限定了某种具体类型,所以它不用强制类型转换。
/*
* 分页类,不确定对什么内容进行分页,可能是商品、人、汽车等
* 所以使用T,表示接收一种类型,具体是什么类型,由外部调用者传递进来
*/
public class Page<T>{
private List<T> rows;
public static void main(String[] args) {
Page<Integer> page = new Page<>();
System.out.println(page);
}
}
E 也是一种类型的意思,只不过通常代表集合中的元素(Element)
public class ArrayList<E> extends AbstractList<E> implements List<E>
泛型通配符:? 泛指某种未知的类型
public class Page<T>{
private List<?> rows;
public static void main(String[] args) {
Page<Integer> page = new Page<>();
page.rows.add(null);
}
}
上面代码使用了“?”,这样声明的List不能向里面add元素,“?”代表某种未知类型。我们传递给add的任何参数都必须是这种未知类型的子类型。因为我们不知道它是什么类型,所以我们无法传递任何内容。唯一的例外是null,它是每种类型的成员。
上限通配符 <? extends Number>
只允许泛型为Number及Number子类的类型
下限通配符 <? super L>
只允许泛型为Number及Number父类的类型
ArrayList<? extends E> al=new ArrayList<? extends E>();
泛型的限定:? extends E:接收E类型或者E的子类型。
? super E:接收E类型或者E的父类型。
13.5、Collection集合常用方法
由于Collection是接口,所以在Collection接口中声明的方法,在其子接口、以及实现类中都可以使用。
常用方法:
boolean isEmpty() - 用于判断当前集合是否为空。
int size() - 用于返回当前集合中元素的个数。
boolean add(E e) – 向集合中添加元素。
boolean addAll(Collection c) -将一个集合中的元素添加到另一个集合中。
boolean remove(Object o) – 从集合中删除一个对象。
boolean removeAll(Collection c) –将集合中存在的另一个集合删除。
void clear() - 用于清空当前集合。
boolean contains(Object o) – 判断集合中是否包含某个元素。
boolean containsAll(Collection c) –判断集合中是否包含另外一个集合。
13.6、Collection集合遍历
13.6.1、 迭代器
通过重复性地移动指针来获取指针所指向的元素
在调用it.next()方法之前必须要调用it.hasNext()进行检测。
若不调用,且下一条记录无效时,会抛出NoSuchElementException异常。
迭代器使用:
13.6.2、 增强版for循环
JDK在1.5版本推出了增强型FOR循环语句,可以用于数组和集合的遍历。
• 是经典迭代的"简化版"
语法格式:
for(目标数据类型 变量:待遍历的数组/集合){
从数组/集合中,每遍历到一个元素,就赋给前面的变量
}
例如:
13.7、练习
1.声明一个英雄Hero类,属性有:姓名、年龄;然后实例化5个对象,存入到Collection集合中,然后使用迭代器模式读取每个元素并输出。
2.声明一个美女Beauty类,属性有:姓名、年龄、身高;然后实例化5个对象,存入到Collection集合中,然后使用增强版for循环读取每个元素并输出。
第 14 章、List集合
14.1、List集合概述
Java.util.List接口是Collection接口的子接口,用于定义线性表数据结构; 可以将List理解为存放对象的数组,只不过其元素个数可以动态的增加或减少。
该接口的主要实现类有:ArrayList类、LinkedList类、Stack类、Vector类
其中,ArrayList类的底层是采用动态数组实现的,访问方便,增删不方便
其中,LinkedList类的底层是采用链表实现的,访问不方便,增删方便
其中,Stack类(栈)的底层是采用动态数组实现的,具有后进先出的特性
其中,Vector类是一个古老的集合,JDK1.0就有了。该类与ArrayList相似,底层也是动态数组,但是是属于线程安全的类,效率比较低。
14.2、面试题
ArrayList、 LinkedList 和 Vector之间的区别
ArrayList,底层使用Object[]存储,线程不安全,效率高
LinkedList,底层使用双向链表存储,对于频繁的插入、删除操作,使用此类效率比ArrayList高
Vector和ArrayList类似,底层使用Object[]存储,线程安全,效率低
14.3、ArrayList
查看源代码:
ArrayList的JDK1.8之前与之后的实现区别?
JDK1.7:ArrayList像饿汉式,直接创建一个初始容量为10的数组
JDK1.8:ArrayList像懒汉式,一开始创建一个长度为0的数组,当添加第一个元 素时再创建一个始容量为10的数组
ArrayList底层使用动态数组保存
所谓动态数组,如果数组存满了,这个类的内部会再声明一个更大的数组,将原数组内容拷贝一份到新数组
支持下标,能够随机访问,查询方便
添加、删除元素时,需要移动其他元素,添加、删除不方便
14.4、LinkedList
LinkedList:双向链表,内部没有声明数组,而是定义了Node类型的first和last,用于记录首末元素。
同时,定义内部类Node,作为LinkedList中保存数据的基本结构。
Node除了保存数据,还定义了两个变量:
1: prev变量记录前一个元素的位置
2: next变量记录下一个元素的位置
总结:
可以认为,ArrayList和LinkedList的方法在逻辑上完全一样,只是在性能上有一定的差别,ArrayList类更适合于随机访问,而LinkedList类,更适合于频繁的插入和删除,在性能要求不是特别苛刻的情形下可以忽略这个区别。
14.5、List接口方法
List除了从Collection集合继承的方法外,List 集合里添加了一些根据索引来 操作集合元素的方法。
void add(int index, Object ele):在index位置插入ele元素
Object get(int index):获取指定index位置的元素
int indexOf(Object obj):返回obj在集合中首次出现的位置
int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
Object remove(int index):移除指定index位置的元素,并返回此元素
Object set(int index, Object ele):设置指定index位置的元素为ele
第 15 章、Set集合
15.1、Set接口概述
java.util.Set接口,是Collection的子接口,其特点是:
- 元素无序,无索引、无序号
- 元素不能重复
该接口的主要实现类有:HashSet类 和 TreeSet类
其中,HashSet类的底层是采用一张哈希表实现,散列存放,无序
其中,TreeSet类的底层是采用一棵二叉树实现,有序存放,有序
Set接口是Collection的子接口,set接口没有提供额外的方法
Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals() 方法。
15.2、HashSet
HashSet按Hash 算法来存储集合中的元素,因此具有很好的存取、查找、删除 性能。
HashSet 具有以下特点:
1.不能保证元素的排列顺序
2.HashSet 不是线程安全的
3.集合元素可以是 null
在将对象加入HASHSET集合中时,需要获取对象的HASHCODE值,然后通过HASH算法决定该对象 在 HashSet 底层数组中的存储位置,所以哈希表的增删和查询效率都比较高。
向HashSet中添加元素的过程:
HashSet底层也是数组,初始容量为16,当如果使用率超过0.75,(16*0.75=12) 就会扩大容量为原来的2倍。(16扩容为32,依次为64,128…等)
代码演示:
HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相 等,并且两个对象的 equals() 方法返回值也相等。
对于存放在Set容器中的对象,对应的类一定要重写equals()和hashCode(Object obj)方法,以实现对象相等规则。即:“相等的对象必须具有相等的散列码”。
15.3、自然排序
- 自定义的类,只需要实现java.lang.Comparable接口,并重写compareTo方法
- 需要在compareTo方法中指定排序的字段
两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小。
15.4、自定义排序
自定义排序规则,按照该规则进行排序
步骤:
自定义一个比较器,实现Comparator接口,重写compare方法
最后将比较器作为参数传到TreeSet当中
将自定义比较器,作为参数传递到TreeSet集合中
练习:
自定义Person类,有年龄、姓名属性,要求按照年龄自然排序,如果年龄相等,再按照姓名的字典顺序排序
第 16 章、Map接口
16.1、Map集合介绍
Java.util.Map(K,V)接口用于存放键值对(Key => Value)形式的集合,其中键不允许重复,一个键只能对应一个值:
Map接口继承树
Map接口的常用实现类:
HashMap、TreeMap、LinkedHashMap和 Properties。
其中,HashMap是 Map 接口使用频率最高的实现类
HashMap,底层采用哈希表存储
TreeMap,底层采用红黑树存储
16.2、Map集合常用的方法:
最常用的方法:put、get
增删改:
Object put(Object key,Object value):将指定key-value添加 (或修改)当前map集合
void putAll(Map m):将m中的所有key-value对存放到当前map中
Object remove(Object key):移除指定key的key-value对,并返回value
void clear():清空当前map中的所有数据
查询操作:
boolean isEmpty() - 用于判断当前集合是否为空。
int size() - 用于获取当前集合中的键值对个数。
Object get(Object key):获取指定key对应的value
boolean containsKey(Object key):是否包含指定的key
boolean containsValue(Object value):是否包含指定的value
元视图操作的方法:
Set keySet():返回所有key构成的Set集合
Collection values():返回所有value构成的Collection集合
Set entrySet():返回所有key-value(键值对)构成的Set集合/视图
K getKey() - 用于获取当前元素中的key值。
V getValue() - 用于获取当前元素中的value值。
16.3、课堂练习:
1.总结遍历集合的4种方式
2.课堂练习
使用HashMap统计相同字符串出现次数,例如:
String line = “169,589, 798,723 , 589 , 169 , 169 , 723”
统计结果格式为:{723 = 2, 798 = 1, 169 = 3, 589 = 2}
思路:
String类,有split方法,根据逗号将字符串拆分成数组
循环集合Map集合的方法实现
16.4、HashMap存储结构
JDK 7及以前版本:HashMap是数组+链表结构(即为链地址法)
JDK 8版本发布以后:HashMap是数组+链表+红黑树实现。
第 17 章、学生信息管理系统
17.1、声明Student类
保存学生的信息(学号、姓名、年龄、住址)
17.2、搭建学生管理系统的界面
17.3、添加学生
17.4、查询所有学生
17.5、修改学生信息
修改学生—方法一
修改学生—方法二:
17.6、删除学生
17.7、退出管理系统