2022.07.15 금요일/자바 정리/클래스 사용법2

Jimin·2022년 7월 15일
0

비트캠프

목록 보기
2/60

008. 클래스 사용법2

  • 클래스 문법을 사용하여 데이터 타입 설계하기
  • 클래스와 인스턴스, 레퍼런스의 관계
  • 레퍼런스 배열과 인스턴스를 다루는 방법
  • 인스턴스의 변수에 값을 넣고 꺼내는 방법
  • 배열에서 값을 삭제하는 방법

1단계 - 게시글 데이터를 저장할 메모리를 설계한다.

=> com.bitcamp.boar.Board class 생성

  • 클래스 문법
  1. 메서드를 분류
class A{
	m1(){-}
    m2(){-}
    m3(){-}
    ...
    }
  1. 데이터 타입 정의
  • 새 데이터 타입 정의
    int no;
    String title;
    String content;
    no = 1;
    title = "제목입니다.";
    content = "okok"
    => 클래스에서 하는 일반적인 변수 선언에서 새 클래스에 필요한 변수 선언으로 변경
    class Board{
    	int no;
       String title;
       String content;
       }
  • Board b = new Board();

    - Board 설계도에 따라 변수를 준비한다.
    - primitive type(byte, short, int, long, float, double, boolean, char)의 변수를 제외한 나머지 모든 변수는 인스턴스(new 명령어로 준비하는 변수)의 주소를 담는 레퍼런스 변수이다.
    - primitive type의 배열도 reference 변수이다.

레퍼런스, 인스턴스, 값 할당

Board b1 = new Board()
b.no = 100;
b.title = "aaa";
b.content = "ok";

Board b2;
b2 = b1;

b2.no =333;
System.out.println(b1.no) ==> 333

  • 실제 코드
public class Board {
  // 인스턴스를 생성할 때 준비되는 메모리를 선언
  int no;
  String title;
  String content;
  String writer;
  String password;
  int viewCount;
  long createdDate;
}

2단계 - 게시글 처리에 배열을 사용한다.

  • App 클래스에 모든 변수를 선언해서 사용하는 것보다 Board 클래스에 필요한 변수를 선택해서 App에서 객체, 레퍼런스 변수를 만들어서 Board 클래스의 변수를 이용한다.

com.bitcamp.board.BoardHandler 클래스 변경

- 기존의 게시글 관련 변수 배열을 저장할 배열을 Board reference 배열로 대체한다.

  • Board class 레퍼런스 배열 선언
  static int boardCount = 0; // 저장된 게시글의 개수
  static final int SIZE = 3;
  static Board[] boards = new Board[SIZE];

게시글 입력, 목록, 상세보기 메서드를 변경한다.

  • processInput() method
     static void processInput() {
    //------------------- menu 3 --------------------------
    System.out.println("[게시글 등록]");

    if (SIZE == boardCount) {
      System.out.println(
          "더 이상 게시글을 등록할 수 없습니다. 
          최대 게시물 등록 수를 초과했습니다!"
          );
      return;
    }

    Board board = new Board();
    boards[boardCount] = board;
    board.title = Prompt.inputString("제목? ");
    board.content = Prompt.inputString("내용? ");
    board.writer= Prompt.inputString("작성자? ");
    board.password = Prompt.inputString("암호? ");

    board.no = boardCount == 0 ? 1 : boards[boardCount - 1].no + 1;

    boards[boardCount].createdDate = System.currentTimeMillis();

    boards[boardCount].viewCount = 0;

    // 새로만든 인스턴스 주소를 레퍼런스 배열에 저장한다.

    boardCount++;
  }

가독성을 위하여 레퍼런스 변수 board를 선언해 주고 그 주소를 현재 게시글의 레퍼런스 배열에 연결시켜준다.
레퍼런스 배열로 구성했으므로 인덱스가 아닌, 이전 레퍼런스 배열의 no값을 가져온다.

  • processList() method
