HAZEL

[ CH02. 객체지향 입문 ] 객체 간의 협력, static 변수, 싱글톤 패턴(Singleton pattern) , 배열 , 다차원 배열 본문

카테고리 없음

[ CH02. 객체지향 입문 ] 객체 간의 협력, static 변수, 싱글톤 패턴(Singleton pattern) , 배열 , 다차원 배열

Rmsid01 2021. 3. 31. 13:33

CH02. 객체지향 프로그래밍 

: 패스트 캠퍼스 강의를 공부하고 정리한 내용입니다.

 

 

01. 객체 간의 협력 (collabration)

: 객체지향 프로그래밍에서 객체 간에는 협력이 이루어짐 - 유기적으로 연동되어있다. 

: 협력을 위해서는 필요한 메세지를 전송하고 이를 처리하는 기능이 구현되어야 함

: 매개 변수로 객체가 전달되는 경우가 발생 

 

02. static 변수 ( 정적 변수 )

: 동일한 클래스에서 생성된 여러 인스턴스에서 공통으로 사용하는 변수 

 

1. 공통으로 사용하는 변수가 필요한 경우.

: 여러 인스턴스가 공유하는 기준 값이 필요한 경우 

 

2. static 변수 사용 법

: static int LEEnum;

   Student.LEEnum = 100;

 

 - 인스턴스가 생성될때 만들어지는 변수가 아닌, 처음 프로그램이 메모리에 로딩될때, 메모리 할당 ( 자세한건 아래에 적혀있음 )

 - 클래스 변수, 정적변수 라고 함. ( 인스턴스 변수와는 다르다 ) 

 - 인스턴스 생성과 상관없이 사용 가능하므로, 클래스 이름으로 직접 참조

 

3.  static 변수는 언제 만들어 지는 가 ?

: 프로그램을 구동시키면 -> 메모리에 올라가게 됨. ( 이러한 상태를 '프로세스'라고 함 )  -> 스레드 상태가 되서 돌아감

   이렇게, 메모리에 올라가게 될때, 2가지 영역을 가지게 됨.

   1. data( 상수, static ) 영역 - 처음에 메모리에 로딩될때, 처음부터 메모리를 잡는 영역 ex, 상수, 리터럴, static 변수

   2. 코드 영역  - 프로그래밍을 하면, instruction - 명령을 하게되면 라인 바이 라인으로 수행됨. 

 

 즉, **힙메모리가 아닌, data 영역에 사용됨. 메모리가 로딩되는 순간 잡히고, 프로그래밍이 끝나서 메모리가 업로드 되는 순간 없어짐.

 

  ** 힙 메모리 - 인스턴스가 사용될때마다 쓰이는 메모리 ( 동적 메모리 ) => 이것이 사라지는 순간 garbage collector  에 의해서 메모리가 수거가 됨. 

 

4. static 메서드의 구현과 활용 

: 클래스 이름으로 호출 가능 ( 클래스 메서드, 정적 메서드 )

: 인스턴스 호출과 무관하게 바로 메서드를 사용할 수 있다. ( 이미 메모리상에 저장되어있기 때문! ) 

System.out.println(Employee.getSerialNum());


- static 메서드 ( 클래스 메서드 ) 에서는 인스턴스 변수를 사용할 수 없다. 

  : 인스턴스 생성과 무관함. - 따라서, 

  : 인스턴스 생성 전에 호출 될 수 있으므로 static 메서드 내부에서는 인스턴스 변수를 사용할 수 없음. 

public static void setSerialNum(int serialNum) {

        int i = 0; // i 는 이함수가 시작해서 없어질 지역 변수 - 지역변수는 상관 없다. 
//        employeeName = "Lee";  - 이 함수가 불러올때 이 변수(인스턴스변수)가 없을 수도 있음 -> 오류 발생 

		Employee.serialNum = serialNum;
	}
    

// static가 아닌 일반 메서드 안에서는 아무 문제가 없다
// 메모리 문제 ! - 일반 메서드에서 static 변수를 사용하는것은 아무 문제가 없다. ( 이미 static은 있기 때문에)
public int getEmployeeId() {
        serialNum = 1000;
        return employeeId;
    }

 

