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

JAVA 12일차 (2023-06-08) 자바 기초 DAY10

by prometedor 2023. 6. 8.

클래스 관계 : UML 표기법 (Unified Modeling Language)

상속 (inheritance)

ㄴ A 의 기능에 +알파 기능을 추가한 B

ㄴ ex) 원래 있는 자동차 기능에 dump() 라는 기능을 추가하는 것

 

연관 (association)

ㄴ A 는 B 를 지속적으로 사용

ㄴ ex) 사람이 핸드폰을 사용함 (핸드폰 phone; 에서 phone 은 레퍼런스)

ㄴ 도구를 지속적으로 사용하는 관계가 있을 때 사용

ㄴ 이때 사용되는 도구는 dependency(의존객체) 라고 함

ㄴ 위 그림에서 Prompt 는 Scanner 클래스를 사용하여 문자열을 입력받는 기능을 사용함

ㄴ 여기서 Scanner 는 의존객체(dependency)임

 

집합(aggregation)

ㄴ A 는 B 를 포함함

ㄴ ex) 단순한 이용관계를 넘어서 키보드는 컴퓨터의 일종의 부품으로 이용됨

 

연관과 집합은 코드 상으로는 같지만 의미가 살짝 다름

=> 애매한 경우 연관으로 쓰자

 

합성 (composition)

ㄴ A 에 B가 포함됨

ㄴ ex) 컴퓨터는 그래픽카드와 RAM으로 이루어짐

ㄴ 여기서 A(컴퓨터) 는 container, B(그래픽카드 or RAM) 은 containee 임

강한 연관을 가지고 있음

 

의존

ㄴ 특정 메소드를 호출할 때만 사용함 (특정 기능을 수행할 때만 사용)

ㄴ 어떤 클래스를 사용할 경우 클래스가 의존하는 클래스를 같이 가져가줘야함 

 

 

 

 

클래스 문법 용도

ㄴ class 문법에는 메서드 분류와 데이터 타입/연산자(메서드)설계가 있음

 

 

ㄴ 데이터 메모리 설계도는 실체가 아님

ㄴ class Member{...} => Member 는 데이터를 저장할 메모리 설계도

ㄴ Member obj = new Member(); => Member 는 클래스명, obj 는 인스턴스의 주소를 담는 변수인 레퍼런스(reference)

ㄴ Member 라는 설계도에 따라 변수를 생성하는데 이때 생성되는 변수를 인스턴스(instance)라고 함(초기화는 모두 0으로 됨)

=> 이를 인간을 위한 고차원적인 표현으로 표현하면 0, null, \u0000 으로 표현됨

      ㄴ 주소를 저장하는 변수의 값이 0인 경우 : null 로 표기

      ㄴ 문자 변수(char)의 값이 0인 경우 '\u0000'으로 표기

 

 

인스턴스(instance)

ㄴ 설계도에 따라서 생성한 실제로 존재하는(준비된) 메모리

 

 

ㄴ new 명령을 이용하여 obj 라는 인스턴스를 만들고 obj.no 등을 사용하여 obj 라는 인스턴스의 주소인 200을 찾아가서 no 라는 인스턴스 필드에 100 을 할당함 (초기 인스턴스는 모두 0, null, \u0000 으로 초기화됨)

ㄴ 인스턴스를 가리키지 않은 상태에서 필드를 사용하려고 할 경우에는 예외(에러)가 발생함

 

 

레퍼런스, 인스턴스, 가비지 

ㄴ Member m1 = new Member(); 를 이용해 주소 200의 인스턴스를 생성

ㄴ 생성한 인스턴스를 가리키는 m1 에 주소 300의 새로운 인스턴스를 가리키도록 했을 때 주소 200의 인스턴스의 주소를 잃어버리게됨

=> 이는 Garbage 가 됨

 

 

레퍼런스 배열

members = new Memeber[100];

=> [100] 가 붙으면 레퍼런스를 100개 만들라는 말

 

인스턴스와 메모리

ㄴ Method Area 에 있는 MemberHandler.class 를 로딩하여 inputMember() 메서드를 호출함 => 로컬 변수 준비

ㄴ new Member() 를 통해 Heap 영역에 주소 200(예시)의 인스턴스를 생성함 => 인스턴스는 초기에 0, null, \u0000 으로 세팅됨

ㄴ 생성된 인스턴스의 주소 200을 JVM Stack 에 있는 InputMember() 프레임의 m이라는 로컬변수에 저장 (JVM Stack 에 메서드 코드가 있는 것이 아님)

 

 

스태틱 필드와 논스태틱 필드

ㄴ 스태틱 필드(static field)는 클래스 필드라고도 함

ㄴ 논스태틱 필드(non-static field)는 인스턴스 필드라고도 함

 