static void processList() {
    //------------------- menu 1 --------------------------
    java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat(
        "yyyy-MM-dd hh:mm:ss"
        );

    System.out.println("[게시글 목록]");

    System.out.println("번호\t제목\t\t조회수\t작성자\t등록일");
    for (int i = 0; i < boardCount; i++) {
      Board board = boards[i];
      java.util.Date date = new java.util.Date(board.createdDate);
      String dateStr = formatter.format(date);
      System.out.printf(
          "%d\t%s\t\t%d\t%s\t%s\n",
          board.no,
          board.title,
          board.viewCount,
          board.writer,
          dateStr
          );
    }
  }

가독성을 위하여 Board 객체 board를 만들어서 for문을 통해 boards[i]의 주소를 각각 넣어주고, 객체 board를 이용해 출력해준다.

  • processDetail() method
static void processDetail() {
    //------------------- menu 2 --------------------------
    Board board = null;
    System.out.println("[게시판 상세보기]");
    int noBoard = Prompt.inputInt("몇 번 게시물을 조회하시겠습까? ");
    for (int i = 0; i < boardCount; i++) {
      if (boards[i].no == noBoard) {
        board = boards[i];
        break;
      }
    }

    if (board == null) {
      System.out.println("해당 번호의 게시물은 존재하지 않습니다!");
      return; // 메소드를 호출할 곳으로 돌아가고 싶을 때. 
    }

    board.viewCount++;

    System.out.printf("번호: %d\n", board.no);
    System.out.printf("제목: %s\n", board.title);
    System.out.printf("내용: %s\n", board.content);
    System.out.printf("조회수: %d\n", board.viewCount);
    System.out.printf("작성자: %s\n", board.writer);

    java.util.Date date = new java.util.Date(board.createdDate);
    System.out.printf("등록일: %1$tY-%1$tm-%1$td/%1$tA %1$tH:%1$tM\n", date);
  }

메소드 안에 board 객체를 null로 선언해주고, 조회하려는 입력 번호와 일치하는 게시글의 번호가 있을 경우 null이었던 board 객체에 일치하는 게시글의 번호가 들어있는 레퍼런스 배열 원소를 넣어준다.
만약 board가 여전히 null이라면 일치하는 boardCount가 존재하지 않았던 것이다.

3단계 - 게시글 삭제 메뉴를 추가한다.

com.bitcamp.board.App class 변경

  • 그냥 switch 메뉴 선택지 4번 하나 추가해준다.

com.bitcamp.board.BoardHandler class 변경

 static void processDelete() {
    System.out.println("[게시글 삭제]");
    int deleteNo = Prompt.inputInt("삭제하시고 싶은 게시글의 번호를 입력해 주시길 바랍니다.");

    int deleteIdx = -1;
    for(int i=0;i<boardCount;i++) {
      if(deleteNo == boards[i].no) {
        System.out.println("삭제되었습니다.");
        deleteIdx=i;
        delete(deleteIdx);
        break;
      }
    }
    if(deleteIdx == -1) {
      System.out.println("잘못된 번호를 입력하셨습니다. 해당 게시글 번호는 존재하지 않습니다.\n올바른 번호를 입력해 주십시오.");
      return;
    }
  }

  static void delete(int deleteIdx) {
    for(int i=deleteIdx+1;i<boardCount;i++) {
      boards[i-1] = boards[i]; //마지막 인덱스 고려하기
    }
    boardCount--;
    boards[boardCount]=null; // 없앤 값은 null 처리하기

    //boards[--boardCount]=null도 가능!
  }
  • processDelete(): 인덱스를 이용해서 원소들을 이동시켜야 하기 때문에 삭제하고 싶은 게시글 번호를 가지고 있는 배열의 원소 인덱스를 찾아서 delete라는 메소드를 하나 만들어 그곳으로 넘겨 주었다.
    그리고 항상 for문을 돌려 체크할 때, boardCount로 체크해야함을 명심해야했다.
  • delete(int deleteNo): 인덱스가 중요했는데,마지막 인덱스가 범위(SIZE)를 초과하면 안되므로 초기 인덱스 i는 삭제할 인덱스 +1로 해주고 업데이트 할 배열 속 원소 값은 i-1로 해주고 i의 원소로 업데이트를 해준다.
    앞으로도 배열 업데이트 등, 계속 쓰일 코드인 듯 하니 기억하는 것이 좋을 것 같다.
    for(int i=deleteIdx+1;i<boardCount;i++) {
        boards[i-1] = boards[i]; //마지막 인덱스 고려하기
      }
    또한 중요한 점은, 이제 쓸모 없어진 삭제된 게시글 배열 인덱스 레퍼런스 변수를 null처리 해주는 것이다.
    게시글의 총 개수는 배열의 실제 인덱스보다 1크므로 -1을 해주고 null처리를 해주면 된다.

