본문 바로가기
Java/Java

배열) 객체 배열, VO class 설계

by 박채니 2022. 3. 18.
SMALL

안녕하세요, 코린이의 코딩 학습기 채니 입니다.

 

개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.


객체 배열을 만들기 전, VO class를 생성해보겠습니다.

 

☞ VO class (Value Object class)

- 데이터를 담기 위한 클래스

- private 필드 (캡슐화)

- public getter/setter (캡슐화)

- 기본 생성자, 파라미터 생성자

- 모든 필드 정보를 확인할 수 있는 메소드

DTO (Data Transfer Object), DO (Domain Object), Entity, bean 이라고도 함

 

이름, 나이, 결혼여부 정보를 갖고 있는 VO class 생성

public class Person {
	//filed
	private String name;
	private int age;
	private boolean married;

	//contructor
	public Person() {}
	public Person(String name, int age, boolean married) {
		this.name = name;
		this.age = age;
		this.married = married;
	}
	
	//setter, getter
	public void setName(String name) {
		this.name = name;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public void setMarried(boolean married) {
		this.married = married;
	}
	public String getName() {
		return name;
	}
	public int getAge() {
		return age;
	}
	public boolean isMarried() {
		return married;
	}
	
	//정보 확인용 메소드
	public String printPersonInfo() {
		return "[" + name + ", " + age + ", " + married + "]";
	}
}

 

main 메소드에서 객체 배열 선언, 할당, 요소 대입, 출력

public class PersonMain {
	public static void main(String[] args) {
		PersonMain main = new PersonMain();
		main.test1();
	}
	
	public void test1() {
		//배열 선언
		Person[] persons;
		//할당
		persons = new Person[3];
		//번지수별 요소 대입
		persons[0] = new Person("홍길동", 44, false);
		persons[1] = new Person("신사임당", 67, true);
		persons[2] = new Person("이순신", 33, false);
		//출력
		for(int i = 0; i < persons.length; i++) {
			System.out.println(persons[i].printPersonInfo());
		}
	}
}

@콘솔출력값
[홍길동, 44, false]
[신사임당, 67, true]
[이순신, 33, false]

기존 배열 생성과 다를 건 없으며, 다만 타입이 Person클래스 타입인 배열 객체를 선언하였습니다.

 

메모리 구조를 확인해보겠습니다. (편의 상 static 메모리 생략)

Person[] persons
persons = new Person[3]
값 대입

마치 2차원 배열과 비슷한 메모리 구조를 갖고 있습니다.

다만 배열에서 가리키는 주소값에는 또 다른 배열이 아닌 '객체'가 있는 것이죠.

(0x123, 0x456, 0x789는 생성된 Person 객체)

 

다양한 객체 배열 생성 방법

//방법 1) 배열 객체 생성 후 값 대입
Person[] persons1 = new Person[3];
persons1[0] = new Person("홍길동", 44, false);
persons1[1] = new Person("신사임당", 67, true);
persons1[2] = new Person("이순신", 33, false);
		
//방법 2) 배열 객체 생성과 동시에 값 대입 (길이 지정 X)
Person[] persons2 = new Person[]	{
		new Person("홍길동", 44, false), 
		new Person("신사임당", 67, true), 
		new Person("이순신", 33, false)
	};
		
//방법 3) 대입할 값만 입력
Person[] persons3 = {
		new Person("홍길동", 44, false),
		new Person("신사임당", 67, true),
		new Person("이순신", 33, false)
	};

 

객체 배열 출력하기

//for문 활용
for(int i = 0; i < persons2.length; i++) {
	System.out.println(persons2[i].printPersonInfo());
}
System.out.println();
		
//for-each문 활용
for(Person p : persons3) {
	System.out.println(p.printPersonInfo());
}

@콘솔출력값
[홍길동, 44, false]
[신사임당, 67, true]
[이순신, 33, false]

[홍길동, 44, false]
[신사임당, 67, true]
[이순신, 33, false]

객체 배열 또한 for문과 for-each 문을 활용하여 출력 가능합니다.

 

사용자 입력 값을 받아 Person 객체 만들어보기 (방법 1)

public void test3() {
	Scanner sc = new Scanner(System.in);
		
	System.out.print("> 이름을 입력하세요 : ");
	String name = sc.next();
	System.out.print("> 나이를 입력하세요 : ");
	int age = sc.nextInt();
	System.out.print("> 결혼여부를 입력하세요(t/f) : ");
	boolean married = sc.next().charAt(0) == 't';
		
	Person persons = new Person(name, age, married);
	System.out.println(persons.printPersonInfo());
}

@콘솔출력값
> 이름을 입력하세요 : 박채니
> 나이를 입력하세요 : 24
> 결혼여부를 입력하세요(t/f) : f
[박채니, 24, false]

 

사용자 입력 값을 받아 Person 객체 만들어보기 (방법 2)

public void _test3() {
	Scanner sc = new Scanner(System.in);
		
	Person person = new Person();
	System.out.print("> 이름을 입력하세요 : ");
	person.setName(sc.next());
	System.out.print("> 나이를 입력하세요 : ");
	person.setAge(sc.nextInt());
	System.out.print("> 결혼여부를 입력하세요(t/f) : ");
	person.setMarried(sc.next().charAt(0) == 't');
		
	System.out.println(person.printPersonInfo());
}

@콘솔출력값
> 이름을 입력하세요 : 박채니
> 나이를 입력하세요 : 24
> 결혼여부를 입력하세요(t/f) : f
[박채니, 24, false]

 

사용자 입력 값을 받아 Person객체 3개 만들고, 출력

public void test4() {
	Scanner sc = new Scanner(System.in);
	Person[] persons = new Person[3];
		
	//입력부
	for(int i = 0; i < persons.length; i++) {
		System.out.print("> 이름을 입력하세요 : ");
		String name = sc.next();
		System.out.print("> 나이를 입력하세요 : ");
		int age = sc.nextInt();
		System.out.print("> 결혼여부를 입력하세요(t/f) : ");
		boolean married = sc.next().charAt(0) == 't';
			
		persons[i] = new Person(name, age, married);
	}
		
	//출력부
	for(Person p : persons) {
		System.out.println(p.printPersonInfo());
	}
}

@콘솔출력값
> 이름을 입력하세요 : 홍길동
> 나이를 입력하세요 : 29
> 결혼여부를 입력하세요(t/f) : f
> 이름을 입력하세요 : 신사임당
> 나이를 입력하세요 : 56
> 결혼여부를 입력하세요(t/f) : t
> 이름을 입력하세요 : 이순신
> 나이를 입력하세요 : 44
> 결혼여부를 입력하세요(t/f) : f
[홍길동, 29, false]
[신사임당, 56, true]
[이순신, 44, false]

객체가 한 개 이상이므로, 객체 배열을 사용하여 코드를 짜보았습니다.


Person 객체를 관리하는 클래스를 하나 더 만들어서

VO 클래스, 실행 main 클래스, 관리 Manager 클래스 총 3개로 Person 객체를 관리해보겠습니다.

 

관리 클래스에서는 배열의 길이를 넉넉하게 만들어서 사용자의 입력 값에 따라서 배열 출력을 해보겠습니다.

 

Person 클래스

public class Person {
	private String name;
	private int age;
	private boolean married;
	