5. 변수의 유효범위(scope) 와 메모리 

: 변수의 유효범위와 생성, 소멸은 각 변수의 종류마다 다르다.

패스트 캠퍼스 강의

: static 변수는 프로그램이 메모리에 있는 동안 계속 그 영역을 차지함 -> 매우 큰 메모리를 할당하는것은 안좋음

: 클래스 내부의 여러 메서드에서 여러번 사용하는 변수는 멤버 변수로 선언하는것이 나음

: 그러나, 멤버 변수가 너무 많으면 인스턴스 생성시 메모리가 쓸데없이 할당되므로 적절하게 사용하는 것이 좋음 

 

 

03. 싱글톤 패턴 ( Singleton pattern ) 

1. 싱글톤 패턴이란

: 디자인패턴(23개패턴)의 한 분야로, 객체지향프로그램에 의해서 좀더 효율적인 코드를 만들고자 하는 패턴  

: 보통, 인스턴스가 여러개인 경우가 많지만, 그럴경우 문제가 발생하는 경우가 존재한다. ( ex, date ) 즉, 프로그램에서 인스턴스가 단 한 개만 생성되어야 하는 경우 사용하는 디자인 패턴으로 static 변수, 메서드를 활용하여 구현 가능

public class Company {
    // 회사이름은 단하나 이기 때문에, static으로 만듦
    private static Company instance = new Company();

    // 외부에서 회사를 마음대로 new 할수없도록 private를 만듦
    private Company(){}
    
    // static 을 넣어줘야 외부에서 아래 이름을 써어줄수 있음 .
    // 외부에서 유일한 인스턴스를 참조할 수 있는 public 메서드 제공
    public static Company getInstance() {
        if (instance == null){
            instance = new Company(); // 혹시 몰라서 넣은 방어적인 코드
        }
        return instance;
    }
  }
  
import java.util.Calendar;

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

        // 인스턴스를 만들지 않고, 바로 가져다 쓸것 이기 때문에 statics
        Company company1 = Company.getInstance();
        Company company2 = Company.getInstance();

        System.out.println(company1); // ch18.Company@1540e19d
        System.out.println(company2); // ch18.Company@1540e19d - 같음

        // 날짜가 필요할때, 자바에서 util에서 제공해줌. - static 이므로, new 안됨. - 유일한 객체를 제공함
        Calendar calendar = Calendar.getInstance();
        System.out.println(calendar);
    }
}

 

즉 , class 이름 : singleton 으로 -  instance 라는 이름의 private 멤버 변수 -  singleton 생성자가 private 이고, getinstance public으로 제공된다.

 

 

04. 배열 

1. 배열이란?

: 동일한 자료형의 순차적 자료구조, 인덱스 연산자 [] 을 이용해서 빠르게 참조할 수 있음

: 물리적 위치와 논리적 위치가 동일하며 '0' 부터 시작함.  - 데이터를 찾는데 빠르다. ( linked list 와 다름 )

 

- 자바에서는 ArrayList 를 많이 활용함 ( 파이썬에서 array와 비슷한 것 같다 ) 

- 배열의 한 요소를 element라고 하며, 몇개인지 먼저 선언해준다. 즉, size를 설정해준다. 

- element 끼리 연속적이어야 한다. -> 그로인해, 중간에 삽입이나 삭제할 경우, 속도 지연이 좀 걸린다. 

 

-  기본자료형 배열  ( int , double ) , 객체 배열 ( Student ,Employee ) 

 

 

2. 배열 선언 < 2가지 방법이 있음 > 

int[] arr1 = new int[10];
int arr2[] = new int[10];

 

3. 배열 초기화 < 3가지 방법 > 

: 배열은 선언과 동시에 자료형에서 초기화됨. 

int[] numbers = new int[] {10, 20, 30};  //개수 생략해야 함 new int[3] - x 

int[] numbers = {10, 20, 30};            // new int[]  생략 가능 

int[] ids; 
ids = new int[] {10, 20, 30};            // 선언후 배열을 생성하는 경우는 new int[] 생략할 수 없음

 

