입력받은 다수의 회원정보를 List를 이용해 MemberInfo class의 멤버변수에 저장하고 출력하는 프로그램

 

1. 설명 및 목표

 키보드를 통해서 각 회원들의 정보를 입력 받는  클래스(MemberInput)를 작성한다. 이때 입력 받는 회원의 정보는 성명, 나이, 이메일, 주소를  입력 받는다. 그리고 키보드로 입력한 회원의 정보는 새로운 회원정보를 저장하는 클래스(MemberInfo)의 멤버변수에 저장을 시킨후 출력하는 프로그램을 작성하시오. 

  • 다수의 회원정보를 한번에 입력받아 List를 이용해 MemberInfo class에 저장하고 출력한다
  • Setter, Getter를 이용해 멤버변수를 초기화하고 리턴한다
  • List를 사용할 때, 강제형변환을 통한 다운캐스팅을 하거나 Generic을 이용한다
  • 나이를 입력할 때 숫자가 아닌 값이 입력되면 예외처리 메시지를 출력한다.

 

 

2. 이론

 컬렉션 프레임워크Collection Framework란 여러가지 자료형의 객체 값을 효과적으로 처리할 수 있는 표준화된 프로그래밍 방식을 제공하는 데이터 그룹의 집합을 의미하며, 다수의 데이터를 다루는 데에 필요한 다양한 클래스와 인터페이스를 제공한다. 값을 입력받는 메소드의 매개변수가 최상위 클래스인 Object이기 때문에 데이터의 형태에 구애받지 않고 저장할 수 있기 때문에 사용이 편리하고, 재사용이 가능하며, 배열과 달리 동적인 자료구조로서 크기를 자유롭게 조절할 수 있다는 장점을 가진다.
 컬렉션 중 하나인 List Interface는 데이터를 입력하면 index 번호 순으로 입, 출력되며 데이터를 중복으로 저장할 수 있다는 특징을 갖는다.
 제네릭Generic은 컬렉션의 클래스(인터페이스)명 뒤에 붙는 <E> 부분인데, 원래 모든 데이터형을 입력받을 수 있는 매개변수의 자료형 Object를 특정 데이터형으로지정해 그 데이터형만 저장할 수 있도록 제어하는 것이다. 제네릭을 사용할 경우, 값을 stack으로 옮길 때 다운캐스팅하는 과정을 생략할 수 있다는 장점이 있다.
 예외란 프로그램이 실행되는 동안 발생하는 예기치 못한 에러를 의마하고, 에러로 인한 비정상적인 종료를 막고 정상 실행 상태로 안전하게 돌아갈 수 있도록 처리하는 것이 예외처리이다.

 

