每日笔记

Account

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package com.zxq._02_atm;

import java.time.LocalDateTime;
import java.util.StringJoiner;

/*
账户的抽象的父类
*/
public abstract class Account {

// 使用 stringjoiner拼接操作的日志
private StringJoiner log = new StringJoiner("\r\n");

private String id; // 卡号
private String password;// 密码
private double money; // 余额
private double limit;// 单次取款限额

private Person person;// 所属人

private AccountType type; // 卡片的类型 储蓄卡,信用卡

@Override
public String toString() {
return "Account{" +
"id='" + id + '\'' +
", password='" + password + '\'' +
", money=" + money +
", limit=" + limit +
", person=" + person +
", type=" + type +
'}';
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public double getMoney() {
return money;
}

public void setMoney(double money) {
this.money = money;
}

public double getLimit() {
return limit;
}

public void setLimit(double limit) {
this.limit = limit;
}

public Person getPerson() {
return person;
}

public void setPerson(Person person) {
this.person = person;
}

public AccountType getType() {
return type;
}

public void setType(AccountType type) {
this.type = type;
}

public Account() {
}

public Account(String id, String password, double money, double limit, Person person, AccountType type) {
this.id = id;
this.password = password;
this.money = money;
this.limit = limit;
this.person = person;
this.type = type;
}

public void writeLog(String type) {
// 记录日志,
log.add(person.getName()+"在"+ LocalDateTime.now()+"进行了: "+type+" 操作!");
}

public void showLogs() {
System.out.println(log);
}
}

Person

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.zxq._02_atm;
/*
公民类
*/
public class Person {
private String name;
private char sex;
private String id;

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", sex=" + sex +
", id='" + id + '\'' +
'}';
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public char getSex() {
return sex;
}

public void setSex(char sex) {
this.sex = sex;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public Person() {
}

public Person(String name, char sex, String id) {
this.name = name;
this.sex = sex;
this.id = id;
}
}

MyScannerUtils_v2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.zxq._02_atm;

import java.util.Scanner;

/*
在java的scanner的基础上,再次封装,解决键盘输入的数据不合法的问题,及nextLine丢失键盘输入的机会的问题
*/
public class MyScannerUtils_v2 {
private static Scanner sc = new Scanner(System.in);
private MyScannerUtils_v2(){

}
// 提供静态方法,让调用者直接使用
public static int getInt(){
// 让用户循环输入,直到输入整数为止
while (true){
try {
String s = sc.nextLine();
return Integer.parseInt(s);
} catch (Exception e) {
// 把残留在内存中的不是整数的数据"吃掉"
System.out.println("请务必输入整数.....");
}
}
}
public static double getDouble(){
// 让用户循环输入,直到输入整数为止
while (true){
try {
String s = sc.nextLine();
return Double.parseDouble(s);
} catch (Exception e) {
// 把残留在内存中的不是整数的数据"吃掉"
System.out.println("请务必输入小数.....");
}
}
}
public static String getString(){
return sc.nextLine();
}

}

AccountType

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.zxq._02_atm;
/*
卡片的类型

属性:
利率
透支额度
类型描述


*/
public enum AccountType {
XY(0,10000,"信用卡"),CX(0.001,0,"储蓄卡");
private double ll;
private double tz;
private String type;

public double getLl() {
return ll;
}

public double getTz() {
return tz;
}

public String getType() {
return type;
}

AccountType(double ll, double tz, String type) {
this.ll = ll;
this.tz = tz;
this.type = type;
}
}

SavingsAccount

1
2
3
4
5
6
7
8
9
10
11
package com.zxq._02_atm;

public class SavingsAccount extends Account implements Transaction{
public SavingsAccount() {
}

public SavingsAccount(String id, String password, double money, double limit, Person person, AccountType type) {
super(id, password, money, limit, person, type);
}
}

CreditAccount

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.zxq._02_atm;

import java.time.LocalDateTime;
import java.util.StringJoiner;

/*
信用卡,添加专属的属性 催账员
*/
public class CreditAccount extends Account implements Transaction{

// // 使用 stringjoiner拼接操作的日志
// private StringJoiner log = new StringJoiner("\r\n");

private String czy;

public CreditAccount(String id, String password, double money, double limit, Person person, AccountType type, String czy) {
super(id, password, money, limit, person, type);
this.czy = czy;
}

public String getCzy() {
return czy;
}

public void setCzy(String czy) {
this.czy = czy;
}

@Override
public String toString() {
return "信用卡{" +
"催账员是:'" + czy + '\'' +super.toString()+
'}';
}

// @Override
// public void writeLog(String type) {
// // 记录日志,
// log.add(getPerson().getName()+"在"+LocalDateTime.now()+"进行了: "+type+" 操作!");
// }
//
// @Override
// public void showLogs() {
// System.out.println(log);
// }
}

Transaction

1
2
3
4
5
6
7
8
9
package com.zxq._02_atm;

import java.util.StringJoiner;

public interface Transaction {
void writeLog(String type);
void showLogs();
}

MyBusnessException

1
2
3
4
5
6
7
8
package com.zxq._02_atm;

public class MyBusnessException extends RuntimeException{
public MyBusnessException(String message) {
super(message);
}
}

ATM_System

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
package com.zxq._02_atm;

import java.util.Arrays;
import java.util.IdentityHashMap;
import java.util.Random;

/*
atm核心业务相关的内容,都在这个类中

1: 注册
2: 登录
3: 存款
4: 取款
5: 转账
6: 注销

设计一个 账户的数组,用于保存账户的信息


*/
public class ATM_System {
private Account[] accounts = new Account[3];

public ATM_System(){
accounts[0] = new CreditAccount("1", "1", 0, 10000, new Person("管理员", '女', "123456"), AccountType.XY, "张小");
accounts[1] = new SavingsAccount("2", "2", 0, 10000, new Person("管理员2", '男', "123456"), AccountType.CX);
}

private Account loginedAccount; // 这个变量专门记录已经登录的用户对象,以便于后续的存款,取款,转账...

// 展示菜单的方法
public void showMenu() {
System.out.println("----------------欢迎进入ATM系统---------------");
while (true) {
System.out.println("请选择要执行的功能:");
System.out.println("1: 注册");
System.out.println("2: 登录");
int i = MyScannerUtils_v2.getInt();
switch (i) {
case 1 -> regist();
case 2 -> login();
default -> System.out.println("输入有误,请重新输入!");
}
}
}

private void regist() {
// 让用户输入基本信息 姓名,性别,身份证号,密码,单次取款限额,卡片类型
// 系统生成不重复的卡号 10位数
System.out.println("请输入姓名:");
String name = MyScannerUtils_v2.getString();
//System.out.println("请输入性别:"); // 性别从身份证的第17位数字获取,如果是奇数代表男,偶数代表女
char sex;
String cardId;
while (true) {
System.out.println("请输入身份证号:");
cardId = MyScannerUtils_v2.getString();
if (cardId.length() != 18) {
System.out.println("身份证号不合法,请重新输入");
continue;
}
sex = Integer.parseInt(cardId.substring(16, 17)) % 2 == 1 ? '男' : '女';
break;
}
String password;
while (true) {
System.out.println("请输入密码:");
password = MyScannerUtils_v2.getString();
System.out.println("请确认密码:");
String rePassword = MyScannerUtils_v2.getString();
if (!password.equals(rePassword)) {
System.out.println("两次密码不一致,请重新输入!");
} else {
break;
}
}
double limit;
while (true) {
System.out.println("请输入单次取款的限额:");
limit = MyScannerUtils_v2.getDouble();
if (limit > 0) {
break;
}
System.out.println("必须大于0!");
}
// 一切信息都合法的情况下,直接创建对应的卡片对象,生成唯一id,并添加到 数组中保存起来
int index = getIndex();
if (index == -1) {
// 记录扩容前,数组的长度,作为即将添加的账户索引使用
index = accounts.length;
// 说明数组存满了,扩容,
accounts = Arrays.copyOf(accounts, accounts.length + accounts.length / 2);
}
String id = getId();
// 卡片类型
while (true) {
System.out.println("请选择卡片的类型:1信用卡 2:储蓄卡");
int type = MyScannerUtils_v2.getInt();
switch (type) {
case 1 -> {
accounts[index] = new CreditAccount(id, password, 0, limit, new Person(name, sex, cardId), AccountType.XY, "小张");
System.out.println("恭喜您:" + name + (sex == '男' ? " 先生" : " 女士") + "您的信用卡账户开通成功,账号是:" + id);
}
case 2 -> {
accounts[index] = new SavingsAccount(id, password, 0, limit, new Person(name, sex, cardId), AccountType.CX);
System.out.println("恭喜您:" + name + (sex == '男' ? " 先生" : " 女士") + "您的储蓄卡账户开通成功,账号是:" + id);
}
default -> {
System.out.println("类型有误,请重新输入!");
continue;
}
}
accounts[index].writeLog("注册");
return;
}
}

/*
让用户输入 卡号和密码,如果校验成功,则把这个对象记录下来,如果失败,就提示
*/
private void login() {
System.out.println("请输入卡号:");
String id = MyScannerUtils_v2.getString();
int i = findAccountById(id);
if (i == -1) {
System.out.println("卡号不存在,请先去注册!");
} else {
// 继续提示输入密码进行比较
System.out.println("请输入密码:");
String password = MyScannerUtils_v2.getString();
if(accounts[i].getPassword().equals(password)){
// 密码对了,登录成功,则把这个对象记录下来
loginedAccount = accounts[i];
loginedAccount.writeLog("登陆");
// 展示二级菜单
showMenu2();
}else {
System.out.println("密码不对呀!");
}
}
}

private void showMenu2() {
while (true){
try {
System.out.println("-------------尊敬的:"+loginedAccount.getType().getType()+"用户"+loginedAccount.getPerson().getName()+"请选择您的操作--------------");
System.out.println("0: 查看详情");
System.out.println("1: 存款");
System.out.println("2: 取款");
System.out.println("3: 转账");
System.out.println("4: 销户");
System.out.println("5: 退出");
System.out.println("6: 查看日志");
int i = MyScannerUtils_v2.getInt();
switch (i){
case 0 -> showInfo();
case 1 -> addMoney();
case 2 -> drawMoney();
case 3 -> trans();
case 4 -> {
boolean delete = delete();
if(delete){
return;
}
}
case 5 -> {
return;
}
default -> System.out.println("输入有误!");
case 6-> loginedAccount.showLogs();
}
}catch (Exception e){
//e.printStackTrace();
System.err.println(e.getMessage());
}
}
}

private boolean delete() {
/*
1: 判断余额是否为 0
2: 把当前位置的对象设置为null
*/
if(loginedAccount.getMoney() != 0){
System.out.println("余额不是0,不能销户!");
return false;
}
System.out.println("该操作,将彻底删除用户信息,确认要删除吗?确认输入1,输入其他取消");
String string = MyScannerUtils_v2.getString();
if("1".equals(string)){
int i = findAccountById(loginedAccount.getId());
accounts[i] = null;
System.out.println("感谢您的陪伴...");
loginedAccount.writeLog("销户成功");
return true;
}else {
loginedAccount.writeLog("取消销户");
System.out.println("已取消操作!");
return false;
}
}

private void trans() {
/*
1: 用用户输入收款人 卡号
2: 根据卡号查询对象
如果没有查询到,直接结束
如果查询到了,判断是不是自己,是自己直接结束
查到了,并且不是自己,
3: 输入转账金额
4: 校验合法性及是否超过了自己的余额
5: 输入对方的 名字中的第1个字,并判断是否匹配
6: 分别操作两个账户的余额
*/
System.out.println("请输入收款人卡号:");
String id = MyScannerUtils_v2.getString();
int i = findAccountById(id);
// 如果没有查询到,直接结束
if(i == -1){
//System.out.println("收款人不存在~");
//return;
loginedAccount.writeLog("转账的时候,收款人不存在");
throw new MyBusnessException("收款人不存在~");
}
//如果查询到了,判断是不是自己,是自己直接结束
if(accounts[i] == loginedAccount){
//System.out.println("不能给自己转账~");
//return;
throw new MyBusnessException("不能给自己转账~");
}
//3: 输入转账金额
System.out.println("请输入转账金额:");
double v = MyScannerUtils_v2.getDouble();
// 4: 校验合法性及是否超过了自己的余额
if(v <= 0 || v > loginedAccount.getMoney()+loginedAccount.getType().getTz()){
System.out.println("自己都没钱,就别慷慨了...");
return;
}
//5: 输入对方的 名字中的第1个字,并判断是否匹配
System.out.println("请输入对方的姓氏:");
String xing = MyScannerUtils_v2.getString();
if(accounts[i].getPerson().getName().startsWith(xing)){
// 6: 分别操作两个账户的余额
loginedAccount.setMoney(loginedAccount.getMoney()-v);
accounts[i].setMoney(accounts[i].getMoney()+v);
System.out.println("转账成功~");
loginedAccount.writeLog("转账成功");
}else {
System.out.println("收款人信息有误!");
}


}

private void drawMoney() {
while (true) {
System.out.println("请输入取款金额:(0代表退出)");
double v = MyScannerUtils_v2.getDouble();
if(v == 0){
System.out.println("取消操作...");
break;
}
if(v < 0 ){
//throw new MyBusnessException("金额不合法!");
System.out.println("金额不合法!请重新输入!");
continue;
}
// 校验是否超过了单次的限额
if(v > loginedAccount.getLimit()){
System.out.println("超过了单次操作的限额,您的限额是:"+loginedAccount.getLimit());
continue;
}
double tz= loginedAccount.getMoney()+loginedAccount.getType().getTz();
if(v> tz){
System.out.println("余额不足,您可以取款的最大金额是:"+tz);
continue;
}
loginedAccount.setMoney(loginedAccount.getMoney()-v);
System.out.println("取款:"+v+"元成功,余额为:"+loginedAccount.getMoney());
break;
}
}

private void addMoney() {
while (true) {
System.out.println("请输入存款金额:");
double v = MyScannerUtils_v2.getDouble();
if(v <= 0 ){
//throw new MyBusnessException("金额不合法!");
System.out.println("金额不合法!请重新输入!");
continue;
}
loginedAccount.setMoney(loginedAccount.getMoney()+v);
System.out.println("存入:"+v+"元成功,余额为:"+loginedAccount.getMoney());
break;
}
}

private void showInfo() {
StringBuilder sb = new StringBuilder();
StringBuilder append = sb.append("卡号:")
.append(loginedAccount.getId())
.append("\r\n")
.append("余额:")
.append(loginedAccount.getMoney())
.append("\r\n")
.append("限额:")
.append(loginedAccount.getLimit())
.append("\r\n")
.append("所属用户:")
.append(loginedAccount.getPerson().getName())
.append("\r\n")
.append("账户类型:")
.append(loginedAccount.getType().getType())
.append("\r\n")
.append("利率:")
.append(loginedAccount.getType().getLl())
.append("\r\n")
.append("透支额度:")
.append(loginedAccount.getType().getTz());
System.out.println(append);


}

// 找数组中为null的索引位置
private int getIndex() {
for (int i = 0; i < accounts.length; i++) {
if (accounts[i] == null) {
return i;
}
}
return -1;
}

// 生成不重复的id的方法
private String getId() {
Random random = new Random();
while (true) {
StringBuilder sb = new StringBuilder();
sb.append(random.nextInt(1, 10));
for (int i = 0; i < 9; i++) {
sb.append(random.nextInt(10));
}
String id = sb.toString();
// 校验是否重复,如果重复了,则重新生成
int i = findAccountById(id);
if (i == -1) {
return id;
}
}
}

private int findAccountById(String id) {
for (int i = 0; i < accounts.length; i++) {
if (accounts[i] != null && accounts[i].getId().equals(id)) {
return i;
}
}
return -1;
}
}

APP

1
2
3
4
5
6
7
8
9
10
package com.zxq._02_atm;
/*
程序的入口类
*/
public class APP {
public static void main(String[] args) {
new ATM_System().showMenu();
}
}