	public Person() {}
	public Person(String name, int age, boolean married) {
		this.name = name;
		this.age = age;
		this.married = married;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public void setMarried(boolean married) {
		this.married = married;
	}
	public String getName() {
		return name;
	}
	public int getAge() {
		return age;
	}
	public boolean isMarried() {
		return married;
	}
	
	public String printPersonInfo() {
		return "[" + name + ", " + age + ", " + married + "]";
	}
}

 

PersonManager 클래스

PersonManager - Person객체를 관리
 - PersonManager가 Person객체를 가지고 있음
 - PersonManger has a Person -> has-a-포함관계
 - UML 클래스 다이어그램에서는 이른 연관관계(Asscociation)

public class PersonManager {
	Scanner sc = new Scanner(System.in);
	
	public static final int LEN = 10;
	private Person[] persons = new Person[LEN];
	private int index = 0;
	
	public void inputData() {
		for(int i = 0; i < persons.length; i++) {
			System.out.println("----- " + (i+1) + "번째 -----");
			System.out.print("> 이름을 입력하세요 : ");
			String name = sc.next();
			System.out.print("> 나이를 입력하세요 : ");
			int age = sc.nextInt();
			System.out.print("> 결혼 여부를 입력하세요(t/f) : ");
			boolean married = sc.next().charAt(0) == 't';
			//배열 추가
			pushToPerson(new Person(name, age, married));
			//추가 입력 여부
			System.out.println("----------------");
			System.out.print("> 더 입력하시겠습니까?(y/n) : ");
			char yn = sc.next().charAt(0);
			
			if(yn == 'n')
				break;
		}
	}
	
	public void pushToPerson(Person person) {
		persons[index++] = person;
	}
	
	public void printData() {
		for(int i = 0; i < index; i++) {
			System.out.println(persons[i].printPersonInfo());
		}
	}
}

배열의 길이를 넉넉하게 할당 후 사용자 입력 값만큼 값 대입을 하는 것이기 때문에,

index 변수 없이 for문을 이용하여 출력할 경우, 비어있는 배열 공간은 Null값이기 때문에 NullPointException이 발생합니다.

(Null 공간의 printPersonInfo 메소드를 실행하라고 하니 당연하겠죠?)

 

따라서 사용자의 입력 수만큼 배열 객체를 출력하기 위해서 사용자 입력 수 만큼을 카운트 해주는 index 변수를 따로 하나 선언하여 사용자가 입력할 때마다 index++ 해준다면 for문을 통하여 입력된 배열 수만큼만 출력 해줄 수 있겠습니다.

 

PersonMain 클래스

public class PersonMain {
	public static void main(String[] args) {
		PersonMain main = new PersonMain();
		main.test5();
	}

public void test5() {
		PersonManager pm = new PersonManager();
		pm.inputData();
		pm.printData();
	}
}

@콘솔출력값
----- 1번째 -----
> 이름을 입력하세요 : 홍길동
> 나이를 입력하세요 : 44
> 결혼 여부를 입력하세요(t/f) : f
----------------
> 더 입력하시겠습니까?(y/n) : y
----- 2번째 -----
> 이름을 입력하세요 : 신사임당
> 나이를 입력하세요 : 33
> 결혼 여부를 입력하세요(t/f) : t
----------------
> 더 입력하시겠습니까?(y/n) : y
----- 3번째 -----
> 이름을 입력하세요 : 이순신
> 나이를 입력하세요 : 77
> 결혼 여부를 입력하세요(t/f) : t
----------------
> 더 입력하시겠습니까?(y/n) : n
[홍길동, 44, false]
[신사임당, 33, true]
[이순신, 77, true]

 

UML 다이어그램에서는 이런 관계를 갖고 있습니다.

 

LIST