3. 세부 내용

		boolean bb = true;
		String name, email, address;
		int age;
        
		while (true) {
			System.out.print("Name: ");
			name = sc.nextLine();
			System.out.print("Age: ");
			try {
				age = sc.nextInt();
				sc.nextLine();
			} catch (Exception e) {
				System.out.println("입력한 값이 숫자가 아닙니다.");
				bb = false;
				sc.close();
				break;
			}
			System.out.print("Email: ");
			email = sc.nextLine();
			System.out.print("Address: ");
			address = sc.nextLine();

각 변수에 정보값을 입력받는다. 변수 age에는 정수형 숫자만 입력할 수 있는데, 만약 입력받은 값이 숫자가 아니라면 예외처리되어 에러 메시지를 출력하게 된다. 이어 boolean bb이 false가 된 후 반복문이 끝나고 프로그램이 종료된다. 예외가 발생하지 않는다면 age에 값을 입력하고 email을 입력하는 창이 나오게 된다.

		ArrayList<MemberInfo> list = new ArrayList<MemberInfo>();
        
        	MemberInfo m = new MemberInfo();
			m.setName(name);
			m.setAge(age);
			m.setEmail(email);
			m.setAddress(address);
			list.add(m);

 MemberInfo의 객체를 새로 생성하고, Setter를 이용해 클래스의 필드값을 입력받은 값으로 초기화한다. 그리고 MemberInfo의 객체, 즉 초기화된 필드값이 저장되어있는 heap 영역의 주소를 담고 있는 stack 영역의 변수 m을 List로 저장한다. 이렇게 되면 나중에 출력할 때 객체 m을 이용해 값이 저장되어있는 heap 영역의 주소로 접근할 수 있게 된다. 제네릭을 이용해 List에 입력받는 데이터형을 MemberInfo 클래스로 한정시켰다.

		for (int i = 0; i < list.size(); i++) {
			if (bb != true)
				break;
			System.out.println();
			System.out.println((i + 1) + "번 학생 정보");
			MemberInfo mm = list.get(i);

			System.out.println("NAME:" + mm.getName());
			System.out.println("AGE:" + mm.getAge());
			System.out.println("EMAIL:" + mm.getEmail());
			System.out.println("ADDRESS:" + mm.getAddress());

		}

 입력받은 list의 값만큼 반복문을 돌려야 하기 때문에 list.size()로 반복 범위를 한정시키고, 입력받는 과정에서 예외가 발생해 예외처리가 된 경우 값이 출력되지 않아야 하므로 boolean값이 true가 아니면(=false) 반복문이 실행되지 않도록 조치한다.

 그리고 MemberInfo의 객체 mm에 list.get() 메소드를 이용해 정보가 저장되어있는 heap 영역의 주소값을 입력받는다. 그리고 mm을 이용해 memberInfo 클래스에 접근해 Getter로 heap 영역에 저장되어있는 필드값을 출력한다. 

 

4. 실행 결과

1. 값을 잘못 입력받았을 때

첫번째 정보는 올바르게 입력하고, 두번째 정보를 잘못 입력했을 때의 결과이다. 예외처리되어 메시지가 출력되었고, 이미 list에 입력받은 데이터가 존재하더라도 결과가 출력되지 않도록 조치했기 때문에 메시지 외의 정보는 출력되지 않은 채 프로그램이 정상 종료되었음을 확인할 수 있다.

 

2. 정상적으로 입력받았을 때

세 명의 정보를 입력받아 출력시킨 결과이다. 차례대로 잘 출력되었음을 확인할 수 있다.

5. 고찰

 과제 자체는 어제 나온 것인데, 차마 블로그에 정리해 올리기 쪽팔린 수준이라 오늘 풀이를 보고 이해해보고 내가 더 기능을 보강한 버전으로 리뷰를 올리게 되었다.

 어제 한 과제를 올릴 수 없었던 가장 큰 이유는, List에 대한 이해가 부족해 이것을 효율적으로 사용하지 못했기 때문이다. 좀 더 넓게 보자면 클래스에 대한 이해가 부족했다고도 할 수 있다. 데이터형에 관계 없이 저장할 수 있다는 것은, 보편적으로 사용되는 int, double, String 등의 데이터 뿐 아니라 내가 만든 class도 포함된다는 의미인데, 그걸 간과하고 입력받은 정보를 하나하나 list에 저장하고 출력시켰다. 출력은 잘 되었지만, 코드가 너무 더럽고 비효율적이라 올릴 수 없었다. 그걸 고찰한다고 해서 딱히 배울 점도 없었고. 차라리 과제 풀이를 보고 완벽하게 이해한 후 보강하는 게 나은 선택이라고 생각했다.

 일단, List에는 내가 만든 MemberInfo형 객체도 입력할 수 있다. 이 객체는 입력 반복문이 한 번 돌아갈 때마다 new 연산자를 통해 새로 하나씩 만들어지고, 만들어진 객체가 가리키는 heap 영역에는 입력받은 name, age, email, address 정보가 저장된다. stack에 만들어진 MemberInfo 객체는 그 영역에 대한 주소값을 저장하고 있고, list는 그 주소값을 입력받아 저장한다. 다시 반복문이 돌면 새로운 heap 영역이 만들어지고 새로 입력받은 정보가 저장되고, 그 정보가 저장되어있는 영역의 주소값이 다음 list로 저장되는 식이다. 즉, 출력 시에 list에서 주소를 다시 받아와 그 주소로 접근해 정보를 가져오면 되는 것이다.

 물론 출력할 때 단순히 list.get(i)의 형식으로 빼올 수는 없다. 특히 List 객체를 선언할 때 제네릭을 따로 지정해주지 않으면 더욱 그렇다. 이 경우, MemberInfo형 객체로 값을 돌려줘야 제대로 그 클래스에 접근할 수 있는데 list.get(i)으로 나오는 값의 데이터형은 Object이고 이것은 MemberInfo보다 더 상위 클래스이기 때문에 강제형변환으로 다운캐스팅을 해줘야 한다. MemberInfo mm=(MemberInfo)list.get(i)으로 말이다. 만약 이 과정을 넘기고 싶다면 위에 세부코드에 나와있듯 처음 list를 선언할 때 제네릭으로 데이터형을 MemberInfo로 한정해주면 된다. 그럼 list.get(i)으로 빼낸 값은 MemberInfo 형이기 때문에 형변환을 할 필요가 없다. 이렇게 값을 빼내고 그 주소를 이용해 MemberInfo 클래스에 접근, Getter를 이용해 필드값을 가져와 출력시킬 수 있다.

 예외처리는 그렇게 어렵지 않았다. 문제가 있었던 건 예외처리 메시지가 출력된 뒤에도 계속 뭔가가 출력되었던 부분인데 결과에 대한 출력은 boolean으로 제어할 수 있었고 입력부분도 break;를 입력해 반복문을 빠져나오는 것으로 해결했다.

 아무튼 이렇게 코드 리뷰를 하고 고찰에 코드의 흐름에 대해 설명을 붙일 수 있다는 건 내가 이 프로그램이 실행되는 과정을 제대로 이해하고 있다는 의미인 것이다. 전날에 이해를 완벽하게 끝낼 수 있었다면 좋았겠지만 그래도 아직까지는 어떻게든 따라갈 수 있는 상황이라 다행이라고 생각한다. 자바 책을 산 게 있으니 클래스, 객체에 대한 전반적인 복습을 다시 한번 해야겠다고 느낀다.

 

 

6. 전체 코드

 

 

'개인 > 풀이' 카테고리의 다른 글

220110 과제  (0) 2022.01.10
220107 과제  (0) 2022.01.07
220106 과제  (0) 2022.01.06
220104 과제  (0) 2022.01.04
220103 과제 보강  (0) 2022.01.03

+ Recent posts