본문 바로가기
네이버클라우드/JAVA 웹 프로그래밍

JAVA 14일차 (2023-06-12) 자바 기초 DAY12_getter/setter 적용

by prometedor 2023. 6. 12.

getter/setter 적용

ㄴ 워크스페이스에서 Member.java 를 열고 우클릭 > Source > Generate Getters and Setters... 선택

 

ㄴ [select All] > Access modifier - public 설정 확인 > [Generate] 선택

 

ㄴ 간편하게 getter/setter 생성 가능

 

Project 컴파일

ㄴ Project > Clean... 선택

ㄴ [Clean] 선택

 

ㄴ Build Automatically 설정 되어있는지 꼭 확인

 

ㄴ 실행 시 [재생 아이콘] 선택

=> 이클립스는 저장 시 컴파일 실행됨

 

 

컴파일러는 자동으로 빈 생성자를 만듦

ㄴ Member.java 에서 생성자 없었을 때 Member.class 파일 확인 시 컴파일러가 자동으로 빈 생성자를 만드는 것을 확인

 

임의의 생성자 추가 시

 

임의의 생성자 추가 시 컴파일러는 자동으로 빈 생성자를 만들지 않음

ㄴ Member.java 에서 생성자 추가한 후 Member.class 파일 확인 시 컴파일러가 자동으로 빈 생성자를 만들지 않고 추가한 생성자만 호출되는 것을 확인

 

getter/setter 적용

=> 아래와 같이 getter/setter 적용하여 수정

Member m = new Member();
m.setName(Prompt.inputString("이름? "));
m.setEmail(Prompt.inputString("이메일? "));
m.setPassword(Prompt.inputString("암호? "));
m.setGender(inputGender((char) 0));
for (int i = 0; i < length; i++) {
      Member m = members[i];
      System.out.printf("%d, %s, %s, %s\n", m.getNo(), m.getName(), m.getEmail(),
          toGenderString(m.getGender()));
}
if (m.getNo() == Integer.parseInt(memberNo)) {
    // i 번째 항목에 저장된 회원 정보 출력
    System.out.printf("이름: %s\n", m.getName());
    System.out.printf("이메일: %s\n", m.getEmail());
    System.out.printf("성별: %s\n", toGenderString(m.getGender()));
    return;
}
if (m.getNo() == Integer.parseInt(memberNo)) {
    // i 번째 항목에 저장된 회원 정보 출력
    m.setName(Prompt.inputString("이름(" + m.getName() + ")? "));
    m.setEmail(Prompt.inputString("이메일(" + m.getEmail() + ")?\n"));
    m.setPassword(Prompt.inputString("새암호? "));
    m.setGender(inputGender(m.getGender()));
    return;
}
if (m.getNo() == memberNo) {
    return i;
}

 

리팩토링

모든 인스턴스가 공유하는 값은 스태틱 필드에 보관

ㄴ static int userId = 1; 코드를 Member.java 로 이동시킴

ㄴ static int userId = 1; 코드를 Member.java 로 이동시킨 후 private 붙여줌

=> 모든 인스턴스가 공유하는 값은 스태틱 필드에 보관

 

생성자 추가

ㄴ 생성자에 no 를 userId++ 하는 기능을 추가해줌

ㄴ m.setNo(itemId++); 코드는 Member.java 의 생성자에서 기능을 해주기 때문에 제거

 

GRASP 패턴 : Information Expert

ㄴ 상수는 스태틱 필드로 정의

ㄴ 정보를 다룰 때는 그 정보를 갖고 있는 클래스에 그 기능을 둠

ㄴ 필드도 마찬가지

ㄴ 해당 코드 Member.java 로 이동

ㄴ Member.java 로 이동시킨 코드에 모두 public 을 붙여줌

 

ㄴ MemberHandler.java 에서 해당 필드 값 앞에 클래스 이름을 적어줌

ex) return MALE => return Member.MALE;

 

수정 결과

Member.java

package bitcamp.myapp.vo;

public class Member {

  // 모든 인스턴스가 공유하는 값은 스태틱 필드에 보관한다.
  private static int userId = 1; // 회원 번호

  // 상수는 스태틱 필드로 정의한다.
  // 정보를 다룰 때는 그 정보를 갖고 있는 클래스에 그 기능을 둔다.
  // 필드도 마찬가지이다.
  // => GRASP 패턴: Information Expert
  public static final char MALE = 'M'; // 상수로 정의
  public static final char FEMALE = 'W';

  // 인스턴스 필드는 각각 개별적으로 유지해야 하는 값을 저장할 때 사용한다.
  // new 명령을 통해 변수를 Heap 영역에 생성한다.
  private int no; // no를 저장할 칸 마련
  private String name; // name을 저장할 변수
  private String email;
  private String password;
  private char gender;

  // 생성자는 인스턴스를 생성한 후 필드를 초기화시키는 일을 한다.
  // 인스턴스를 사용할 떄 문제가 없도록 유효한 값으로 초기화시킨다.
  // 기본 생성자(default constructor)는 개발자가 생성자를 정의하지 않을 때
  // 컴파일러가 추가해주는 생성자다.
  // 물론 개발자가 직접 추가할 수 있다.
  public Member() {
    this.no = userId++;
  }

  // getter/setter는 인스턴스 필드의 값을 설정하고 꺼내는 메서드다.
  // 보통 외부에서 직접 필드에 접근하는 것을 막았을 때 사용한다.
  public int getNo() {
    return no;
  }

  public void setNo(int no) {
    this.no = no;
  }

  public String getName() {
    return name;
  }

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

  public String getEmail() {
    return email;
  }

  public void setEmail(String email) {
    this.email = email;
  }

  public String getPassword() {
    return password;
  }

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

  public char getGender() {
    return gender;
  }