스태틱 필드

ㄴ 클래스를 로딩할 때 생성하며, 딱 한 번만 생성됨(클래스당 한 번만 로딩됨)

 

논스태틱 필드

ㄴ new 명령을 실행할 때 생성됨

 

 

 

실습

 

 

App.java

package bitcamp.myapp;

import bitcamp.myapp.handler.MemberHandler;
import bitcamp.util.Prompt;

public class App {
  
  public static void main(String[] args) {

    printTitle();

    printMenu();

    while (true) {
      String menuNo = Prompt.inputString("메인> ");
      if (menuNo.equals("6")) {
        break;
      } else if (menuNo.equals("menu")) {
        printMenu();
      } else if (menuNo.equals("1")) {
        MemberHandler.inputMember();
      } else if (menuNo.equals("2")) {
        MemberHandler.printMembers();
      } else if (menuNo.equals("3")) {
        MemberHandler.viewMember();
      } else if (menuNo.equals("4")) {
        MemberHandler.updateMember();
      } else if (menuNo.equals("5")) {
        MemberHandler.deleteMember();
      } else {
        System.out.println(menuNo);
      }
    }

    Prompt.close();
  }

  static void printMenu() {
    System.out.println("1. 회원등록");
    System.out.println("2. 회원목록");
    System.out.println("3. 회원조회");
    System.out.println("4. 회원변경");
    System.out.println("5. 회원삭제");
    System.out.println("6. 종료");
  }

  static void printTitle() {
    System.out.println("나의 목록 관리 시스템");
    System.out.println("----------------------------------");
  }
}

 

MemberHandler.java

package bitcamp.myapp.handler;

import bitcamp.util.Prompt;

public class MemberHandler {

  static final int MAX_SIZE = 100;
  static int[] no = new int[MAX_SIZE];
  static String[] name = new String[MAX_SIZE];
  static String[] email = new String[MAX_SIZE];
  static String[] password = new String[MAX_SIZE];
  static char[] gender = new char[MAX_SIZE];
  static int userId = 1;
  static int length = 0;

  static final char MALE = 'M';
  static final char FEMALE = 'W';

  public static void inputMember() {
    if (!available()) {
      System.out.println("더이상 입력할 수 없습니다!");
      return;
    }

    name[length] = Prompt.inputString("이름? ");
    email[length] = Prompt.inputString("이메일? ");
    password[length] = Prompt.inputString("암호? ");
    gender[length] = inputGender((char)0);

    no[length] = userId++;
    length++;
  }

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

    for (int i = 0; i < length; i++) {
      System.out.printf("%d, %s, %s, %s\n", 
        no[i], name[i], email[i], 
        toGenderString(gender[i]));
    }
  }

  public static void viewMember() {
    String memberNo = Prompt.inputString("번호? ");
    for (int i = 0; i < length; i++) {
      if (no[i] == Integer.parseInt(memberNo)) {
        System.out.printf("이름: %s\n", name[i]);
        System.out.printf("이메일: %s\n", email[i]);
        System.out.printf("성별: %s\n", toGenderString(gender[i]));
        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++) {
      if (no[i] == Integer.parseInt(memberNo)) {
        System.out.printf("이름(%s)? ", name[i]);
        name[i] = Prompt.inputString("");
        System.out.printf("이메일(%s)? ", email[i]);
        email[i] = Prompt.inputString("");
        System.out.printf("새암호? ");
        password[i] = Prompt.inputString("");
        gender[i] = inputGender(gender[i]);
        return;
      }
    }
    System.out.println("해당 번호의 회원이 없습니다!");
  }

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

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

  public static void deleteMember() {
    int memberNo = Prompt.inputInt("번호? ");

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

    for (int i = deletedIndex; i < length - 1; i++) {
      no[i] = no[i + 1];
      name[i] = name[i + 1];
      email[i] = email[i + 1];
      password[i] = password[i + 1];
      gender[i] = gender[i + 1];
    }

    no[length - 1] = 0;
    name[length - 1] = null;
    email[length - 1] = null;
    password[length - 1] = null;
    gender[length - 1] = (char) 0;

    length--;
  }

  private static int indexOf(int memberNo) {
    for (int i = 0; i < length; i++) {
      if (no[i] == memberNo) {
        return i;
      }
    }
    return -1;
  }

  private static boolean available() {
    return length < MAX_SIZE;
  }
}

 

Prompt.java

package bitcamp.util;

import java.util.Scanner;

public class Prompt {

  static Scanner scanner = new Scanner(System.in);

  public static String inputString(String title) {
    System.out.print(title);
    return scanner.nextLine();
  }

  public static int inputInt(String title) {
    return Integer.parseInt(inputString(title));
  }

  public static void close() {
    scanner.close();
  }

}