public class Account {
private String ano; //계좌번호
private String owner; //계좌주
private int balance; //잔고
public Account(String ano, String owner, int balance) {
this.ano = ano;
this.owner = owner;
this.balance = balance;
}
public String getAno() {
return ano;
}
public void setAno(String ano) {
this.ano = ano;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) { //잔액변경
this.balance = balance;
}
}
package a0113.Account3;
import java.util.Scanner;
public class BankApp {
//Account acc = new Account("123-123", "이순신", 10000);
// 객체를 하나만 만든다.
//Account 객체를 100개를 관리하고 싶다.
private static Account[] accountsArray = new Account[100];
//Account 객체 100를 관리하는 배열을 만든다.
private static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
boolean run = true;
while (run) {
System.out.println("-------------------------------------------------------------------");
System.out.println("1.계좌생성 | 2.계좌목록 | 3. 예금 | 4. 출금 | 5.계좌이체 | 6. 종료");
System.out.println("-------------------------------------------------------------------");
System.out.print("선택> ");
int selNum = 0;
try{
selNum = Integer.parseInt(scanner.nextLine());
}catch(Exception e){
}
//a 라고 문자를 입력해도
//에외처리 - 에러발생해도 프로그램 계속실행 - while
switch(selNum){
case 1 : createAccount();
break;
case 2 : accountList();
break;
case 3 : deposit();
break;
case 4 : withdraw();
break;
case 5 : transfer();
break;
case 6:
System.out.println("프로그램 종료");
run = false;
break;
}
}
}
private static void transfer() {
System.out.println("-----------");
System.out.println("계좌이체");
System.out.println("-----------");
System.out.print("출금 계좌번호: ");
String ano = scanner.nextLine();
System.out.print("입금 계좌번호: ");
String send = scanner.nextLine();
Account account = findAccount(ano);
Account sendAccount = findAccount(send);
if(account == null || sendAccount == null){
System.out.println("결과 : 계좌가 없습니다.");
return;
}
System.out.print("이체금액 : ");
int money = 0;
try {
money = Integer.parseInt(scanner.nextLine());
if(money<=0){
System.out.println("이체 금액은 1원이상이여야 합니다.");
return;
}
if(account.getBalance() <= money){
//잔액보다 찾는 금액이 많으면 잔액부족
System.out.println("잔액부족입니다.");
return;
}
account.setBalance(account.getBalance() - money); //보낸사람 객체에서 잔액 - 이체금액
sendAccount.setBalance(sendAccount.getBalance() + money);//받는사람 객체에서 잔액 + 이체금액
System.out.println("이체성공");
} catch (NumberFormatException e) {//숫자 에러(문자가 들어왔을때)
System.out.println("잘못된입력 입니다. 숫자를 입력해 주세요.");
}
}
private static void withdraw() {
System.out.println("-----------");
System.out.println("출금");
System.out.println("-----------");
System.out.print("계좌번호: ");
String ano = scanner.nextLine();
Account account = findAccount(ano);
if(account == null){
System.out.println("결과 : 계좌가 없습니다.");
return;
}
System.out.print("출금액 : ");
try {
int money = Integer.parseInt(scanner.nextLine());
if(money<=0){
System.out.println("출금액은 1원이상이여야 합니다.");
return;
}
if(account.getBalance() <= money){
//잔액보다 찾는 금액이 많으면 잔액부족
System.out.println("잔액부족입니다.");
return;
}
account.setBalance(account.getBalance() - money);
System.out.println("결과 :출금완료 현재잔액 :"+ account.getBalance() + "원");
} catch (NumberFormatException e) {//숫자 에러(문자가 들어왔을때)
System.out.println("잘못된입력 입니다. 숫자를 입력해 주세요.");
}
}
private static void deposit() {//3. 예금
System.out.println("-----------");
System.out.println("예금");
System.out.println("-----------");
System.out.print("계좌번호: ");
String ano = scanner.nextLine();
Account account = findAccount(ano);
if(account == null){
System.out.println("결과 : 계좌가 없습니다.");
return;
}
System.out.print("예금액 : ");
try {
int money = Integer.parseInt(scanner.nextLine());
if(money<=0){
System.out.println("예금액은 1원이상이여야 합니다.");
return;
}
account.setBalance(account.getBalance() + money);
} catch (NumberFormatException e) {//숫자 에러(문자가 들어왔을때)
System.out.println("잘못된입력 입니다. 숫자를 입력해 주세요.");
}
}
private static void createAccount() {
System.out.println("------------------");
System.out.println("계좌생성");
System.out.println("------------------");
System.out.print("계좌입력 : ");
String ano = scanner.nextLine();
if(findAccount(ano) != null){
System.out.println("이미 존재하는 계좌번호 입니다.");
return;
}
System.out.print("계좌주: ");
String owner = scanner.nextLine();
System.out.print("초기입금액: ");
int balance = 0; //잔액 0 초기
try {
balance = Integer.parseInt(scanner.nextLine());
if(balance < 0){
System.out.println("초기입금액은 0원 이상이여야 합니다.");
return;
}
Account newAccount = new Account(ano, owner,balance);
for(int i =0; i < accountsArray.length;i++){
if(accountsArray[i] == null){
accountsArray[i] = newAccount;
System.out.println("결과 계좌가 생성되었습니다.");
break;
}
}
} catch (Exception e) {
System.out.println("잘못된 입력입니다. 숫자를 입력하세요" );
}
}
private static void accountList(){
System.out.println("---------------");
System.out.println("계좌목록");
System.out.println("---------------");
for(int j =0; j < accountsArray.length;j++ ){
if(accountsArray[j] != null){
System.out.printf("%s %4s %d\n", accountsArray[j].getAno(),accountsArray[j].getOwner(),accountsArray[j].getBalance());
}
}
}
private static Account findAccount(String ano) { //계좌번호 유무 찾는 메소드
Account account = null;
//반환 될 값 초기화
for(int k =0; k < accountsArray.length;k++ ){
if(accountsArray[k] != null){
String dbAno = accountsArray[k].getAno();
if(dbAno.equals(ano)){
account = accountsArray[k];
break;
}
}
}
return account;
}
}
은행 애플리케이션 데이터 흐름 시각화
📌 프로그램 구조
클래스 구조
┌─────────────────────────────────────┐
│ BankApplication (메인 클래스) │
├─────────────────────────────────────┤
│ - accountsArray: Account[100] │
│ - scanner: Scanner │
├─────────────────────────────────────┤
│ + main() │
│ - createAccount() │
│ - accountList() │
│ - deposit() │
│ - withdraw() │
│ - transfer() │
│ - findAccount() │
└─────────────────────────────────────┘
│
│ 사용
▼
┌─────────────────────────────────────┐
│ Account (계좌 클래스) │
├─────────────────────────────────────┤
│ - ano: String (계좌번호) │
│ - owner: String (계좌주) │
│ - balance: int (잔액) │
├─────────────────────────────────────┤
│ + getAno() │
│ + getOwner() │
│ + getBalance() │
│ + setBalance() │
└─────────────────────────────────────┘
1️⃣ 배열 구조
accountsArray 초기 상태
┌─────────────────────────────────────────────────────────┐
│ accountsArray (Account[100]) │
├─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬──────┤
│ [0] │ [1] │ [2] │ [3] │ ... │[99] │ │ │ │
├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼──────┤
│null │null │null │null │ ... │null │ │ │ │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴──────┘
↑
모든 요소가 null (초기 상태)
2️⃣ 계좌 생성 (createAccount)
실행 흐름
사용자 입력
↓
계좌번호: "123-456"
계좌주: "홍길동"
초기입금액: 10000
↓
findAccount("123-456") 호출
↓
배열에서 계좌 찾기
↓
계좌가 없으면 → 새 Account 객체 생성
↓
배열의 빈 자리(null)에 저장
메모리 구조 변화
1단계: Account 객체 생성
┌─────────────────────────────────────┐
│ Heap 메모리 │
├─────────────────────────────────────┤
│ │
│ ┌───────────────────────────────┐ │
│ │ Account 객체 │ │
│ │ ano: "123-456" │ │
│ │ owner: "홍길동" │ │
│ │ balance: 10000 │ │
│ └───────────┬───────────────────┘ │
│ │ │
└──────────────┼──────────────────────┘
│ 참조
│
┌──────────────▼──────────────────────┐
│ accountsArray[0] │
│ = newAccount │
└─────────────────────────────────────┘
2단계: 배열에 저장
accountsArray 초기 상태:
┌─────┬─────┬─────┬─────┬─────┬─────┐
│ [0] │ [1] │ [2] │ [3] │ ... │[99] │
├─────┼─────┼─────┼─────┼─────┼─────┤
│null │null │null │null │ ... │null │
└─────┴─────┴─────┴─────┴─────┴─────┘
createAccount() 실행 후:
┌─────┬─────┬─────┬─────┬─────┬─────┐
│ [0] │ [1] │ [2] │ [3] │ ... │[99] │
├─────┼─────┼─────┼─────┼─────┼─────┤
│ │null │null │null │ ... │null │
│ Acc │ │ │ │ │ │
│객체 │ │ │ │ │ │
│참조 │ │ │ │ │ │
└─────┴─────┴─────┴─────┴─────┴─────┘
▲
│
┌───┴──────────────────────────────┐
│ Account 객체 │
│ ano: "123-456" │
│ owner: "홍길동" │
│ balance: 10000 │
└───────────────────────────────────┘
여러 계좌 생성 시
계좌 3개 생성 후:
accountsArray:
┌─────┬─────┬─────┬─────┬─────┬─────┐
│ [0] │ [1] │ [2] │ [3] │ ... │[99] │
├─────┼─────┼─────┼─────┼─────┼─────┤
│ Acc1│ Acc2│ Acc3│null │ ... │null │
│참조 │참조 │참조 │ │ │ │
└──┬──┴──┬──┴──┬──┴─────┴─────┴─────┘
│ │ │
│ │ └─► Account { ano: "789", owner: "이영희", balance: 5000 }
│ │
│ └─► Account { ano: "456", owner: "김철수", balance: 20000 }
│
└─► Account { ano: "123-456", owner: "홍길동", balance: 10000 }
3️⃣ 계좌 찾기 (findAccount)
실행 흐름
findAccount("123-456") 호출
↓
┌─────────────────────────────────────┐
│ 배열을 처음부터 끝까지 순회 │
│ (for문: k = 0 ~ 99) │
└───────────┬─────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ accountsArray[k]가 null인가? │
│ → null이면 다음 요소로 │
│ → null이 아니면 계좌번호 비교 │
└───────────┬─────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ accountsArray[k].getAno() │
│ .equals("123-456") ? │
│ → 같으면: 해당 Account 반환 │
│ → 다르면: 다음 요소로 │
└─────────────────────────────────────┘
시각적 표현
배열 탐색 과정:
accountsArray:
┌─────┬─────┬─────┬─────┬─────┐
│ [0] │ [1] │ [2] │ [3] │ ... │
├─────┼─────┼─────┼─────┼─────┤
│ Acc1│ Acc2│ Acc3│null │ ... │
│참조 │참조 │참조 │ │ │
└──┬──┴──┬──┴──┬──┴─────┴─────┘
│ │ │
│ │ │
▼ ▼ ▼
┌────┐ ┌────┐ ┌────┐
│123 │ │456 │ │789 │
│홍 │ │김 │ │이 │
│1000│ │2000│ │5000│
└────┘ └────┘ └────┘
findAccount("456") 실행:
↓
[0] 비교: "123" ≠ "456" → 다음
[1] 비교: "456" = "456" → 찾음! ✅
↓
accountsArray[1] 반환
4️⃣ 예금 (deposit)
실행 흐름
사용자 입력
↓
계좌번호: "123-456"
예금액: 5000
↓
findAccount("123-456") 호출
↓
Account 객체 찾기
↓
계좌가 없으면 → "계좌가 없습니다."
↓
계좌가 있으면 → 잔액 증가
account.setBalance(
account.getBalance() + money
)
메모리 변화
예금 전
┌─────────────────────────────────────┐
│ Account 객체 (accountsArray[0]) │
├─────────────────────────────────────┤
│ ano: "123-456" │
│ owner: "홍길동" │
│ balance: 10000 ←─── 현재 잔액 │
└─────────────────────────────────────┘
예금 실행
account.setBalance(account.getBalance() + money)
↓
account.setBalance(10000 + 5000)
↓
account.setBalance(15000)
↓
예금 후
┌─────────────────────────────────────┐
│ Account 객체 (accountsArray[0]) │
├─────────────────────────────────────┤
│ ano: "123-456" │
│ owner: "홍길동" │
│ balance: 15000 ←─── 증가된 잔액 │
└─────────────────────────────────────┘
5️⃣ 출금 (withdraw)
실행 흐름
사용자 입력
↓
계좌번호: "123-456"
출금액: 3000
↓
findAccount("123-456") 호출
↓
Account 객체 찾기
↓
계좌가 없으면 → "계좌가 없습니다."
↓
계좌가 있으면 → 잔액 확인
account.getBalance() >= money?
↓
잔액 부족 → "잔액이 부족합니다."
↓
잔액 충분 → 잔액 감소
account.setBalance(
account.getBalance() - money
)
메모리 변화
출금 전
┌─────────────────────────────────────┐
│ Account 객체 │
├─────────────────────────────────────┤
│ balance: 15000 ←─── 현재 잔액 │
└─────────────────────────────────────┘
출금 검증 및 실행
1. 잔액 확인: 15000 >= 3000? → ✅ 충분
2. 잔액 감소: 15000 - 3000 = 12000
3. balance 필드 업데이트
출금 후
┌─────────────────────────────────────┐
│ Account 객체 │
├─────────────────────────────────────┤
│ balance: 12000 ←─── 감소된 잔액 │
└─────────────────────────────────────┘
6️⃣ 계좌 이체 (transfer)
실행 흐름
사용자 입력
↓
출금 계좌번호: "123-456"
입금 계좌번호: "456"
이체금액: 5000
↓
findAccount("123-456") → account
findAccount("456") → sendAccount
↓
두 계좌 모두 존재하는가?
↓
없으면 → "계좌가 없습니다."
↓
있으면 → 출금 계좌 잔액 확인
account.getBalance() >= money?
↓
잔액 부족 → "잔액이 부족합니다."
↓
잔액 충분 → 이체 실행
account.setBalance(account.getBalance() - money)
sendAccount.setBalance(sendAccount.getBalance() + money)
메모리 변화
이체 전 상태
출금 계좌 (accountsArray[0]):
┌─────────────────────────────────────┐
│ Account 객체 │
├─────────────────────────────────────┤
│ ano: "123-456" │
│ owner: "홍길동" │
│ balance: 12000 ←─── 출금 계좌 │
└─────────────────────────────────────┘
입금 계좌 (accountsArray[1]):
┌─────────────────────────────────────┐
│ Account 객체 │
├─────────────────────────────────────┤
│ ano: "456" │
│ owner: "김철수" │
│ balance: 20000 ←─── 입금 계좌 │
└─────────────────────────────────────┘
이체 실행 과정
1단계: 출금 계좌 잔액 감소
account.setBalance(12000 - 5000)
account.setBalance(7000)
2단계: 입금 계좌 잔액 증가
sendAccount.setBalance(20000 + 5000)
sendAccount.setBalance(25000)
이체 후 상태
출금 계좌 (accountsArray[0]):
┌─────────────────────────────────────┐
│ Account 객체 │
├─────────────────────────────────────┤
│ ano: "123-456" │
│ owner: "홍길동" │
│ balance: 7000 ←─── 5000 감소 │
└─────────────────────────────────────┘
입금 계좌 (accountsArray[1]):
┌─────────────────────────────────────┐
│ Account 객체 │
├─────────────────────────────────────┤
│ ano: "456" │
│ owner: "김철수" │
│ balance: 25000 ←─── 5000 증가 │
└─────────────────────────────────────┘
총액: 7000 + 25000 = 32000 (변화 없음 ✅)
7️⃣ 계좌 목록 (accountList)
실행 흐름
accountList() 호출
↓
배열을 처음부터 끝까지 순회
(for문: j = 0 ~ 99)
↓
accountsArray[j] != null?
↓
null이면 → 다음 요소로
↓
null이 아니면 → 계좌 정보 출력
System.out.printf("%s %4s %4d\n",
accountsArray[j].getAno(),
accountsArray[j].getOwner(),
accountsArray[j].getBalance()
)
시각적 표현
accountsArray 상태:
┌─────┬─────┬─────┬─────┬─────┬─────┐
│ [0] │ [1] │ [2] │ [3] │ ... │[99] │
├─────┼─────┼─────┼─────┼─────┼─────┤
│ Acc1│ Acc2│ Acc3│null │ ... │null │
└──┬──┴──┬──┴──┬──┴─────┴─────┴─────┘
│ │ │
▼ ▼ ▼
출력 출력 출력
출력 결과:
123-456 홍길동 7000
456 김철수 25000
789 이영희 5000
8️⃣ 전체 데이터 흐름도
프로그램 실행 흐름
┌─────────────────────────────────────┐
│ 프로그램 시작 │
│ (main 메서드 실행) │
└───────────┬─────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 메뉴 표시 및 선택 │
│ 1.계좌생성 2.목록 3.예금 │
│ 4.출금 5.이체 6.종료 │
└───────────┬─────────────────────────┘
│
┌───────┴───────┐
│ │
▼ ▼
┌────────┐ ┌─────────┐
│ case 1 │ │ case 2 │
│ 계좌생성│ │ 계좌목록 │
└───┬────┘ └────┬────┘
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│Account 객체 │ │ 배열 순회 │
│생성 및 배열 │ │ 계좌 정보 │
│에 저장 │ │ 출력 │
└─────────────┘ └─────────────┘
│ │
▼ ▼
┌────────┐ ┌─────────┐
│ case 3 │ │ case 4 │
│ 예금 │ │ 출금 │
└───┬────┘ └────┬────┘
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│계좌 찾기 │ │계좌 찾기 │
│잔액 증가 │ │잔액 감소 │
└─────────────┘ └─────────────┘
│ │
└───────┬───────┘
│
▼
┌────────┐
│ case 5 │
│ 계좌이체│
└───┬────┘
│
▼
┌─────────────┐
│출금계좌 찾기 │
│입금계좌 찾기 │
│출금계좌 감소 │
│입금계좌 증가 │
└─────────────┘
9️⃣ 핵심 개념 시각화
배열과 객체의 관계
┌─────────────────────────────────────────┐
│ accountsArray (Stack) │
├─────────────────────────────────────────┤
│ [0] → Account 객체 (주소: 0x100) │
│ [1] → Account 객체 (주소: 0x200) │
│ [2] → Account 객체 (주소: 0x300) │
│ [3] → null │
│ ... │
│[99] → null │
└────┬────┬────┬──────────────────────────┘
│ │ │
│ │ │ 참조
▼ ▼ ▼
┌────┐ ┌────┐ ┌────┐
│Acc1│ │Acc2│ │Acc3│ (Heap)
│0x100│ │0x200│ │0x300│
└────┘ └────┘ └────┘
데이터 변경의 전파
예금 실행 시:
사용자 입력: 계좌번호 "123-456", 예금액 5000
↓
findAccount("123-456")
↓
accountsArray[0] 반환 (Account 객체 참조)
↓
account.setBalance(account.getBalance() + 5000)
↓
Account 객체의 balance 필드 변경
↓
accountsArray[0]이 참조하는 객체의 값이 변경됨
↓
같은 객체를 참조하는 모든 곳에서 변경된 값이 반영됨
🔟 메모리 상태 변화 타임라인
시나리오: 계좌 생성 → 예금 → 출금 → 이체
초기 상태
accountsArray: 모두 null
1. 계좌 생성 (홍길동, 10000원)
accountsArray[0] → Account { "123-456", "홍길동", 10000 }
2. 계좌 생성 (김철수, 20000원)
accountsArray[0] → Account { "123-456", "홍길동", 10000 }
accountsArray[1] → Account { "456", "김철수", 20000 }
3. 예금 (홍길동 계좌에 5000원)
accountsArray[0] → Account { "123-456", "홍길동", 15000 } ← 변경
accountsArray[1] → Account { "456", "김철수", 20000 }
4. 출금 (홍길동 계좌에서 3000원)
accountsArray[0] → Account { "123-456", "홍길동", 12000 } ← 변경
accountsArray[1] → Account { "456", "김철수", 20000 }
5. 이체 (홍길동 → 김철수, 5000원)
accountsArray[0] → Account { "123-456", "홍길동", 7000 } ← 변경
accountsArray[1] → Account { "456", "김철수", 25000 } ← 변경
💡 핵심 정리
데이터 저장 방식
- 배열: Account 객체들의 참조를 저장
- 객체: Heap 메모리에 실제 데이터 저장
- 참조: 배열의 각 요소는 객체의 주소를 가짐
데이터 접근 방식
- 직접 접근: accountsArray[0] → Account 객체
- 간접 접근: findAccount() → 배열 탐색 → Account 객체 반환
데이터 변경
- 배열 요소 변경: accountsArray[i] = newAccount (객체 교체)
- 객체 필드 변경: account.setBalance() (객체 내부 변경)
중요 포인트
- 배열은 참조를 저장: Account 객체가 아니라 객체의 주소(참조)를 저장
- 객체 공유: 같은 Account 객체를 참조하면 같은 데이터를 공유
- 참조 변경: accountsArray[i] = null 또는 다른 객체로 변경 가능
- 필드 변경: account.setBalance()로 객체의 내부 상태만 변경
📚 관련 개념
- 배열 (Array)
- 객체 참조 (Object Reference)
- 메모리 구조 (Stack vs Heap)
- 메서드 호출과 파라미터 전달
- 객체 상태 변경 (State Change)
'BackEnd > Java' 카테고리의 다른 글
| 배열-vs-ArrayList-비교 (0) | 2026.01.16 |
|---|---|
| 8_2 .학생 관리 시스템 실습 문제 (0) | 2026.01.15 |
| 5_1 . 이차원 배열 연습문제 (0) | 2026.01.06 |
| 15장. 미니 프로젝트 & 실습 (0) | 2026.01.04 |
| Java와 데이터베이스 연동 (0) | 2026.01.04 |