文章目录
- day01之Java基础入门
- day02之Java基础语法
- day03之程序流程控制
- day04 习题课
- day05之Java数组
- day6之Java方法
- day07-09之编程训练&比赛
- day10之面向对象
- day11之字符串和集合
- day12之ATM系统
day01之Java基础入门
一、Java介绍(了解)
1.Java背景
● Java是美国sun公司1995年推出的计算机高级编程语言。
● Java之父:詹姆斯·高斯林。
● 2009年sun公司被==Oracle(甲骨文)==公司收购。
● Java主要用来做企业级应用开发
● Java应用的六大行业:
桌面应用开发:如IDEA
服务器系统:应用后台
企业级应用开发:微服务,大型互联网应用如:京东首页、后台管理系统、OA办公系统
大数据开发:Hadoop
移动应用开发:Android,医疗设备
游戏开发:如Minecraft
2.Java技术体系
三大技术体系:
- JavaSE(标准版):Java技术的核心和基础(标准版本)
- JavaEE(企业版):企业级应用开发解决方案(企业级应用版本)
- JavaME(小型版):针对移动设备应用的解决方案(做Android)
二、Java入门(重要)
1.JDK简介
JDK(Java Development Kit:Java开发者工具包),必须安装JDK才能使用Java语言
1996年 JDK1.0
2000年 JDK1.3
2004年 JDK5.0
2014年 JDK8.0(LTS)
2018年9月 JDK11.0(LTS)
2021年9月14日 JDK17.0(LTS) LTS(long-term support):长期支持版
2.验证JDK安装是否成功
验证JDK安装是否成功:
win+R,输入cmd,输入命令java -version
,如果能看到版本号,则安装成功
DOS命令窗口出现,‘java’不是内部或外部命令,说明JDK配置有问题,需要重新配置。
3.卸载JDK
卸载JDK:
1.直接删除JDK包
2.删除环境变量(JAVA_HOME和Path)
4.常用命令(javac和java)
● Java程序是高级语言,计算机底层硬件不能识别
5.Java入门程序
5.1Java开发三步骤
编写代码、编译代码、运行代码
文件名全英文,首字母大写,源代码文件的后缀必须是.java
程序员写的代码称为源代码,机器不识别,需要编译(javac)
5.2HelloWorld程序介绍
6.IDEA介绍(重要)
6.1IDE概念
IDE(Integrated Development Environment)集成开发环境
● 把代码编写、编译、执行等功能综合起来的开发工具,可进行代码智能提示,错误提醒,项目管理等等。
6.2IDEA优点
Intellij IDEA简称IDEA,在代码错误提醒,智能代码补全等多方面表现优秀。
1.自动保存
2.自动编译
3.在main方法的左侧小箭头上点击选择Run命令
6.3IDEA管理Java程序的结构
IDEA的层次目录结构,用IDEA开发,最终的目的还是类。
以上三个目录结构都是为了把类划分的更详细,便于管理项目代码。
整个IDEA组织起来有四层:
-
project(项目、工程)
-
module(模块)
-
package(包)
-
class(类)——>.java文件
整个基础阶段是一个project,
每天课程是一个module。
6.4用IDEA开发Java程序步骤
- 创建工程new Project(空工程)
最外层项目就是一个文件夹,新建时选Empty Project
- 设置JDK
- 创建模块 new Module
- 创建包 new Package
- 创建类
- 编写代码并运行
总结:
6.5IDEA中设置主题、字体、背景色
主题、字体设置:
背景色设置:
6.6IDEA常用快捷键
三、Java基础语法 (重要)
1.注释
注释对代码进行解释说明,不影响代码执行
源代码要变成机器能认识的代码要经过编译,编译过程会将注释抹去。
总结:
2.字面量(常量)
● 数据在程序中的书写格式:
种类:整数 小数 字符 字符串 布尔值 空值
整数字面量:77 88 0 -1
小数字面量:0.1 3.14
字符字面量:单引号引起来的一个字符'A' 'a' ' '
字符串字面量:双引号引起来的任意数量字符"A" "ABC" "" " "
布尔值字面量:true false
空字面量:null
总结:
3.变量
3.1变量的定义
● 变量用来记住程序中要处理的数据
格式:
数据类型 变量名 = 值(字面量);
快递包装盒大小 快递名 = 快递内容;
age:快递盒名字
int:快递盒大小
18:快递盒里放的东西
3.2用变量的好处
用变量记要处理的数据,代码更灵活,管理更方便。
3.3变量的特点
变量中装的数据可变。
在同一个作用域中,不能同时定义两个同名的变量。
但是可以先定义,然后改动值。
3.4变量的应用场景
写程序对数据进行处理很方便
总结:
3.5使用变量的注意事项
● 变量要先声明后使用
● 变量是啥类型,就要装什么类型数据
●变量的作用域
变量有作用域:从定义开始,到最近的一个}结束;
在同一个作用域中,变量的名称不能相同
● 定义变量的时候可以不赋初始值;
但在使用时,变量里必须有值
总结:
4.关键字、标识符
4.1关键字
Java自己用的一些有特殊作用的词称为关键字,如:public、class、int、double…
除了48个关键字,还有2个保留字(预留关键字)const、goto
,3个特殊直接量(特殊关键字)true、false、null
4.2标识符
标识符是自定义的名字,如类型、变量名等等
4.3标识符的要求
1.基本组成:只能由数字、字母、下划线(_) 和 美元符($) 等组成。
2.强制要求:不能用关键字(53个)作为名字、 不能以数字开头、区分大小写。
中国被认为是字母,可以用来命名
中文也叫字母,中文也能作类名,也能作变量名。
4.4标识符命名规范
大小驼峰模式只和第一个字母有关
● 变量名称:小驼峰模式要求首字母小写,如:studyNumber
● 类名称:大驼峰模式要求首字母大写,如:HelloWorld,Student
总结:
四、Java理论补充(理解)
1.JDK的组成
● JVM:Java虚拟机,真正运行Java程序的地方。程序员写的程序最终被Java虚拟机运行。
● 核心类库:高斯林写的一些Java基础提供好的一些类,可以直接调用,如sout。
Java自己写好的程序,给程序员自己的程序调用。
这是Java的一个便利点,这个思想叫做面向对象编程,拿来直接用。
JVM+核心类库=JRE
● JRE:Java的运行环境
如果不是一个Java开发人员,只是想用Java跑程序,只需要JRE就能保证程序运行。
● 开发工具:java、javac...
总结:
2.Java跨平台原理
2.1跨平台定义
Java的特点:一次编译,到处运行
跨平台原理:为不同的平台提供不同的虚拟机,虚拟机具备把.class文件翻译成对应平台能看懂文件的能力。
Linux(做服务器的)
总结:
3.JDK安装后配置Path和JAVA_HOME环境变量的原因
3.1Path环境变量
● Path环境变量用来记住程序路径,方便在命令行窗口的任意目录启动程序。
● 在dos中输入命令时,它会按照下面顺序寻找命令文件:
1.dos中当前位置(当前执行的目录下)
2.环境变量中path指定的路径
3.2为java、javac配置Path路径
之所以要把java的路径配置到环境变量中,主要是为了方便。
如果不配置环境变量,只能在JDK的bin目录下运行java命令。
一旦配置到环境变量,就可以在电脑的任何位置运行java命令,因为会自动找环境变量里的东西。
总结:
五、总结
day02之Java基础语法
一、数据存储(了解)
1.二进制
● 计算机中所有数据都以二进制形式存储,二进制即只有0和1。
● 也即计算机只认识0和1两个数字。
● 把数字、文字、图片、视频保存到计算机中,要想办法把它们转换为0和1。
2.数字存储
2.1二进制介绍
● 二进制即只有0和1,按照逢2进1的方式表示数字。
2.2十进制转二进制
BIN(binary system):二进制
OCT(octonary number system):八进制
DEC(decimalism):十进制
HEX(hexadecimal):十六进制:A-F表示10-15
2.3计算机中的数据的基本单元和最小单位
最高位认为是符号位,符号位是0表示是正数,符号位是1表示是负数。
字节是最小单位(数据存储的基本单元),等于8个二进制位,不可拆。
● 数据存储基本单元:使用8个二进制位为一组,称为一个字节(byte,简称B)
● 数据存储最小单位:数据基本单元中,每个二进制位称为比特(bit,简称b),1B = 8b
3.总结:
3.其他存储
3.1字符在计算机中存储
● 转换成对应的ASCII码,把对应的ASCII码转成二进制保存到计算机里。
ASCII编码:即美国信息交换标准编码,规定了字母、数字和其他西欧字符对应的数字编号。
'0':48
'A':65
'a':97
3.2图片数据在计算机中存储
● 图片由无数个像素点组成。
● 每个像素点的数据:用0~255255255(三原色RGB)表示其颜色。
3.3声音数据在计算机中存储
把声音的音波频率转换为对应的数字,再把数字转换为二进制保存到计算机中。
3.4总结
二、数据类型(重点)
● 数据类型规定了变量只能存储什么类型的数据
1.分类
数据类型 变量名称 = 初始值;
基本数据类型:4类8种
整型:
byte(1字节)
short(短整型)(2字节)
int(默认)(4字节)
long(8字节)
浮点型:
float(单精度浮点类型)(4字节)
double(双精度浮点类型)(默认)(8字节)
字符型:
char(2字节)
布尔型:
boolean(1字节)
引用数据剧类型:String
● 类型转换指的是不同类型的变量相互转换
2.自动类型转换
2.1自动类型转换的概念
类型范围小的变量,可以直接赋值给类型范围大的变量。
自动类型转换不会造成数据的损失。
帮助理解:变量里面存的是数据,变量是内存中的一块区域,类似于一个快递盒子。
翻译过来就是,小快递盒子里的快递可以直接装进大快递盒子。
再比方说,一杯水可以直接倒入一个大桶,这杯水不会有损失。
浮点型和整型,在计算机中存储数据时机制是不一样的,不能单纯地比较占几个字节。
=是赋值运算
2.2表达式的自动类型转换
● 在表达式中,小类型的变量,会自动转换成表达式中较大范围类型的变量,再参与运算。
● 表达式的最终结果类型由表达式中的最高类型决定。
● 表达式中,byte、short、char直接转换成int类型参与运算。
● char单独打印打印的是本身,一旦参与运算,用的是在ASCII表中的值。
3.强制类型转换
大范围类型的变量——>小范围类型的变量,这个操作,IDEA认为是有危险的,默认不允许,直接报错,硬干需要强制类型转换。
可以用一桶水倒到一个杯子里来理解
强转:把一个大范围类型,强行转换为小范围类型
这种情况下没有问题
这种情况下发生了数据损失
注意:
● 强转可能造成数据(丢失)溢出;
● 浮点型强转成整型,直接丢掉小数部分,保留整数部分并返回
三、运算符(重点)
● 运算符是对变量、字面量(常量)进行运算的符号。
1.算术运算符
1.1算术运算符介绍
1.2+号运算规则
● "+"符号与字符串运算时用作连接符,其结果依然是字符串。
● +号两边只要有一边是字符串,+就当做连接符来用。
● +号,能算则算,不能算就拼接在一起。
1.3数值拆分
2.自增自减运算符
● ++、–只能操作变量,不能操作字面量
● 如果变量单独使用,符号在前、在后没有区别
2.1自增自减的使用注意事项
● ++、–若不是单独使用(若在表达式中或同时有其他操作),放在变量前后有明显区别。
赋值运算也是一种运算:
口诀:
3.赋值运算符
3.1基本赋值运算符
就是“ = ”,从右往左看
int a = 10;
//先看“=”右边,把数据10赋值给左边的变量a存储
3.2扩展赋值运算符
符号 用法 作用 底层代码形式
+= a+=b 加后赋值 a = (a的类型) (a + b);
-= a-=b 减后赋值 a = (a的类型) (a - b);
*= a*=b 乘后赋值 a = (a的类型) (a * b);
/= a/=b 除后赋值 a = (a的类型) (a / b);
%= a%=b 取余后赋值 a = (a的类型) (a % b);
扩展的赋值运算符隐含了强制类型转换
4.逻辑运算符
4.1关系运算符
关系/比较运算符,关系运算符用于变量之间的比较。
关系表达式 是包含关系运算符的表达式,它的值是boolean类型
符号 例子 作用 结果
> a>b 判断a是否大于b 成立返回true,不成立返回false
>= a>=b 判断a是否大于或者等于b 成立返回true,不成立返回false
< a<b 判断a是否小于b 成立返回true,不成立返回false
<= a<=b 判断a是否小于或者等于b 成立返回true,不成立返回false
== a==b 判断a是否等于b 成立返回true,不成立返回false
!= a!=b 判断a是否不等于b 成立返回true,不成立返回false
关系运算符判断数据是否满足条件,最终会返回一个判断的结果,此结果是布尔类型的值:true或者false
4.2逻辑运算符
把多个条件放在一起运算,最终返回布尔类型的值:true、false。
符号 叫法 例子 运算逻辑
& 逻辑与 2>1&3>2 多个条件必须都是true,结果才是true;有一个是false,结果就是false
| 逻辑或 2>1|3<5 多个条件中只要有一个是true,结果就是true
! 逻辑非 !(2>1) 取反:你真我假,你假我真!true==false、!false==true
^ 逻辑异或 2>1^3>1 前后条件的结果相同返回false;前后条件结果不同才返回true
&& 短路与 2>10&&3>2 判断结果与“&”一样,过程不同:左边为false,右边则不执行
|| 短路或 2>1||3<5 判断结果与“|”一样,过程不同:左边为true,右边不执行
注意:
在java中,“&”、“|”:无论左边是false还是true,右边都要执行。
&&、||运算效率更高,在开发中使用的更多。
5.三元运算符
格式:条件表达式?值1:值2;
执行流程:首先计算关系表达式的值,若为true,返回值1,若为false,返回值2。
6.运算符的优先级
四、键盘录入(重点)
核心类库就是API:应用程序编程接口
Java写好的程序,程序员可以直接调用。
Java为自己写好的程序提供了相应的程序使用说明书(即API文档)。
Scanner是JDK提供好的一个类,需要可以直接调用。
day03之程序流程控制
控制程序的执行顺序
程序的三种控制结构:
顺序结构:自上而下地执行代码
分支结构:根据条件选择对应代码执行
循环结构:控制某段代码重复执行
一、分支结构
1.if分支
1.1if语句介绍
● 根据条件(真或假)决定执行某段代码
if第一种形式
if第二种形式
if第三种形式
1.2if使用的几个常见问题
● 如果if语句的{}中只有一行代码,()可以忽略不写(但不推荐忽略)。
● if(条件){},()后不能跟“;”,否则{}中的代码将不受if的控制。
1.3练习:用户登录
2.switch分支
● switch分支通过比较值决定执行哪条分支
switch分支执行流程:
1.先执行表达式的值,用待匹配的值去匹配对应的case。
2.与哪个case的值匹配为true就执行对应的语句体,遇到break就结束switch分支。
3.所有case都匹配不到,执行default块中的语句体。
3.switch使用时的注意事项
1.switch分支语句()中的表达式类型只能是byte、short、int、char,JDK5开始支持枚举,JDK7开始支持String。
不支持double、float、long。
2.case给出的值不能重复,并且只能是常量,不能是变量。
3.使用switch时忘写break会出现穿透现象。
● 穿透现象:
当匹配成功一个case以后,执行完语句体之后,没有break。
就会忽略后面的条件判断,直接执行语句体,直到再次出现break或者整个switch语句结束。
穿透现象可以加以利用,优化代码。
4.if和switch比较
● if适合做区间匹配,功能更强。
● switch适合做值匹配,性能更好。
二、循环结构
● 控制一段代码重复执行多次。
1.for循环
2.for循环案列
求1-5之间 的数据和
求1-10之间的奇数和
水仙花数
3.while循环
4.while循环案例
折纸案例
for和while循环都可以实现循环,使用时如何选择?
for:明确知道循环次数
while:不知道循环多少次
5.do-while循环
do-while循环的特点是:先执行后判断。
初始化语句;
do{
循环体语句;
条件变更语句;
}while(条件判断语句);
6.三种循环的对比
7.死循环
7.1死循环的概念
死循环:
是指可以一直执行下去(即保证循环的条件判断语句永远成立)的循环,若没有干预不会停下来。
7.2死循环的写法
8.循环嵌套
8.1概念
即循环中又包含循环。
8.2特点
外部循环每循环一次,内部循环会全部执行完一轮。
外层循环执行一次,内层循环执行一轮。
8.3案例:连续说3天,每天说5遍“我爱你”
8.4案例:在控制台打印4行5列的矩形
三、跳转关键字:break、continue
1.介绍
break:跳出并结束当前所在循环的执行(break只能用于结束所在循环 或 结束所在switch分支的执行)
(帮助理解:吃包子,吃出蟑螂,本包子不吃了,别的包子也都不吃)
continue:跳出当前循环的本次执行,直接进入循环的下一次执行(continue只能在循环中使用)
(帮助理解:吃包子,一个掉到地上,本包子不吃了,拿下一个包子来吃)
2.案例:密码验证
四、Random类:生成随机数
1.Random类的作用、使用及注意事项
举例:随机点名、年会抽奖
Random 作用:生成随机数
2.总结:
3.案例:猜数字游戏
day04 习题课
day05之Java数组
一、数组介绍
● 数组是一个容器,用来存储一批同类型的数据
有变量,为何用数组?
答:遇到批量操作同类型数据时,数组比变量更合适。
二、数组定义和访问
1.静态初始化数组
● 定义数组的时候直接给数组赋值(要求在定义数组时已知要存的元素)
注意:
● 数据类型[ ] 数组名
也可写成数据类型 数组名[ ]
● 什么类型的数组只能存放什么类型的数据
注意:
数组变量名中存储的是数组在内存中的地址,数组是一种引用类型数据。
● **基本数据类型:**四类八种,变量记录的就是数据本身
● **引用数据类型:**变量记录的是内存地址,该变量对应的类型是引用数据类型
判定一个数据是否是引用类型,只需要判定这个变量里面存的是内存地址还是数据本身。
2.数组的访问
数组名[索引]
如上图,通过变量arr找内存地址,通过内存地址再找索引0,通过索引就能找到数据。
ArrayIndexOutofBoundException
:
数组索引越界异常
3.数组的遍历
**遍历:**一个一个地访问数据
ages.length:ages数组的数组长度
数组遍历求和:累加思想,定义一个sum变量
4.动态初始化数组
静态初始化数组:创建数组时已知里面的元素
动态初始化数组:创建数组时不知道里面的元素
● 定义数组时先不存入具体元素值,只确定数组存储的数据类型和数组长度
数组的动态初始化格式:
数据类型[] 数组名 = new 数据类型[长度];
int[] arr = new int[3];
三、数组常见案例
声明变量快捷方式:列选择
Alt+按住鼠标左键,光标下拉
数据交换要引入一个临时变量temp
临时变量思想
数组反转要引入双指针思想,定义两个指针变量,分别指向数组的首尾索引
随机排名/打乱数组
四、数组执行原理
1.数组的执行原理
计算机最后拿到的是一个class文件,由JVM来执行,JVM是代码真正运行的地方。class文件中的main方法会被JVM自动调用。
堆内存中存放new出来的,
随机数对象,键盘对象,数组,对象会存在堆内存中。
Java内存分配:
● 方法区:存放字节码文件
● 栈(内存):存放方法和变量
● 堆(内存):new出来的东西(对象)
● 本地方法栈
● 寄存器
基本类型是固定的四类八种,除了基本类型都是引用类型。
基本数据类型的变量和值都存在栈中。
引用数据类型的变量,变量名存在栈中,变量名下存的是一个地址,这个地址对应的真正位置在堆里面。
2.多个变量指向同一个数组的问题
帮助理解:arr1和arr2变量想成家门的钥匙,我和我媳妇都有家门的钥匙,钥匙对应的内存地址中存的数据想成家里的家具,我把其中的值修改,比如把家里的床卖了,媳妇的视角里也会受到影响。
五、Debug工具的使用
Debug工具:
IDEA自带的断点调试工具,可以控制代码从断点开始一行一行地执行,然后详细观看程序执行的情况。
Debug工具基本使用步骤
1.在需要控制的代码行左侧,点击一下形成断点
2.选择Debug方式启动程序,启动后程序会在断点暂停
3.控制代码一行一行往下执行
注意事项:
1.打断点
(希望程序在哪一行暂停),断点要打在正式的代码行,不要打在类名、方法名、导包、空行等位置。
2.使用debug运行程序
3.控制程序一步一步执行
Step Into:下一步如果有方法就会进入方法
Step Over:下一步如果有方法,方法会自动执行完成(不会进入方法)
4.查看程序执行的情况
Debugger:查看方法执行情况,查看程序中变量的变化情况
Console:普通控制台,输入数据或者查看输出的数据
5.停止debug:取消断点:如果不取消断点,下次运行时又会暂停到断点处。
6.调试时,灰色的提示指的是每一行变量的值
扩展:
如果程序很多,不知道打了哪些断点,可以点击View Breakpoints
,在这里可以看到所有的断点。
而点击Mute Breakpoints
之后,所有的断点都将不再生效。
六、数组总结
当把一个引用类型变量置为空时,相当于断开了和堆内存的联系,当联系断开之后,不能再通过此变量访问堆内存中对应的空间里的任何东西,包括长度和内容。如果强行访问会出现空指针异常。
观察变量值的方法:
可以看Debugger中Variables中的值,也可以直接看程序中的值。
day6之Java方法
课程设计:
1.先介绍
2.讲语法
3.做案例练习
4.讲理论
一、方法介绍
方法是把一些代码打包起来,在需要的地方可重复使用。
1.1什么是方法
1.方法是把一些代码打包在一起,用到的时候就调用。
2.方法是程序中最小的执行单元。程序员写的代码如果想执行,必须放在方法里面,Java在运行代码时是以方法为单元的,至少要运行一个方法,不能没有方法去直接运行一行代码。
3.方法只有在被调用时才会执行。
main方法是提供好的,main方法由JVM自动调用。
1.2用方法的好处
1.提高代码的复用性(抽取重复代码,重复使用)
2.提高代码的可维护性(方便修改)
二、方法定义和调用
方法定义是把一些代码打包在一起,用到的时候就调用。
方法定义:
把一些代码打包在一起,该过程称为方法定义。
方法调用:
方法定义后不直接运行,需要手动使用才能执行,该过程称为方法调用。
1.基本方法
1.1基本方法的定义和调用的格式和范例
1.JVM执行程序的入口是main方法,main方法和别的自定义的方法是并列(平级)关系,方法不能嵌套定义。
1.2IDEA中设置方法分割线:
FIle->Settings->Editor->General->Appearance->选中Show method separators
2.方法从上往下顺序执行的过程中,遇到方法就会跳到方法里面执行,执行完毕之后再回到执行点。
(帮助理解:高速公路服务区)
3.调换方法的定义顺序不会影响到程序的执行结果。
4.调换方法的调用顺序会影响程序的执行结果。
5.如果在eat()方法中调用drink(),在drink()方法中调用eat(),方法会循环调用,造成堆栈溢出。
StackOverflowError:堆栈溢出异常
1.3基本方法定义总结:
2.带参数的方法
2.1带参数方法的定义和调用
注意:
方法调用时。实参必须与形参保持相同的类型、数量和顺序。
形参:全称形式参数,方法定义中的参数。
实参:全称实际参数,方法调用中的参数。
形参列表即参数列表
3.带返回值的方法
方法的返回值就是方法运行的最终结果。
当调用一个方法时,如果方法的执行结果会在后续程序中用到,就需要方法将运行的结果返回。
3.1带返回值方法的定义
3.2带返回值方法的调用
return部分返回数据的类型必须和方法定义时声明的返回值类型一致。
总结:
4.方法总结
方法的注意事项:
main方法虽然我们没有调用,但是JVM调用了。
在return语句下面写的代码是无效代码,永远执行不到。
返回值类型是void,不能再接收结果
三、方法案例
1.方法的编写步骤
1.根据需求,判断方法是否有参数。参数的数量和类型分别是什么。
即通过分析确定参数列表。
2.分析方法是否有返回结果。返回值的类型是什么。
即通过分析确定返回值类型。
3.方法要处理的业务(具体实现)
2.计算1-n的和
3.判断一个整数是奇数还是偶数
分析参数的方法:把自己当成这个功能,缺什么要什么。
4.打印int类型的数组内容
数组转换成字符串
Arrays.toString(数组名);
Java已经提供了把一个数组转成字符串的方法
5.比较两个int类型的数组是否一样
四、方法重载
1.方法重载定义
重载是方法与方法之间的关系。
在同一个类中,名称相同,形参列表不同的多个方法,这些方法构成重载关系。
2.方法重载意义和场景
Java支持方法重载,是为了让调用者不用记忆太多繁琐的方法名称(方便)
开发中为了经常处理一类业务,提供多种解决方案,可以使用重载来设计程序。
如:System.out.println();
在底层通过方法重载
3.方法重载案例
五、方法执行原理
1.执行原理
● 方法被调用的时候,才会进入栈内存中运行。
栈是一种先进后出的数据结构。
sum方法运行结束后弹栈
main方法运行结束后弹栈
方法调用的时候入栈,只要调用完毕,就会弹栈。
需要注意的是:
在一个方法内部定义的变量,它在内存中的位置就在这个方法的内部。
不能试图从main方法中强行拿c变量,main方法和sum方法是隔离的,拿不到c变量,sum方法可以把值传递过来,但main方法不能直接使用c变量。
(帮助理解:邻居孩子可以抱抱,但不能直接成自己的。)
方法调用的时候入栈,只要调用完毕,就会弹栈。
2.参数传递
2.1参数传递概念
Java的参数传递机制都是:值传递
参数传递:调用方法的时候,把实参传给形参的过程
所谓值传递,指的是在传输实参给方法的形参的时候,传输的是实参变量中存储的值的副本
实参:全称实际参数,指方法调用中的参数
形参:全称形式参数,指方法定义中的参数,作用是接收实参中的数据
main方法中的a和change方法中的a没有关系,一个在main方法区域中,一个在change方法区域中,这两个方法中的变量相互之间是隔离的,没有任何关系。
change方法中a=20;
在改变a的值,改变的是change方法里a的值,change方法执行完毕之后弹栈。
main方法中的a没有发生变化。
2.2基本类型的参数传递:传递的是变量中保存的值
对于基本类型(4类8种),它们在参数传递的时候,传递的都是变量中存进去的值。
在另一个方法中改动这个值,不会影响本身这个方法。
因为传过去的是副本,改动的是复制的内容,对本身没有影响。
2.3引用类型的参数传递:传递的是变量中保存的地址
由于是把地址传递过去了,因此两个地方访问的是同一块空间(即同一块堆内存)。
基本数据类型变量里面保存的是值本身
引用数据类型变量里面保存的是内存地址
堆中存储的是数据真正的内容
栈中只会存储一个内存地址值
不管是基本数据类型还是引用数据类型,参数传递赋值时,赋过去的都是变量中保存的值的副本。
变量中原本保存的是地址值,就把这个地址值复制一份传递给change方法的形参。
由于引用类型变量存的是地址值,change方法中的arrs中的值和main方法中的arrs中的值指向的是同一块内存空间,通过在change方法中修改内存空间中所存的值,通过main方法中的arrs能看到修改后的结果。
2.4总结
参数传递,不管是基本类型还是引用类型都是值传递,传递的都是变量中保存的值。
此处,main方法和change方法中的a是完全隔离的,在change方法中修改a的值,main方法中a不会受任何影响。
(下图的帮助理解:同桌和你借电子书,你把电子书直接传给同桌,同桌把电子书改了、扔了、撕了,和你的电子书没有关系,你的那本还是那本。)
change方法中的arrs变量和main方法中的arrs变量,这两个变量指向了堆内存中的同一个内存区域。
(下图的帮助理解:你把电子书存到一个秘密的盘中,你给同桌的是一个盘的访问密码,你俩访问的是同一个东西,同桌现在把电子书修改、销毁,你也会受影响。)
day07-09之编程训练&比赛
20个题目
day10之面向对象
詹姆斯·高斯林:万物皆对象
一、面向对象
1.基础认知
1.1基本概念
类是创建对象的模板,要创建一个对象必须先有类。
类中主要包含两部分内容:属性(变量 静态)和动作(方法 动态)
直接写在类里面而不在方法里面的变量称为成员变量,也叫全局变量。
写在方法里面的变量:局部变量
类是创建对象的模板,要创建一个对象必须要先有类。
类是一个模板,想要用类必须创建它的对象。
类中主要包含两部分内容:
属性:变量(静态)
动作:方法(动态)
面向对象编程基本步骤:
1.创建一个类(编写属性和动作)
2.编写测试类(main方法,创建对象,属性赋值,调用方法)
1.2一个类可以创建多个对象
由同一类创建出来的两个对象没有关系,(如:两个同学买的同一个品牌同一个型号的电脑,其实都是同一个模板制造出来的,两个电脑本身一模一样,但是没有任何关系)
2.深入理解
2.1面向对象编程的好处?
万物皆对象。
汽车的数据找汽车对象处理
手机的数据找手机对象处理
学生的数据找学生对象处理
即谁的事情谁来做,谁的数据谁负责。
好处:更符合人类思维习惯,编程更简单、更直观。
2.2程序中的对象到底是什么?
对象是一个具体的东西,可以用属性和行为对其进行具体描述。
如果要创建一个汽车对象,必须要先有类
汽车的属性,都是在类中定义好的,对象只是把这些属性做了一个具体化,具体出来才是宝马,5系,黑色,50w。
类是抽象的,对象是对类的一个具体描述。
因此,可以总结如下:
对象是由类创建出来的,类是创建对象的模板,对象是类的具体实现
帮助理解:
类是抽象的,可以理解成月饼模具
做出来的一个个月饼是具体的对象。
模板是什么样,对象就得是什么样。
模板是抽象的,对象是具体能产生的东西。
这就是对象和模板(类)之间的关系。
2.2.1总结
属性具体来说就是变量
行为具体来说就是方法
类是对象的抽象
对象是类的具体
2.3对象是怎么出来的?
对象是由类创建出来的,类是创建对象的模板,对象是类的具体实现。
2.4创建对象注意事项
一个代码文件中,可以写多个class类,但只能一个用public修饰,并且,public修饰的类名必须与代码文件名一致。
如下图这种情况中,只能Teacher类用public修饰。
3.案例
4.内存图
对象在计算机中的执行原理
在方法中声明的变量出现在栈内存中,
在类中声明的变量出现在堆内存中。
也就是说变量存储的位置跟着它的“老大”走:
1.方法在栈里面,方法里声明的变量就在栈里面。
2.类实例化出来的对象最后在堆里面,因此对象里面的直接属性就会进入堆里面。
类的地址:标识对象是由哪个类创建出来的。
方法不进入堆内存,方法的字节码永远存在于方法区中。当方法被调用的瞬间,方法会压栈。
如上图,如果某个对象没有任何对象指向它,需要注意:
当堆内存中的对象,没有被任何变量引用(指向)时,就会被判定为内存中的==“垃圾”==。
Java存在垃圾自动回收机制,会自动清除掉垃圾对象,程序员不必操心。
总结:
二、封装
面向对象三大特征:封装、继承、多态
1.封装理论
1.1什么是封装?
在面向对象程序设计中,应把对象的属性和行为设计到对象内部去,且对象中的数据不能被随意访问。
1.2为什么要封装?
在类中默认定义的变量随时可被其他类访问、修改,是不安全的。
1.3封装的设计规范
合理隐藏、合理暴露
一个变量一旦被private修饰,它就不能被其它的类随意修改。
本类可以修改,只是其他的类不能随意修改
(帮助理解:你自己的娃想打就打,别人要打肯定不行)
成员变量用private修饰之后,提供公用(public)的set方法,之后想修改此成员变量的值,可以调用公共的方法。
(帮助理解:我把我家娃藏起来,别人想打打不着,但是可以让我来打,调用我的打娃方法)
隐藏属性,暴露方法!
总结:
2.this关键字
2.1Java就近原则
“ this ” : 当前对象(成员变量位置)
“ . ” : 的
2.2this是什么
this是一个变量,用在方法中,代表当前方法所属的对象
直接打印 this
2.3this的应用场景
this主要用来解决变量名称冲突问题
2.4成员变量和局部变量的区别
2.5this的执行原理
总结:
3.构造器
3.1构造器的特点
构造器又叫构造方法,用于创建对象,
有以下几个特点:
1.方法名必须和类名保持一致
2.方法没有返回值,也不能用void修饰
3.创建对象时,构造方法会被自动调用
4.一个类中若没有任何构造方法,Java会自动生成一个无参构造
构造器的作用:
可以在创建对象时执行一些有意义的代码
3.2构造器的应用场景
创建对象时同时完成对 对象成员变量(属性) 的初始化赋值
格式:Student s = new Student("张三",12);
3.3构造器注意事项
一个类中,若没有任何构造方法,Java会自动生成一个无参构造。
一个类中,一旦有了有参构造方法,Java将不会再生成无参构造,此时若需要无参构造,可自行创建。
3.4总结
4.案例
4.1对前面内容的总结
面向对象,把一个类的属性和方法封装到内部,属性不能被别人随意访问,需要用private修饰,此时成员变量不能被别的类访问,所以对外提供公共(public)的方法。
提供方法时引出一个问题,在传参时会出现局部变量和成员变量的命名冲突问题,又引入this关键字。
最后在创建完对象赋值时如果值非常多,赋值可能非常麻烦,又引入构造器(也即构造函数),它可以在new一个对象的时候,直接把参数传递进去。
4.2案例:学生类
4.3案例:航班类
三、JavaBean
1.介绍
JavaBean,又叫实体类,是一种特殊形式的类。
实体类的两个要求:
1.类中的成员变量都要私有,对外提供相应的get、set方法。
2.类中必须有一个公共的无参的构造器,也可以提供一些带参构造器,用于属性赋值。
变量可以保存数据,set方法和构造方法都可以存数据,get方法可以取数据。只留下这些就可以满足实体类。
实体类只负责数据的存取,而对数据的处理交给其他类来完成,以实现数据和数据业务处理相分离。
数据单独在一起,业务单独在一起。
(帮助理解:
比如StudentOperator类是你,Student类是你的钱包类,如果有人(比如我)向你借钱,我就需要找到你这个对象,你的钱在你的钱包里,之后你在你这个类里再去操作钱包,把钱拿出来给我。
就好像把原来的类一分为二,Student类中只保留数据本身以及和本身相关的存取方法,其他和业务相关的方法放到StudentOperator类中。
在StudentOperator类中,要操作Student类,就需要在StudentOperator类中维护一个Student对象的引用(即提供一个Student的变量)。
即你本身要有一个你的钱包的引用,没有这个引用你就找不到你的钱包。)
在StudentOperator类中维护一个student引用时,只声明一个Student类型的变量而不赋值,则这个变量默认值为null,再用这个变量调用方法时,会出现空指针异常。
需要做的是,先赋值(也可以先写死),然后就可以创建对象测试了,此时应该创建的对象是StudentOperator类的对象(因为只要创建了StudentOperator类的对象,一运行private Student student = new Student(1001,"张三",'男',19);
这句代码,就把Student对象创建出来了。)
此时,我们需要创建一个测试类,在main方法里创建一个studentOperator的对象,然后就可以调用studentOperator的方法且不需要赋值,可以直接调用。
在这个版本中,student对象的属性是写死在StudentOperator类中的,此时如果要修改student对象属性,就需要在StudentOperator类中进行修改。
这是不合理的,因为Student类和StudentOperator类是提供给别人用的,使用时还需要修改类本身的代码。
所以不能写死,应该在调用时传递什么对象就是什么对象。所以想要修改StudentOperator类中的属性student的值,应该给StudentOperator类中的属性(student变量)提供一个set方法,也可以提供全参构造方法。
只需要调用构造器,new一个对象,把对象传进去即可。(如下图)
现在如果要把张三改成李四,只需要在测试类中修改即可。
此时可以认为,现在的Student类和StudentOperator类就和JDK提供的random是一样的。不需要修改别人的代码,只需要修改给别人传的参数即可。
总结
1.实体类的作用:
实体类只负责保存数据,实体类中的东西都是和数据相关的。
变量可以保存数据,set方法和构造方法都可以存数据,get方法可以取数据。只留下这些就可以满足实体类。
2.案例
模仿电影信息系统
day11之字符串和集合
一、常用API
1.API概念
API:应用程序编程接口
API是别人写好的类,要使用得先学习其中的方法。
API是别人写好的一些程序,程序员直接拿去调用就可以解决问题。
使用API的原因:Java已有20多年发展历史,提高开发效率,不用重复造轮子。
2.包的概念和作用
包的作用:
包是分门别类管理程序的,即把类进行分目录管理,让类看起来没有那么乱。
也就是说,包就是来组织类这个结构的。
如下图是Java提供好的一些包:
day12之ATM系统
需求分析:
Account 银行账户类(实体类)
属性:
cardId: 卡号 8位数字 系统自动生成
username: 姓名 用户输入
password: 密码 用户输入,还要重复校验
gender: 性别 用户输入, 只能是男 女
money: 余额 初始化为0
limit: 每次的提现额度 用户输入
ATM(实体操作类)
启动系统的方法 start: 展示主界面,展示用户可以选择的功能
用户登录功能login: 登陆成功,展示子界面: 展示用户可以选择的功能
查询账户功能 showLoginAccount
存款功能depositMoney
转账功能 transferMoney
取款功能 drawMoney
注销功能 cancelAccount
修改密码功能 updatePassword
用户开户功能 createAccount: 开户成功,回退到主界面
ATMTest(测试类)
创建ATM,并调用start方法启动
一、项目技术分析
ATM系统技术选型:
Account:实体类
ATM:实体类的操作类
1.面向对象编程:
银行系统中的每个账户都是一个账户对象:需要设计账户类Account用于创建账户对象封装账户信息。
ATM也是一个对象,需要设计ATM类,代表ATM管理系统,负责对账户的处理。
2.使用集合容器:
ATM管理类中需要提供一个容器来存储系统中全部账户对象的信息,可以选择ArrayList集合。
3.流程控制:
做一些判断和循环:需要结合分支、循环、跳转关键字等程序流程控制知识,用来控制系统的业务流程。
4.使用常见API:
登录信息的内容比较,数据的分析、处理都需要常用API解决,如使用String。从键盘录入,需要用到Scanner对象。
二、系统架构搭建、欢迎页设计
1.系统架构搭建
-
定义一个账户类Account,需要包含(卡号、姓名、密码、性别、余额、单次提现额度)
-
定义一个ATM类,用来代表ATM系统,负责
-
定义一个测试类Test,负责对我们开发的ATM系统进行测试。
2.系统欢迎页设计
1.先定义一个账户实体类:
a.Account实体类
属性:
private String cardId;//卡号(8位数字 系统分配)
private String username;//姓名(字符串 用户输入)
private String password;//密码(字符串 用户输入,需要输入两次且一致)
private char gender;//性别(字符 用户输入且只能是男 女)
private double money;//余额(浮点型 开户默认为0)
private double limit;//单次提现限额(浮点型 用户输入)
2.再定义一个ATM类(实体操作类),负责业务处理,业务处理就是用方法编写功能。
在ATM类中设计一个start()方法,方法负责展示欢迎界面。
欢迎界面用户可以选择的功能有:登录(login)和开户(createAccount)。
b.start()方法
//启动系统的方法start:展示主界面,展示用户可以选择的功能
public void start(){
//死循环
while(true){
System.out.println("===欢迎进入银行系统===");
System.out.println("1.用户登录");
System.out.println("2.用户开户");
System.out.println("选择您要操作的命令:");
//创建键盘对象,接收用户输入的指令
Scanner scanner = new Scanner(System.in);
//使用String接收的原因是避免程序运行出错
String command = scanner.next();
switch(command){
case"1":
System.out.println("开始执行用户登录指令");
break;
case"2":
System.out.println("开始执行用户开户指令");
break;
default:
System.out.println("用户输入指令有误,请重新输入");
break;
}
}
}
分析需求,不管是上述的启动方法(start()),还是登录、开户方法,每个方法都要用到Scanner的对象,所以应该把scanner对象提升为成员变量。
因为成员变量可以被类中的所有方法访问,这样就不用在每个方法中单独创建。
3.再定义一个测试类Test,负责对开发的ATM系统进行测试。
小结:
对应面向对象编程的思想,Account类就是实体类,ATM类就是操作类,Test类就是测试类。
项目再大都遵循对象思想。
至此,搭建系统架构完成。
三、开户功能实现
欢迎页有两个功能,登录和开户。
我们先开发开户功能,因为开户之后才能登录。
所谓开户,就是新增一个账户,即给系统的账户集合中添加一个账户对象。
在ATM机中应该维护一个账户的集合,和Person的操作类中维护了一个Person的集合是一个道理。
系统开户的本质就是,从键盘接收用户输入的账户属性,保存在一个账户对象中,再把这个account账户保存到账户集合中。
public class ATM{
ArrayList<Account> accountList = new ArrayList<>();
}
c.createAccount()方法
//开户方法:本质上是向ATM系统中的账户集合中保存一个新账户(信息来自于用户键盘)
public void createAccount(){
System.out.println("===系统开户操作===");
//1.创建账户对象(属性没有值)
Account account = new Account();//这个account里的各个属性还没有值
//2.对账户对象的各个属性进行赋值(键盘录入)
//为各个属性一个一个进行赋值
//2-1 cardId:卡号(8位数字 系统分配)
String cardId = GenCardId();
account.setCardId(cardId);
//2-2 username:姓名(字符串 用户输入)
System.out.println("请您输入账户用户名");
String username = scanner.next();
account.setUsername(username);
//2-3 password:密码(字符串 用户输入,需要输入两次且一致)
while(true){
System.out.println("请您输入账户密码");
String password = scanner.next();
System.out.println("请您再次输入密码以确认");
String password2 = scanner.next();
if(!password.equals(password2)){
System.out.println("两次输入的密码不一致,请重新输入");
}else{
//密码一样,赋值到对象,并且跳出循环
account.setPassword(password);
break;//跳出循环
}
}
//2-4 gender:性别(字符 用户输入且只能是男 女)
while(true){
System.out.println("请您输入您的性别:");
char gender = scanner.next().charAt(0);
if(gender!='男&&gender!='女){
//用户输入有误
System.out.println("您输入的性别有误,请重新输入");
}else{
//输入正确——>先赋值,再跳出
account.setGender(gender);
break;
}
}
//2-5 money:余额(浮点型 开户默认为0)
//余额直接给个默认值就行,刚开完户余额一定是0
account.setMoney(0);
//2-6 limit:单次提现限额(浮点型 用户输入)
while(true) {
System.out.println("请您输入账户单次提现限额");
double limit = scanner.nextDouble();
if(limit<0){
System.out.println("您输入的限额额度有误,请重新输入");
}else{
account.setLimit(limit);
break;
}
}
//3.将账户对象保存到账户集合中
//集合应该new在方法的上面,这个账户集合在ATM类中的很多方法中都要使用,创建账户、查询需要在集合里拿,所以new集合应该放在全局变量的位置
accountList.add(account);
//4.提示开户成功
System.out.println("恭喜您,您开户成功,您的卡号是:88888888");
}
注释后面+todo,todo意思就是待办。
当在注释中加入todo后,能在IDEA的TODO:中看到未完成的代码。
生成卡号的方法:
d.genCardId()方法
public class ATM{
Random random = new Random();
}
//注释后面+todo,todo意思就是待办。
//当在注释中加入todo后,能在IDEA的TODO:中看到未完成的代码。
//todo 生成卡号
//八位数字 不能重复
public String genCardId(){
while(true) {
//1.生成8位数字的卡号
//循环8次,每次随机生成一个数字,最后将8次生成的结果拼成一个字符串即可
//随机生成要用到random对象,new random()可以写在本方法中,但考虑到其他对象也可能使用它,所以卸载全局变量的位置
String cardId = "";
for(int i=0; i<8; i++) {
cardId += random.nextInt(10);//0-9
}
//2.保证卡号不重复
//目前cardId变量中保存的是刚生成的新卡号,要跟accountList集合中所有账户的卡号做对比
if(findByCardId(cardId)==null) {
//在集合中找不到说明生成的账号没有被别人使用,可以继续开户
return cardId;
}else{
//虽然没有break跳出while循环,但又return。return也可以结束方法,把结果返回去,跳出循环。
//别人已经使用了,需要重新生成
}
}
}
此时需要一个新方法,根据cardId查询账户:
e.findByCardId()方法
public Account findByCardId(String cardId){
//遍历集合得到每个账户
for(int i=0;i<accountList.size();i++){
Account account = accountList.get(i);
//将传入的cardId和集合中获取到的account的cardId对比
if(cardId.equals(account.getCardId)){
return cardId;//将对象返回
}
}
//循环结束,没有找到cardId对应的对象
return null;
}
}
最后将提示开户成功信息中打印的内容修改:
//在Account实体类的getUsername()方法中加一个性别判断
public String getUsername(){
String u = gender =={ '男' ? username+"先生" : username+"女士" };
return u;
}
//4.提示开户成功
System.out.println("恭喜您,您开户成功,您的卡号是:88888888");
}
System.out.println("恭喜您,"+account.getUsername()+"开户成功,您的卡号是:"+account.getCardId());
}
四、用户登录功能
1.若系统中没有任何账户对象,不允许登录。
2.让用户输入登录的卡号,先判断卡号是否正确,若不正确要给出提示。
3.若卡号正确,再让用户输入密码。
若密码不正确要给出提示,若密码也正确,给出登录成功的提示。
f.login()方法
//登录方法login():本质是从控制台接收用户输入的账号和密码,与开户时留下的账号和密码进行对比。
public void login(){
//0.提前声明变量
Account account = null;
//1.判断当前ATM系统中是否没有任何账户,若是,直接返回展示
if(this.accountList.size()==0) {
System.out.println("您好,当前系统还没有账户");
//结束当前方法
return;
}
//2.接收用户控制台输入的账户信息,使用提供的账户信息去list中查询,若查询不到,重新输入。
while(true){
System.out.println("请您输入登录卡号:");
String cardId = scanner.next();
account = findByCardId(cardId);
if(account == null) {
//账户有误
System.out.println("系统中不存在该账户卡号");
}else{
//查到了账户,跳出循环,继续比对密码
break;
}
}
//3.接收用控制台输入的密码信息,使用提供的密码信息和刚才找到的账户中的密码比对,如果查询不到,重新输入。
while(true){
System.out.println("请您输入登录密码:");
String password = scanner.next();
//此处不能用account,要考虑到变量的作用域。变量从它声明的时候开始生效,直到它邻近的第一个"}"才失效。
//这时要考虑这个account是在所有方法中都使用,还是只在当前方法内使用。
//此处应该在login()方法开头提前声明变量account
if(!password.equals(account.getPassword())) {
//账户有误
System.out.println("系统中不存在该账户卡号");
}else{
//密码正确
break;
}
}
//4.提示登录成功信息
System.out.println("恭喜您,"+account.getUsername()+",您已进入系统,您的卡号是:"+account.getCardId());
}
为了方便测试,要做两个模拟数据。
所以要在start()方法的开头,先向账户集合中插入两个模拟账户。
相当于系统启动的时候就有两个内部账号。
public void start(){
//todo 临时模拟,上线之前要删除
//系统启动的时候,先向账户集合中插入两个模拟账户
accountList.add("66666666","测试1","123",'男',100,100);
accountList.add("88888888","测试2","123",'女',100,100);
......
}
至此,登录功能已实现。
五、操作页展示、查询账户、退出账户
登录成功后应该展示的界面,即操作页。
//此时需要在ATM类的成员变量位置声明一个登录成功后的用户变量
public class ATM{
......
Account currentAccount = null;
......
}
public void login(){
......
//3.接收用控制台输入的密码信息,使用提供的密码信息和刚才找到的账户中的密码比对,如果查询不到,重新输入。
//3.5这里需要将登录成功后的账户,登录成功之后,现将当前这个登录的账户保存到全局变量
currentAccount = account;
//4.提示登录成功信息
......
public void login(){
......
//5.登录成功之后,进入操作页
showOperationView();
}
g.showOperationView()方法
//登录成功之后,进入操作页,操作页提供登录成功之后的可选操作页
public void showOperationView(){
while(true){
System.out.println("===" + currentAccount.getUsername()+",您可以办理以下业务===");
System.out.println("1.查询账号");
System.out.println("2.存款");
System.out.println("3.取款");
System.out.println("4.转账");
System.out.println("5.修改密码");
System.out.println("6.退出");
System.out.println("7.注销账户");
System.out.println("请选择:");
String command = scanner.next();
switch(command){
case "1":
//展示当前用户对象currentAccount属性打印在控制台
showLoginAccount();
break;
case "2":
depositMoney();//存款:本质是修改当前账户的money值
break;
case "3":
drawMoney();//取款:本质是修改当前账户的money属性(要保证当次取款金额小于限额还有小于余额)
break;
case "4":
transferMoney();//转账:本质是修改两个账户的余额(当前账户扣钱,对方账户加钱(校验身份:1.账户 2.身份 3.余额))
break;
case "5":
updatePassword();//更新密码:本质是修改当前登录账户的password属性值
break;
case "6":
//退出 showOperationView()——>login() break——>swtich——>while循环
return;
case "7":
//销户操作:成功--欢迎页 失败--操作页面
boolean flag = cancelAccount();
if(flag){
//销户成功,返回到欢迎页
return;
}else{
//销户失败,留在操作界面
}
break;
default:
System.out.println("您输入的指令有误,请重新输入");
}
}
}
接下来,需要写一个登录用户信息展示方法:
h.showLoginAccount()方法
//将当前登录用户对象currentAccount属性打印在控制台
System.out.println("====正在展示当前登录用户的信息====");
System.out.println("卡号:" + currentAccount.getCardId());
System.out.println("姓名:" + currentAccount.getUsername());
System.out.println("余额:" + currentAccount.getMoney());
System.out.println("单词提现限额:" + currentAccount.getLimit());
六、用户密码修改
i.updatePassword()方法
//更新密码:本质是修改当前登录账户的password属性值
public void updatePassword(){
while(true){
System.out.println("====银行密码修改界面====");
System.out.println("请输入当前账户的密码:");
String oldPassword = scanner.next();
//与当前登录用户的密码对比
if(!currentAccount.getPassword().equals(oldPassword)){
//当前密码输入有误
System.out.println("当前账户密码不正确");
}else{
while(true){
//当前密码输入正确,应该输入新密码
System.out.println("请您输入新密码");
String password = scanner.next();
System.out.println("请再次输入新密码以确认:");
String password2 = scanner.next();
//判断两次输入的新密码是否一致
if(!password.equals(password2)){
System.out.println("您两次输入的密码不一致,请重新输入");
}else{
//输入的密码无误,重新设置密码
currentAccount.setPassword(password);
//提示
System.out.println("密码修改已成功。");
}
}
}
}
}
七、销户功能实现
销户操作:本质是从账户集合中删除当前登录账户
销户操作的基本需求:
cancelAccount()方法
//销户操作:本质是从账户集合中删除当前登录账户。
//在删除过程中判断:1.客户意愿2.是否有余额
private boolean cancelAccount(){
//1.询问用户是否要销户,如果答案是否,直接返回false
System.out.println("您真的要销户?y/n");
String command = scanner.next();
if(!command.equals("y")){
System.out.println("销户操作终止!");
return false;
}
//2.如果用户就是要销户,再判断是否有余额,如果有,提示无法销户,返回false
if(currentAccount.getMoney() > 0) {
System.out.println("您账户中还有钱没有取完,不允许销户!");
return false;
}
//3.执行销户操作,提示销户操作成功,返回true
accountList.remove(currentAccount);
System.out.println("销户成功,即将跳转到登录页面");
return true;
}
八、存款、取款功能实现
用户存款功能
存款操作的本质是:用户为自己的账户存钱,存钱后更新账户的余额。
depositMoney()方法
private void depositMoney(){
System.out.println("===存款操作界面===");
System.out.println("请您输入存款金额");
//这个m不能是负数
double m = scanner.nextDouble();//本次要存的金额
//拿到要存的钱之后要添加到当前的余额上
//1.先拿到当前账户的当前余额
double money = currentAccount.getMoney();//账户查出来的金额
//2.在当前余额的基础上加上本次要存的金额
money = money + m;
//3.将加后的余额保存回账户
currentAccount.setMoney(money);//重新赋值
//4.提示:存款成功
System.out.println("存款成功!本次存款金额" + m + "存完之后当前余额" + currentAccount.getMoney());
}
用户取款功能
取款操作的本质是:从自己的账户中取钱。
取钱的要求:
1.需要先让用户输入取款金额
2.需要判断取款金额是否超过单词限额、余额是否足够
drawMoney()方法
//取款:本质是修改当前账户的money属性(要保证当次取款金额小于限额还有小于余额)
private void drawMoney(){
System.out.println("===取款操作界面===");
System.out.println("请您输入取款金额");
//这个m不能是负数
double m = scanner.nextDouble();//本次要取的金额(键盘录入)
//1.当次取款金额小于限额
if(m > currentAccount.getLimit()){
System.out.println("对不起,您的本次取款金额已经超出限额,无法完成取款操作");
return;
}
//2.当次取款金额小于余额
if(m > currentAccount.getMoney()){
System.out.println("对不起,您的本次取款金额已经超出余额,无法完成取款操作");
return;
//3.执行取款操作(修改当前账户的money属性值)
currentAccount.setMoney(currentAccount.getMoney()-m);
/*
//1.先拿到当前账户的当前余额
double money = currentAccount.getMoney();//账户查出来的金额
//2.在当前余额的基础上减去本次要取的金额
money = money - m;
//3.将减后的余额保存回账户
currentAccount.setMoney(money);//重新赋值
*/
//4.提示:存款成功
System.out.println("取款成功!本次取款金额" + m + "取款之后当前余额" + currentAccount.getMoney());
}
九、转账功能实现
转账:本质是修改两个账户的余额(当前账户扣钱,对方账户加钱(校验身份:1.账户 2.身份 3.余额))
transferMoney()方法
//转账:本质是修改两个账户的余额(当前账户扣钱,对方账户加钱(校验身份:1.账户 2.身份 3.余额))
private void transferMoney(){
double money = 0;
Account targetAccount = null;
System.out.println("===转账操作界面===");
//1.输入接收款项的账户id,检验id是否在本银行存在,若不存在,重新输入
while(true){
//1-1 接收卡号
System.out.println("请输入对方账户:");
String cardId = scanner.next();
//1-2拿到卡号,根据卡号查询是否有账户
targetAccount = findByCardId(cardId);
if(targetAccount == null){
//账户输错了,提示对方重输
System.out.println("请输入的对方账户有误,请重新输入");
}else{
break;//输入正确,跳出循环
}
}
//2.输入接收款项的账户的用户名姓氏,校验对方身份,若校验失败,重新输入
//2-1获取对方的名和姓
String username = targetAccount.getUsername();//林允儿
String xing = username.substring(0,1);//林允儿——>林——>substring(0,1)
String ming = username.substring(1);//林允儿——>允儿——>substring(1)
while(true){
System.out.println("您当前要为【*"+ming+"】转账");
System.out.println("请您输入收款方姓氏");
//2-2从键盘接收对方的姓氏
String xingFromKeyBoard = scanner.next();
//2-3对比键盘接收的姓 vs 截取得到的姓
if(!xingFromKeyBoard.equals(xing)) {
System.out.println("对方姓氏输入有误,请重新输入");
} else{
//输入正确,跳出循环
break;
}//else
}//while
//3.接收键盘录入的转账金额,对金额也要进行判断(跟余额对比),若大于余额,重新输入
while(true){
System.out.println("请您输入转账金额");
money = scanner.nextDouble();
if(money<0 || money>currentAccount.getMoney()){
System.out.println("请您输入的转账金额有误,请重新输入");
}else{
break;
}
}
//4.执行转账操作,给出操作成功提示
//4-1对方账户加钱
targetAccount.setMoney(targetAccount.getMoney() + money);
//4-2自己账户减钱
currentAccount.setMoney(currentAccount.getMoney() - money);
//4-3给出成功提示
System.out.println("恭喜您转账成功,本次转账金额"+money+",当前账户余额:"+currentAccount.getMoney());
}