개발자 준비과정/JAVA

[JAVA] 객체 배열...

하늘바람a 2024. 3. 7. 02:48

오늘 학원에서 풀었던 클래스챕터의 마지막 문제입니다.

저에게는 매우 어려운 문제였고, 강사님이 작성하신 코드를 리뷰해보아도 모르는게 있었습니다.

제가 이해하기 어려웠던 부분이 클래스를 배열로 바꾸었다는 점입니다.

 

강사님 코드를 리뷰해보자면,

Account[] accounts = new Account[100];

main클래스의 앞부분에 Account라는 클래스로 길이가 100인 배열 객체를 만들었습니다.

여기까지는 저도 만들었던 부분이라 이해가 갔는데, 갑자기

Account account = new Account(); 라는 새로운 객체를 만들더니

여기에 Account클래스의 필드값을 가져오고는 앞서 만들었던 배열 객체(?)에 대입을 해버립니다!!

이렇게 말이죠. accounts[numberOfAccount] = account;

Account[] accounts = new Account[100];

Account account = new Account();
account.setNumber(accountNumber);
account.setName(accountName);
account.setBalance(balance);

accounts[numberOfAccount] = account;
numberOfAccount++;

 

클래스가 배열이 될 수 있다는것이 의아해서

(배열엔 같은 타입만 담을 수 있는게 아닌가요?)

구글에 '클래스를 배열로' 라고 검색하니 자동검색어로 '자바 클래스를 배열로'가 뜹니다.

뭔가 규칙이 있나봅니다.

"객체 배열"이라는 키워드가 있어 찾아봤습니다.

 

객체는 메모리에서 single record 만 표현할 수 있다. 만약 multiple record를 표현시 객체배열을 사용한다. 다양한 타입(String,Integer, any class instance)의 데이타를 객체 배열을 통해 저장할 수 있다.

 

클래스를 배열로 선언하는 것이 가능하고,

다양한 타입의 데이터를 표현할 때 객체 배열을 통해 저장할 수 있다고 합니다.


 

Book 객체 3개를 배열 형태로 만들어 사용하기 위해서 먼저 아래와 같이 코드를 작성하게 되면,

레퍼런스 변수 bBook 객체에 대한 레퍼런스 변수 3개가 생성됩니다. 

 

   Book[ ] b = new Book[3];

 

이렇게 선언하게 되면 Book 객체를 담을 레퍼런스 변수 3개가 배열형태로 생성됩니다. 

주의할 아직 Book 객체가 만들어진것은 아니기 때문에, Book 객체를 사용하기 위해서는 아래와 같이 Book 객체를 생성해 주어야 합니다. 

 

   b[1] = new Book( );

   b[2] = new Book( );

   b[3] = new Book( );

 

 

위와 같이 객체 배열 생성 코드를 작성하게 되면 위의 그림과 같이 메모리상에 변수들이 할당됩니다. 

출처: https://kadosholy.tistory.com/90 [KADOSHoly:티스토리]


 

네... 되는것이었습니다...

 

ChatGPT, 뤼튼(chatGPT-4.0버전)을 사용하여 객체배열에 대하여 물어보았습니다.

 

  1. 객체 배열의 정의: 자바에서 배열은 동일한 타입의 여러 변수를 하나의 묶음으로 다루는 것을 의미합니다. 그 중에서 객체 배열은 객체의 참조값을 요소로 가지는 배열입니다. 즉, 객체 배열은 여러 객체를 묶어서 한 번에 관리하게 해주는 도구입니다.
  2. 객체 배열의 선언과 할당 방법: 객체 배열은 아래와 같이 선언하고 할당할 수 있습니다.
java
클래스타입[] 배열이름; // 선언
배열이름 = new 클래스타입[배열의 크기]; // 할당

예를 들어, Student 클래스의 객체를 저장하는 배열을 생성하려면 다음과 같이 합니다.

java
Student[] students; // 선언
students = new Student[10]; // 할당
  1. 사용 시의 주의점: 객체 배열을 생성했다고 해서 해당 배열에 자동으로 객체가 저장되는 것은 아닙니다. 배열에는 객체의 참조값이 저장되기 때문에, 각 배열의 요소마다 실제 객체를 생성해주는 과정이 필요합니다.
java
for(int i=0; i<students.length; i++) {
    students[i] = new Student(); // 각 요소마다 객체 생성
}
  1. 객체 배열 생성 시 메모리의 변화: 객체 배열을 생성하면 힙 메모리 영역에 배열의 크기만큼의 공간이 할당됩니다. 그리고 각 배열의 요소마다 객체를 생성하면, 각 객체마다 별도의 메모리 공간이 할당되고, 배열의 각 요소는 생성된 객체를 참조하게 됩니다.

즉, 예를 들어 Student[10] 배열이 있다면 메모리 안에는 Student 객체를 참조할 수 있는 참조변수 10개가 연속적으로 생성되며, 각각의 참조변수는 new Student()로 생성된 실제 객체를 가리키게 됩니다.