  public void setGender(char gender) {
    this.gender = gender;
  }

}

 

MemberHandler.java

package bitcamp.myapp.handler;

import bitcamp.myapp.vo.Member;
import bitcamp.util.Prompt;

public class MemberHandler {

  static final int MAX_SIZE = 100; // 대문자로 해주는 이유 : 강조하기 위함
  static Member[] members = new Member[MAX_SIZE];
  // static int[] no = new int[MAX_SIZE];
  // static String[] name = new String[MAX_SIZE]; // java에서 []를 앞에 해주는 이유 :
  // primitive type 변수가 아닌 레퍼런스(주소를 담는)라는 것을 알려줌
  // static String[] email = new String[MAX_SIZE];
  // static String[] password = new String[MAX_SIZE];
  // static char[] gender = new char[MAX_SIZE];

  static int length = 0; // 한 사람 입력 할 떄마다 증가시킬 값


  public static void inputMember() {
    if (!available()) {
      System.out.println("더이상 입력할 수 없습니다!");
      return; // 함수 종료시키고 싶을 때
    }

    Member m = new Member();
    m.setName(Prompt.inputString("이름? "));
    m.setEmail(Prompt.inputString("이메일? "));
    m.setPassword(Prompt.inputString("암호? "));
    m.setGender(inputGender((char) 0));

    // 위에서 만든 Member 인스턴스의 주소를 잃어버리지 않게 레퍼런스 배열에 담는다.
    members[length++] = m;

  }

  public static void printMemebers() {
    System.out.println("--------------------------------------------");
    System.out.println("번호, 이름, 이메일, 성별");
    System.out.println("--------------------------------------------");

    for (int i = 0; i < length; i++) {
      Member m = members[i];
      System.out.printf("%d, %s, %s, %s\n", m.getNo(), m.getName(), m.getEmail(),
          toGenderString(m.getGender()));
    }
  }

  public static void viewMember() {
    String memberNo = Prompt.inputString("번호? ");
    // 입력 받은 번호를 가지고 배열에서 해당 회원을 찾아야 한다.
    for (int i = 0; i < length; i++) {
      Member m = members[i];
      if (m.getNo() == Integer.parseInt(memberNo)) {
        // i 번째 항목에 저장된 회원 정보 출력
        System.out.printf("이름: %s\n", m.getName());
        System.out.printf("이메일: %s\n", m.getEmail());
        System.out.printf("성별: %s\n", toGenderString(m.getGender()));
        return;
      }
    }
    System.out.println("해당 번호의 회원이 없습니다!");
  }

  public static String toGenderString(char gender) {
    return gender == 'M' ? "남성" : "여성";
  }

  public static void updateMember() {
    String memberNo = Prompt.inputString("번호? ");
    // 입력 받은 번호를 가지고 배열에서 해당 회원을 찾아야 한다.
    for (int i = 0; i < length; i++) {
      Member m = members[i];

      if (m.getNo() == Integer.parseInt(memberNo)) {
        // i 번째 항목에 저장된 회원 정보 출력
        m.setName(Prompt.inputString("이름(" + m.getName() + ")? "));
        m.setEmail(Prompt.inputString("이메일(" + m.getEmail() + ")?\n"));
        m.setPassword(Prompt.inputString("새암호? "));
        m.setGender(inputGender(m.getGender()));
        return;
      }
    }
    System.out.println("해당 번호의 회원이 없습니다!");
  }

  private static char inputGender(char gender) {
    String label;
    if (gender == 0) {
      label = "성별?\n";
    } else {
      // label = "성별(" + toGenderString(gender) + ")?\n";
      label = String.format("성별(%s)?\n", toGenderString(gender)); // 문자열 리턴
    }
    while (true) {
      String menuNo = Prompt.inputString(label + " 1. 남자\n" + " 2. 여자\n" + "> ");

      switch (menuNo) {
        case "1":
          return Member.MALE;
        case "2":
          return Member.FEMALE;
        default:
          System.out.println("무효한 번호입니다.");
      }
    }
  }

  public static void deleteMember() {
    // 삭제하려는 회원의 정보가 들어 있는 인덱스를 알아낸다.

    int memberNo = Integer.parseInt(Prompt.inputString("번호? "));

    int deletedIndex = indexOf(memberNo);

    // // 입력 받은 번호를 가지고 배열에서 해당 회원을 찾아야 한다.
    // for (int i = 0; i < length; i++) {
    // if (no[i] == Integer.parseInt(memberNo)) {
    // deletedIndex = i;
    // break;
    // }
    // }

    if (deletedIndex == -1) {
      System.out.println("해당 번호의 회원이 없습니다!");
      return;
    }

    // if (deletedIndex < (length - 1)) {
    // // 만약 삭제하려는 항목이 마지막 인덱스의 항목이라면 마지막 인덱스의 값만 0으로 초기화시킨다.
    // no[deletedIndex] = 0;
    // name[deletedIndex] = null;
    // email[deletedIndex] = null;
    // password[deletedIndex] = null;
    // gender[deletedIndex] = (char) 0;
    // } else {
    // 그 밖에는 해당 인덱스부터 반복하면서 앞 인덱스의 값을 당겨온다.
    for (int i = deletedIndex; i < length - 1; i++) {
      members[i] = members[i + 1];
    }

    members[--length] = null;
    // }
    // length를 하나 줄인다.

    System.out.println("삭제했습니다.");
    return;
  }

  private static int indexOf(int memberNo) {
    for (int i = 0; i < length; i++) {
      Member m = members[i];
      if (m.getNo() == memberNo) {
        return i;
      }
    }
    return -1;
  }

  private static boolean available() { // 같은 클래스 안에서만 사용 가능
    return length < MAX_SIZE;
  }
}