4단계 - 게시글 변경 메뉴를 추가한다.

com.bitcamp.board.App 클래스 변경

  • 삭제 메뉴를 만들 때와 마찬가지로 그냥 출력 값들을 수정해주면 된다.

com.bitcamp.board.BoardHandler 클래스 변경

  • 변경할 게시글 질문 -> 변경할 내용 입력(이전 내용 보여줘야함) -> 변경할 것인지 한 번 더 질문(y or n로 답변)
 public static void processUpdate() {
    System.out.println("[게시글 수정]");
    int editNo = Prompt.inputInt("변경할 게시글 번호?");
    int editIdx = -1;
    for(int i=0;i<boardCount;i++) {
      if(editNo == boards[i].no) {
        editIdx=i;
        edit(editIdx);
        break;
      }
    }
    if(editIdx == -1) {
      System.out.println("잘못된 번호를 입력하셨습니다. 해당 게시글 번호는 존재하지 않습니다.\n올바른 번호를 입력해 주십시오.");
      return;
    }
  }

  static void edit(int editIdx) {
    Board board = boards[editIdx];
    String title= Prompt.inputString("제목? " + "("+board.title+")");
    String content= Prompt.inputString("내용? "+ "("+board.content+")");
    String writer = Prompt.inputString("작성자? "+ "("+board.writer+")");
    String password = Prompt.inputString("암호? "+ "("+board.password+")");
    if(isEdit()) {
      board.title =title;
      board.content =content;
      board.writer=writer;
      board.password = password;
      System.out.println("성공적으로 변경되었습니다!");
    }else {
      System.out.println("변경을 취소하였습니다.");
      return;
    }
  }

  static boolean isEdit() {
    char ans = Prompt.inputChar("변경하시겠습니까?(y/n) ");
    return ans =='y'? true:false;
  }
  • processUpdate(): 삭제할 떄와 마찬가지로 삭제하고 싶은 게시글 번호를 가지고 있는 배열의 인덱스를 찾아준다.
  • edit(int editIdx): 찾은 인덱스를 가지고 기존에 존재하던 Prompt 클래스의 inpuString 메소드를 이용해서 새 변수를 선언하고 값을 받아준다. 그리고 isEdit() 메소드를 통해 진짜로 삭제할 것인지 확인하고 true 값이 리턴되면 현재 board 레퍼런스 변수의 원소들을 수정해준다.
  • isEdit(): Prompt 클래스에서 char값을 받는 메소드를 새로 만들어서 char 값을 받고, y가 들어온 경우 true, 아닌 경우 false를 리턴한다.

이클립스

  • 이클립스에서 ctrl+space 하면 미리 코드가 생성됨
  • 이클립스는 저장키를 누를 때 마다 javac가 실행이 되어 자동으로 컴파일이 된다.
  • 이클립스에서 project > clean 누르면 전체가 컴파일 된다.

잡다 필기

String

  • String 배열은 reference 배열이라서
String[] names = new String[29];
names[0] = String("jimin");
  • 위와 같이 나타내어야 하지만, String은 이미 따옴표로 나타내는 것 만으로 레퍼런스가 만들어져서 인스턴스안에 값이 들어가게 되므로 그냥 밑에와 같이 나타낸다.
String[] names = {"jimin", "jiyeon", ...};

import

  • import는 메소드를 가져오는 용도가 아니라 메소드가 어느 패키지에 있는지 알려주는 용도이다.
  • random 메소드는 0~1사이의 값이다.
profile
https://github.com/Dingadung

0개의 댓글