이러한 특성 때문에, 객체 배열을 사용할 때는 반드시 각 배열의 요소마다 객체를 생성해주는 것을 잊지 말아야 합니다.

객체 배열을 선언하기 전에 해당 클래스의 객체를 먼저 생성해야 합니다. 그렇지 않으면 객체 배열에는 아무런 내용이 없는 상태가 됩니다.
 

자바에서 배열은 동일한 타입의 데이터만 담을 수 있습니다. 다양한 타입의 필드값을 담으려면, 이를 포함하는 사용자 정의 클래스를 생성하고, 그 클래스의 객체 배열을 사용해야 합니다.

예를 들어, 아래와 같이 Person 클래스를 선언할 수 있습니다.

java
public class Person {
    String name;
    int age;
    double height;
}

이제 Person 객체를 담는 배열을 생성하면, 이 배열의 각 요소는 name, age, height라는 서로 다른 타입의 필드값을 가질 수 있습니다.

java
Person[] people = new Person[10];
for(int i=0; i<people.length; i++) {
    people[i] = new Person();
}

이렇게 하면 people[0].name, people[0].age, people[0].height와 같은 방식으로 다양한 타입의 필드값에 접근할 수 있습니다.


 

이제야 궁금증이 풀립니다. 

여러 개의 객체를 묶어서 한번에 관리하는 객체 배열이라는것이 존재하고, 클래스의 객체 생성 후에 배열에 객체를 저장합니다.

아직 완벽히 이해가 된 것은 아니지만 어느정도는 알게 되었습니다. 앞으로 조금 더 공부하여 제것으로 만들어야겠습니다.

마지막으로, 오늘 풀었던 문제의 정답 코드입니다.
package ch06.exercise.p20;

public class Account {
    private String number; // 계좌번호
    private String name; // 계좌주 이름
    private int balance; // 현재 잔액

    public void setNumber(String number) {
        this.number = number;
    }

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

    public void setBalance(int balance) {
        this.balance = balance;
    }

    public String getNumber() {
        return number;
    }

    public String getName() {
        return name;
    }

    public int getBalance() {
        return balance;
    }
}

 

 

package ch06.exercise.p20;

import java.util.Scanner;

public class BankApplication {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Account[] accounts = new Account[100];
        int numberOfAccount = 0;

        boolean run = true;
        while (run) {
            System.out.println("""
                    --------------------------------------
                    1.계좌생성|2.계좌목록|3.예금|4.출금|5.종료 
                    --------------------------------------""");
            System.out.print("선택>");
            String menu = scanner.nextLine();

            switch (menu) {
                case "1" -> {
                    System.out.println("""
                            -------
                            계좌생성
                            ------- """);
                    System.out.print("계좌번호: ");
                    String accountNumber = scanner.nextLine();
                    System.out.print("계좌주: ");
                    String accountName = scanner.nextLine();
                    System.out.print("초기입금액: ");
                    int balance = Integer.parseInt(scanner.nextLine());

                    Account account = new Account();
                    account.setNumber(accountNumber);
                    account.setName(accountName);
                    account.setBalance(balance);

                    accounts[numberOfAccount] = account;
                    numberOfAccount++;

                    System.out.println("결과: 계좌가 생성되었습니다.");
                }
                case "2" -> {
                    System.out.println("""
                            -------
                            계좌목록
                            ------- """);
                    for (int i = 0; i < numberOfAccount; i++) {
                        System.out.println(STR."\{accounts[i].getNumber()}     \{accounts[i].getName()}     \{accounts[i].getBalance()}");
                    }
                }
                case "3" -> {
                    System.out.println("""
                            -------
                            예금
                            ------- """);
                    System.out.print("계좌번호: ");
                    String accountNumber = scanner.nextLine();
                    System.out.print("예금액: ");
                    int deposit = Integer.parseInt(scanner.nextLine());

                    // 계좌번호가 accountNumber인 계좌 찾기
                    for (int i = 0; i < numberOfAccount; i++) {
                        if (accounts[i].getNumber().equals(accountNumber)) {
                            int balance = accounts[i].getBalance();
                            accounts[i].setBalance(balance + deposit);
                        }
                    }
                }
                case "4" -> {
                    System.out.println("""
                            -------
                            출금
                            ------- """);
                    System.out.print("계좌번호: ");
                    String accountNumber = scanner.nextLine();
                    System.out.print("출금액: ");
                    int withdrawal = Integer.parseInt(scanner.nextLine());

                    // 계좌번호가 accountNumber인 계좌 찾기
                    for (int i = 0; i < numberOfAccount; i++) {
                        if (accounts[i].getNumber().equals(accountNumber)) {
                            int balance = accounts[i].getBalance();
                            accounts[i].setBalance(balance - withdrawal);
                        }
                    }

                    System.out.println("결과: 출금이 성공되었습니다.");
                }
                case "5" -> run = false;
            }
        }

        System.out.println("프로그램 종료");
        scanner.close();
    }
}