2018-11-29 수업 내용 정리

자바 영역

  • 메서드 에리어(Methed Aera)

    • 명령어가 저장

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      x {
      int i = 100;
      int[] arr;
      arr = new int[10];
      arr[i] = 300;
      }
      main {
      x();
      x();
      }
    • 그런데 만약 문자열이라면?

      1
      2
      3
      4
      String s = new String("Hello World!");
      // 이것은 힙으로 간다.
      String st = "Hello!";
      // 이것은 상수 풀로 간다.

예전에는 String이 char의 배열이었는데, 자바 버전이 올라가며 utf-8로 저장하기 위해 byte의 배열로 변경됨

또한 메서드 호출이 종료되면, 메서드 안의 인스턴스 변수가 소멸된다.

  • 스택(Stack)

    • 메서드 하나 당 하나의 프레임이 형성되고 관련 데이터들의 주소(첫 시작점)가 저장됨

    • 메서드 호출이 종료되면 소멸됨

      1
      2
      3
      4
      main 프레임 생성
      x의 프레임 생성 후 소멸
      x의 프레임 생성 후 소멸
      프로그램이 종료되면 main 프레임 소멸
  • 힙(Heap)

    • 객체의 데이터가 저장됨

    • 유일하게 garbage가 있는 곳

    • garbage collector는

      • 특정 객체가 주소를 잃었고
      • 현재 메모리가 부족하다고 생각되면
      • cpu가 한가할 때 실행됨

      (이게 가능한 이유는 참조-레퍼런스- 카운트를 기억하기 때문)

      1
      x 내 데이터들의 메모리가 저장되었다가 garbage collector가 삭제
    • 자바는 객체 배열을 만들 수 없다

      • 그래서 String 배열을 만든다고 했을 때 힙에는

        1
        2
        [   ] [   ] [   ]....
        // 각각의 칸에 상수 풀 주소가 저장된다
    • 만약 String을 정식 객체 생성을 해서 만들었다고 했을 때

      1
      s의 Hello World가 저장되어 있다
  • 상수 풀(constant pool)

    • 문자열이 저장되었다면 상수 풀(constant pool)에 저장된다! 힙이 아님

    • 이미 같은 문자열이 있다면 새로 메모리를 만들지 않는다

    • 즉 참조 주소가 다르다!

    • 보통 String을

      1
      String st = "~";

      로 만들기 때문에(단축 객체 생성) 참조 주소가 같은 것

    • 그래서 equals를 써야 함

헷갈리니까 이전에 했던 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
> main {
> String s1 = new String("hello");
> String s2 = new String("hello");
> String s3 = "hello";
> String s4 = "hello";
> String s5 = s1;
>
> if(s1 == s2) System.out.println("s1과 s2 주소값이 같음");
> if(s2 == s3) System.out.println("s2과 s3 주소값이 같음");
> if(s3 == s4) System.out.println("s3과 s4 주소값이 같음");
> if(s5 == s1) System.out.println("s5과 s1 주소값이 같음");
> if(s1.equals(s2)) System.out.println("s1과 s2 객체 내용이 같음");
> if(s1.equals(s3)) System.out.println("s1과 s2 객체 내용이 같음");
> }
>

콘솔은

s3과 s4 주소값이 같음

s5과 s1 주소값이 같음

s1과 s2 객체 내용이 같음

s1과 s2 객체 내용이 같음

복습 끝내고 수업 시작