- arr.length : 길이를 나타내줌 ( 파이썬의 len(arr) 와 동일 ) 

 

4. 배열의 길이와 요소의 개수는 동일하지 않음 

: 배열을 선언하면 개수만큼 메모리가 할당되지만, 실제 데이타가 없을 수 도 있음. 

: arr.length - 배열의 개수를 반환 ; 요소의 개수와 다를 수 있음 . 즉, length를 활용하여 오류가 나는 경우가 있음

 

5. 객체 배열 선언과 구현 

: 배열을 선언한 다는 것은 단지, 주소만 잡힌다. ( 메모리가 할당 ) 는 개념이지, 각 배열의 요소들의 객체는 생성된 것은 아니다. 

  따라서, 각각 객체는 생성하여 저장해야한다. 

package ch21;

public class BookArrayTest {
    public static void main(String[] args) {
        Book[] library = new Book[5];

        // 객체를 생성해서 각 배열의 요소 넣기 - 안넣으면 null 이 뜸
        library[0] = new Book("태백산맥1","조정래");
        library[1] = new Book("태백산맥2","조정래");
        library[2] = new Book("태백산맥3","조정래");
        library[3] = new Book("태백산맥4","조정래");
        library[4] = new Book("태백산맥5","조정래");

        for(int i = 0 ; i <library.length ; i++){
            System.out.println(library[i]);
            library[i].showBookInfo();
        }
    }
}

 

6. 객체 배열 복사

 

a. 얕은 복사

: 객체주소만 복사되어 한쪽 배열의 요소를 수정하면 같이 수정됨. 즉, 같은 객체( 같은 주소를 ) 가리킴 

: 같이 복사된 이유는, 원본과 카피라이브러리가 있을 때, new를 하면 또 새로운 공간에 객체가 만들어진다. 

  - 여기서 복사한 것은 저 새로운 공간인 '주소'를 복사한 것이기 때문에, 두개 배열 모두 영향을 주게 된 것이다. 

// 기준점 ~에서, 목적지 ~ 까지 , 얼만큼
System.arraycopy(library, 0, copylibrary , 0, 5);

 

b. 깊은 복사

: 각각의 객체를 생성하여 그 객체의 값을 복사하여 배열이 서로 다른 객체를 가리키도록 함. 

: 다르게 복사가 되는 이유는 각각 다른 인스턴스의 주소를 가지고 있기 때문이다.

Book[] library = new Book[5];
Book[] copylibrary = new Book[5];

// 객체를 생성해서 각 배열의 요소 넣기 - 안넣으면 null 이 뜸
library[0] = new Book("태백산맥1", "조정래");
library[1] = new Book("태백산맥2", "조정래");
library[2] = new Book("태백산맥3", "조정래");
library[3] = new Book("태백산맥4", "조정래");
library[4] = new Book("태백산맥5", "조정래");

// 깊은 복사
copylibrary[0] = new Book();
copylibrary[1] = new Book();
copylibrary[2] = new Book();
copylibrary[3] = new Book();
copylibrary[4] = new Book();

// 다른 주소에 값만 복사! 
for (int i = 0; i < library.length; i++) {
copylibrary[i].setTitle(library[i].getTitle());
copylibrary[i].setAuthor(library[i].getAuthor());
}

 

7. 다차원 배열 

2차원 이상으로 구현된 배열 - 평면이나 공간을 표현할 수 있음. 

int[ ][ ] = new int[2][3]

int[ ][ ] = {{1,2,3},{4,5,6}} // 초기화

 

8. ArrayList - java.util 패키지 제공

: 기존의 배열 선언과 사용은 - 배열의 길이를 정하고, 요소의 개수가 배열의 길이보다 커지면 배열을 재할당하고 복사해야한다는 단점을 가지고 있었다. 이것을 좀더 효율적으로 관리하기 위해서 자바에서 제공해주는 코드! 

 

이미지 출처 : 패스트캠퍼스 강의

ArrayList<Book> library = new ArrayList<Book>(); // 생성자. 

library.add(new Book("태백산맥","조정래"));