ABOUT ME

Today
Yesterday
Total
  • 자바 객체 지향의 원리와 이해
    Java 2021. 2. 1. 16:26

    [스프링 입문을 위한 자바 객체 지향의 원리와 이해] 로 학습 한 내용

     

    1. 자바와 절차적/구조적 프로그래밍

    [하나의 프로그램이 실행될 때 프로그램이 메모리를 사용하는 방식]       [객체지향 프로그램이 메모리를 사용하는 방식]

     

    [1] main() 메서드 실행시 메모리 사용 방식

       1) JRE는 우선 프로그램 안에 main() 메서드가 있는지 확인한다

       2) JRE는 Start 클래스에서 main() 메서드 발견

       3) main() 메서드가 확인되면 JRE는 프로그램을 실행하기위한 사전준비를함-> JVM 부팅

       4) JVM은 목적파일을 받아 실행

       5) JVM이 하는 일

          (1) 전처리 :  java.lang 패키지를 static영역에 배치, 작성한 모든 class와 import 패키지를 static영역에 배치

     

          (2) stack영역에 stack frame할당

          (3) 메서드 인자 args를 저장할 변수공간 할당(스택 맨 밑에 확보)

         ===> 이렇게 메모리 할당 후 첫 명령문 실행!

    * 여는 중괄호를 만날 떄 마다 스택프레임이 생성된다 (class 정의 여는 중괄호 제외)

      닫는 중괄호 만나면 스택프레임 소멸

    * main() 메서드 가 끝나면 JRE는 JVM종료, JRE자체도 운영체제상의 메모리에서 사라진다

                     

    [2] 변수의 위치

    static : class변수 / stack : 지역변수 / heap : 객체변수

    [3] 변수의 종류

    지역변수 : 스택프레임에 종속적인 지역변수

    전역변수 : 스택프레임에 독립적인 전역변수(=공유변수, 속성,프로퍼티,필드)

    ** 전역변수 사용을 자제해야하는 이유 : 프로젝트 규모에 따라 코드가 커지면서 여러 메서드에서 전역 변수의 값을 변경하기 시작하면 T 메모리로 추적하지않는ㄴ 이사 전역 변수에 저장돼 있는 값을 파악하기 쉽지 않다.

    ** 전역상수는 괜찮~!!

     

    [4] 멀티 스레드 / 멀티 프로세스의 이해

    멀티 스레드(Multi Thread)의 T 메모리 모델은 스택 영역을 스레드 개수만큼 분할해서 쓰는 것이다.

    멀티 스레드는 하나의 T 메모리만 사용하는데 스택 영역만 분할해서 사용하는 구조다.

    멀티 스레드는 하나의 T 메모리 안에서 스택영역만 분할한 것이기 때문에, 하나의 스레드에서 다른 스레드의 스택영역에선 접근할 수 없지만, 스태틱과 힙 영역은 공유해서 사용한다. 따라서 멀티프로세스 대비 메모리를 적게 사용할 수 있는 구조다.

     

    멀티 프로세스(Multi Process)는 다수의 데이터 저장 영역, 즉 다수의 T메모리를 갖는 구조다.

    멀티 프로세스는 각 프로세스마다 각자의 T 메모리가 있고 각자 고유의 공간이므로 서로 참조할 수 없다.

    멀트 프로세스는 하나의 프로세스가 다른 프로세스의 T 메모리 영역을 절대 침범할 수 없는 메모리에 안전한 구조이지만 메모리 사용량은 그만큼 크다.

     

    요약 : 

    메모리는 static / stack / heap 영역으로 나뉘고 static과 stack에 어떻게 쌓이는지 

     

    2. 자바와 객체지향

    자바의 4가지 특성

    캡슐화 (Encapsulation) : 정보은닉

    상속 : 재사용

    추상화 (Abstraction) : 모델링

    다형성 (Polymorphism) : 사용편의

     

    [1] 추상화 : 구체적인 것을 분해해서 관심 영역(애플리케이션 경계)에 있는 특성만 가지고 재조합하는것 = 모델링

    객체 : 세상에 존재하는 유일무이한 사물

    클래스 : 분류,집합 같은 속성과 기능을 가진 객체를 총칭하는 개념

    ==> 세상에 존재하는 유일무이한 객체를 특성(속성+기능)에 따라 분류해 보니 객체를 통칭할 수 있는 집합적 개념, 즉 클래스(분류)가 나오게 된다.

    ** 클래스를 이용해 object를 만들었다는 것을 강조할 때는 object라는 표현보다 클래스의 인스턴스(instance)라는 표현을 쓴다. 객체(object) = 클래스의 인스턴스

    ** 애플리케이션의 경계 : 컨텍스트(context)

    요점 :

    • OOP의 추상화는 모델링이다
    • 클래스 : 객체 = 펭귄 : 뽀로로
    • 클래스 설계에서 추상화가 사용된다
    • 클래스 설계를 위해서는 애플리케이션 경계부터 정해야 한다
    • 객체지향에서 추상화의 결과는 클래스다
    • 상송을 통한 추상화,구체화
    • 인터페이스를 통한 추상화
    • 다형성을 통한 추상화

    ★ 자바는 객체 지향의 추상화를 class를 통해 지원하고 있다 ★

     

    클래스 참조변수 = new 클래스();

    ==> 클래스 인스턴스, 즉 객체를 생성하기 위해 객체 생성자를 호출

    ex) Mouse mickey = new Mouse();

    1) Mouse mickey: Mouse 객체에 대한 참조변수 mickey를 만든다

    2) Mouse 클래스의 인스턴스를 하나 만들어 힙에 배치한다

    3) Mouse 객체에 대한 주소(포인터)를 참조변수 mickey에 할당한다

     

    클래스 멤버 = static 멤버 = 정적멤버

    객체 멤버 = 인스턴스 멤버

     

    << 정적메서드 사용 예 >>

    정적 메서드는 객체의 존재 여부에 관계없이 사용할 수 있다. 정적 멤버들은 객체가 아닌 클래스에 속해있으며 JVM구동시 T 메모리 스태틱영역에 바로 배치되기때문에 객체 존재여부와 관계없이 쓸 수 있다.

    1) main 메서드

    2) getter / setter 

    3) 클래스의 인스턴스를 만들지 않고 사용하는 유틸리티성 메서드 (Math 클래스)

     

    ** 정적 속성인 겨우 T메모리의 스태틱 영역에 클래스가 배치될 때 클래스 내부에 메모리 공간이 확부된다

    ** 객체 속성은 스태틱 영역에는 속성명만 있고 메모리 공간은 확보하지않는다. 힙 영역에 객체가 생성되면 바로 그 때 각 객체 안에 멤버 속성을 위한 메모리 공간이 할당된다

     

    [2] 상속 : 재사용+확장

    • 객체 지향의 상속은 상위 클래스의 특성을 재사용한느 것이다.
    • 객체 지향의 상속은 상위 클래스의 특성을 확장하는 것이다.
    • 객체 지향의 상속은 is a kine of 관계를 만족해야 한다.
    • 인터페이스는 be able to 라는 표현의 형태로 만드는것이 좋다

    즉 상위 클래스는 하위 클래스에게 특성(속성,메서드)를 상속해주고, 인터페이스는 클래스가 '무엇을 할 수 있다'라는 기능을 구현토록 강제한다

     

    상속과 T메모리

     

    pororo 인스턴스가 생성(5번째 줄)됐을 때 메모리 상태

    ** 하위클래스의 인스턴스가 생성될 때 상위 클래스의 인스턴스도 생성된다

     

    [3] 다형서이 사용편의성

    다형성과 T메모리

    상위클래스인 Animal을 상속받아 재정의했기때문에 (overriding) pingu객체에서 showName을 호출하면 Penguin에서 재정의한 메서드가 호출된다.

    ** 상위 클래스 타입의 객체 참조 변수를 사용하더라도 하위 클래스에서 오버라이딩(재정의 한) 매서드가 호출된다 **

     

    [4] 캡슐화: 정보은닉

    ** UML표기법에서 접근제어자

    ** 속성이나 메서드 아래 밑줄을 사용한 경우 : 정적 멤버를 나타낸다

    접근제어자가 객체 멤버(인스턴스 멤버)와 쓰일 때와 정적 멤버(클레스 멤버)와 쓰일 대를 비교해서 살펴보자

    정적 멤버에 접근 할 때는 객체참조변수명.정적멤버 형식보다 클래스명.정적멤버 형식으로 접근하는편이 좋다

     

    3. 자바가 확장한 객체지향

    [1] 추상클래스

    • 선언부는 있는데 구현부가 없다
    • 객체를 만들 수 없다
    • 추상 메서드는 하위 클래스에게 메서드 구현을 강제한다
    • 추상 메서드를 포함하는 클래스는 반드시 추상 클래스여야한다

    [2] 생성자

    • 아무런 생성자도 만들지 않으면 자바는 인자가 없는 기본 생성자를 자동으로 만들어준다
    • 인자가 있는 생성자를 하나라도 만든다면 자바는 기본 생성자를 만들어주지않는다

    [3] static 블록

    public class test{

       static {

          /// staitc 블록

        }

    }

     

    클래스 정보는 main메서드 실행 시 바로 메모리에 적재되는것이 아니라 해당 클래스가 처음 사용될 때 static 영역에 로딩된다. 이 때 단 한번 해당 클래스의 static 블록이 실행된다. 클래스가 제일 처음 사용되는 경우는 다음 세가지이다.

    • 클래스의 정적 속성을 사용할 때
    • 클래스의 정적 메서드를 사용할 때
    • 클래스의 인스턴스를 최초로 만들 때

    ** @JUnit 의 @BeforeClass 어노테이션 을 참고하면 좋다

    ** static 블록과 유사하게 클래스의 인스턴스를 위한 인스턴스 블록도 존재한다. 아무런 표시 없이 {} 블록을 사용하게되면 인스턴스가 생성될 때마다 {}블록이 실행된다. {}블록은 객체 생성자가 실행되기 전에 먼저 실행된다

     

    [4] final키워드

    ** final키워드는 클래스,변수,메서드에 붙을 수 있다.

    1. final과 클래스

    public final class cat{} 

    클래스에 붙은 final의미 : 상속을 허락하지않겠다. 따라서 하위클래스를 만들 수 없음

    2. final과 변수

    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
    public class cat(){
        
        final static int 정적상수1 = 1;
        final static int 정적상수2;
     
        final int 객체상수1 = 1;
        final int 객체상수2;
        
        static{
            정적상수2 = 2;
            
            //상수는 한 번 초기화되면 값을 변경할 수 없다
            // 정적상수2 = 4;    
        }
        
        cat(){
            객체상수2 = 2;
     
            //상수는 한 번 초기화되면 값을 변경할 수 없다
            // 객체상수2 = 4;
     
            final int 지역상수1 = 1;
            final int 지역상수2;
     
            지역상수2 = 2;
        }    
     
    }
     

    변수에 final이 붙으면 초기화 후 값 변경을 할 수 없다.

    (1) 정적상수 : 정적 생성자에 해당하는  static블록엡서 초기화 가능

    (2) 객체상수 : 객체 생성자 또는 인스턴스 블록에서 초기화 가능

    (3) 지역상수 : 선언시 또는 최초 한 번만 초기화 가능

    3. final과 매서드

    매서드에 붙은 final의 의미: 재정의 즉 오버라이딩 불가능

     

    [5] instanceof 연산자

    특정 클래스의 인스턴스인지 확인하는 연산자. true나 false 반환함.

     

    [6] this키워드

    main메서드 실행 후 메모리 상태

    위 코드에서 var는 객체변수도 있고 지역변수도 있다. 

    • 지역 변수와 속성(객체 변수, 정적 변수)의 이름이 같은 경우 지역변수가 우선한다.
    • 객체 변수와 이름이 같은 지역 변수가 있는 경우 객체변수를 사용하려면 this를 접두사로 사용한다
    • 정적 변수와 이름이 같은 지역변수가 있는경우 정적 변수를 사용하려면 클래스명을 접두사로 사용한다

    [7] Super키워드

    상위 클래스의 인스턴스를 지칭한다

     

    4. 객체 지향 설계 5원칙 - SOLID

    좋은 소프트웨어 설계를 위해서는 결합도(coupling)는 낮추고 응집도(cohesion)는 높이는것이 바람직하다.

    • 결합도는 모듈(클래스)간의 상호 의존 정도로서 결합도가 낮으면 모듈 간의 상호 의존성이 줄어들어 객체의 재사용이나 수정,유지보수가 용이하다.
    • 응집도는 하나의 모듈 내부에 존재하는 구성요소들의 기능적 관련성으로 응집도가 높은 모듈은 하나의 책임에 집중하고 독립성이 높아져 재사용이나 기능의 수정, 유지보수가 용이하다.

    [1] SPR - 단일 책임 원칙 (어떤 클래스를 변경해야하는 이유는 오직 하나뿐이어야한다, 추상화)

    [2] OCP - 개방 폐쇄 원칙 (자신의 확장에는 열려있고, 주변의 변화에 대해서는 닫혀있어야한다, JDBC)

    [3] LSP - 리스코프 치환 원칙 (하위 클래스의 인스턴스는 상위형 객체 참조 변수에 대입해 상위 클래스의 인스턴스 역할을 하는데 문제가 없어야한다[서브타입은 언제나 자신의 기반 타입으로 교체할 수 있어야한다], 상속)

    [4] ISP - 인터페이스 분리 원칙 (클라이언트는 자신이 사용하지 않는 메서드에 의존관계를 맺으면 안 된다)

    [5] DIPS - 의존 역전 원칙 (자신보다 변하기 쉬운 것에 의존하지마라)

     

     

     

    'Java' 카테고리의 다른 글

    스레드  (0) 2022.10.21

    댓글

Designed by Tistory.