클래스와 데이터 타입

  • 클래스의 용도

    • 데이터 타입 만들기

      • 오늘의 첫 과제는 여기

      • 처음에 혼자 코딩했을 때 이렇게 했는데, 에러가 났다.

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        public class App {

        public static void main(String[] args) {

        Scanner keyboard = new Scanner(System.in);
        final int LENGTH = 10;
        Lesson[] lesson = new Lesson[LENGTH];
        // 클래스는 잘 정의했음

        int i = 0;
        while (i < LENGTH) {
        System.out.print("번호? ");
        lesson[i].no = Integer.parseInt(keyboard.nextLine());
        (중략)
        }
        }
        }
      • 이렇게 하면 nullpointerException이 뜬다.

      • 현재 객체 생성이 되지 않았음!
      • 때문에 while 문 안에서 객체를 생성해주면서 해당 방에 넣어줘야 함

      • 답은 이것

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        55
        56
        57
        58
        59
        60
        61
        62
        63
        64
        import java.sql.Date;
        import java.util.Scanner;

        public class App {

        public static void main(String[] args) {

        Scanner keyboard = new Scanner(System.in);

        final int LENGTH = 10;

        Lesson[] lessons = new Lesson[LENGTH];

        int i = 0;
        while (i < LENGTH) {
        // 클래스로 정의한 새 데이터 타입의 메모리(인스턴스) 만들기
        Lesson lesson = new Lesson();

        // 사용자가 입력한 값을 메모리에 담는다.
        System.out.print("번호? ");
        lesson.no = Integer.parseInt(keyboard.nextLine());

        System.out.print("수업명? ");
        lesson.title = keyboard.nextLine();

        System.out.print("설명? ");
        lesson.contents = keyboard.nextLine();

        System.out.print("시작일? ");
        lesson.startDate = Date.valueOf(keyboard.nextLine());

        System.out.print("종료일? ");
        lesson.endDate = Date.valueOf(keyboard.nextLine());

        System.out.print("총수업시간? ");
        lesson.totalHours = Integer.parseInt(keyboard.nextLine());

        System.out.print("일수업시간? ");
        lesson.dayHours = Integer.parseInt(keyboard.nextLine());

        // i 번째 배열에 수업 정보를 담고 있는 Lesson 객체(의 주소)를 보관한다.
        lessons[i] = lesson;
        i++;

        System.out.print("\n계속 입력하시겠습니까?(Y/n) ");
        String answer = keyboard.nextLine().toLowerCase();

        if (!answer.equals("y") && answer.length() > 0) {
        break;
        }

        System.out.println();
        }

        keyboard.close();

        System.out.println(); // 빈 줄 출력

        for (int j = 0; j < i; j++) {
        System.out.printf("%3d, %-15s, %10s ~ %10s, %4d\n", lessons[j].no, lessons[j].title, lessons[j].startDate,
        lessons[j].endDate, lessons[j].totalHours);
        }
        }
        }

그 외

  • 분기문, 조건문 통합 과제

  • 메서드의 존재 이유를 알아보는 과제(..)
    쉽게 말해 유지 보수가 쉽도록 만듦

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    public class App {
    static Lesson[] lessons;
    final static int LENGTH = 10;
    static int lessonIdx = 0;
    static Scanner keyboard;
    // static 메서드에서 접근이 안되기 때문에 모두 클래스 변수로 만든 것

    static void addLession() {
    (중략)
    }

    public static void main(String[] args) {

    keyboard = new Scanner(System.in);
    lessons = new Lesson[LENGTH];
    boards = new Board[LENGTH];

    while (true) {
    System.out.print("명령> ");
    String command = keyboard.nextLine().toLowerCase();
    // 사실 이 2줄의 코드도 메서드로 뺄 수 있다!
    if (command.equals("/lesson/add")) {
    addLession();
    }
    (중략)
    }
    }
    }
  • 클래스를 활용하여 메서드 분류

    • Low Coupling
      • 낮은 결합도
      • 한 클래스는 최대한 적은 클래스를 의존해야 한다.
    • High Cohesion
      • 높은 응집도
      • 한 클래스는 하나의 역할만을 담당한다.
  • 패키지를 사용해 클래스 분류

    • 도메인 : dto, vo, 사용자 정의 데이터 타입

      접근 제한자

      • privatge : 같은 클래스 내에서 접근 가능

      • default : 같은 패키지 내에서 접근 가능

      • protected : 같은 패키지 내에서 접근이 가능하고 해당 클래스를 상속 받은 자식 클래스의 경우 접근 가능

      • public : 누구나 접근 가능

      접근 제어자(modifier)

      • 본래 성질을 변경시키는 것

      • ex : 접근 제한자, static, final 등

  • 클래스 변수와 클래스 메서드의 한계, 인스턴스 변수와 인스턴스 메서드가 필요한 이유

    클래스 변수와 인스턴스 변수의 할당

    • 변수 선언은 클래스 로딩이 안된다

    • 클래스 로딩은 단 한 번만 된다.

    • 때문에 클래스 변수는 한 개가 만들어진다 : 클래스가 로딩될 때(클래스 멤버를 사용할 때) 최초 할당

      1
      2
      >   Class.forName();
      >
    • static 블럭 : 클래스가 최초 로딩될 때 실행됨, 즉 여러 번 클래스 멤버를 사용해도 한 번만 실행

      1
      2
      3
      4
      >   static {
      >
      > }
      >
    • this : 인스턴스 메서드 내장 변수, 생략 가능
      • static 메서드에서 사용이 불가능함
      • this는 객체의 주소
  • getter, setter의 등장

    • 인스턴스가 유효한 값을 갖도록 제어하기 위해, 변수에 직접 접근을 막으려 접근 제한자를 건다.
    • 멤버 변수들 = 필드
    • 멤버 변수의 이름 = 필드명
    • getter, setter = 프로퍼티
    • get, set을 떼고 소문자로 첫 문자를 변경한 것 = 프로퍼티명
    • 필드명과 프로퍼티명은 다른 개념이다
    • getter만 구성된 경우 : read only property
    • setter만 구성된 경우 : write only property

인스턴스 메서드 = message 라고 하기도 하며, 인스턴스를 다루는 연산자(operator)로 보기도 한다.