자바 정리 1

다람·2023년 5월 18일
0

JAVA

목록 보기
25/27

JAVA 특징

  • JAVA는 객체지향 프로그래밍 언어
  • 기본 자료형을 제외한 모든 요소들이 객체로 표현되고, 객체 지향 개념의 특징인 캡슐화, 상속, 다형성이 잘 적용된 언어

장점

  • JVM 위에서 동작하기 때문에 운영체제에 독립적이다.
  • GC를 통한 자동적인 메모리 관리가 가능하다.

단점

  • JVM 위에서 동작하기 때문에 실행 속도가 상대적으로 느리다.
  • 다중 상속이나 타입어 엄격하며 제약이 많다.

객체지향 프로그래밍(OOP)

우리가 실생활에서 쓰는 모든 것을 객체라고 하는데, 객체 지향 프로그래밍은 프로그램 구현에 필요한 객체를 파악하고 상태와 행위를 가진 객체를 만들고 각각의 객체들의 역할이 무엇인지 정의하여 객체들 간의 상호작용을 통해 프로그램을 만드는 것을 말한다.
특징 - 캡슐화, 상속, 다형성, 추상화 등이 있으며 모듈 재사용으로 확장 및 유지보수가 용이하다.

캡슐화

연관있는 변수와 함수를 클래스로 묶는 작업이며 외부로부터 중요한 데이터를 보존, 보호하는 것 (은닉)

  • 은닉화 : 실제 구현 내용 일부를 외부에 감추는 효과
    --> 은닉화를 지키는 방법은 접근 제한자를 통해서~
    객체의 속성과 행위를 묶으면 응집도가 올라가 자율적인 객체가 된다는 장점이 있다.
//가짜 캡슐화
public class Movie {
    private Money fee;
    
    public Money getFee() {
        return this.fee;
    }
    
    public void setFee(Money fee) {
        this.fee = fee;
    } 
}

// 진짜 캡슐화 참고
// https://steady-coding.tistory.com/449

추상화

객체의 관련 속성만 표시하고 불필요한 세부 정보는 숨기는 것
자료의 추상화 : 객체 지향 관점에서 클래스를 정의하는 것
추상 클래스 : 여러 클래스 간 비슷한 필드와 메소드를 공통적으로 추출해 만들어진 클래스
인터페이스 : 동일한 목적하에 동일한 기능을 수행하게끔 강제하는 것

상속

부모 클래스의 변수, 메소드를 자식 클래스에서도 그대로 사용하는 것
상속은 언제 쓰나? 확장이 아닌 정제할 때 사용

public class Boy extends Student {

    public Boy(String name) {
        super(name);
    }

    public void run() {
        System.out.println("[" + name + "] 뛰고 있습니다.");
    }
}

public class Girl extends Student {

    public Girl(String name) {
        super(name);
    }

    public void walk() {
        System.out.println("[" + name + "] 걷고 있습니다.");
    }
}

다형성

부모-자식 상속 관계에 있는 클래스에서 상위 클래스가 동일한 메세지로 하위 클래스들을 서로 다르게 동작 시키는 것
다형성 구현 방법으로는 오버로딩, 오버라이딩, 함수형 인터페이스
오버로딩 : 요구사항이 변경되었을 때 모든 메소드 수정이 필요하므로 적절히 고려해 사용해야 한다.
오버라이딩 : 중복을 줄이기 위해
함수형 인터페이스 : 람다식과 관련, enum과 함께 사용하면 좋다.

public interface Movable {

    void move();
}

public class Car implements Movable {

    @Override
    public void move() {
        System.out.println("도로로 달립니다.");
    }
}

public class Airplane implements Movable {

    @Override
    public void move() {
        System.out.println("하늘을 납니다.");
    }
}

public class Train implements Movable {

    @Override
    public void move() {
        System.out.println("선로로 주행합니다.");
    }
}

public class Main {

    public static void main(String[] args) {
        final List<Movable> movables = Arrays.asList(new Car(), new Train(), new Airplane());
        for (final Movable movable : movables) {
            movable.move();
        }
    }
}

객체지향 설계원칙

SRP (단일 책임 원칙) : 한 클래스는 하나의 책임만 가져야 한다.
OCP (개방-폐쇄 원칙) : 확장에는 열려있고, 수정에는 닫혀있어야 한다.
LSP (리스코프 치환 원칙) : 상위 타입은 항상 하위 타입으로 대체할 수 있어야 한다.
ISP (인터페이스 분리 법칙) : 최소한의 기능만 제공하면서 하나의 역할에 집중하라는 의미, 단일 책임을 강조
DIP (의존관계 역전 원칙) : 구체적인 클래스보다 인터페이스, 추상클래스와 같이 변하지 않을 가능성이 높은 클래스와 관계를 맺어야 한다. DIP원칙을 따르는 가장 인기 있는 방법은 의존성 주입(DI)이다.

JVM 역할

JVM은 스택 기반으로 동작하며, JAVA byte code를 OS에 맞게 해석해주는 역할을 하고 GC를 통해 자동적인 메모리 관리를 해준다.

JAVA 컴파일 과정

  1. 개발자가 .java 파일을 생성한다.
  2. build를 한다.
  3. java compiler의 javac의 명령어를 통해 바이트코드(.class)를 생성한다.
  4. class loader를 통해 JVM메모리 내로 로드한다.
  5. 실행엔진을 통해 컴퓨터가 읽을 수 있는 기계어로 해석된다.

자바 메모리 구조

  1. method 영역
    전역변수, static 변수 정보가 저장되는 공간이다. 프로그램의 시작부터 종료까지 메모리에 남아있다.
    모든 스레드에서 정보가 공유된다.

  2. Heap
    new 연산자로 생성된 객체, 배열 등이 저장되는 공간이다. heap에 저장된 데이터는 GC가 처리하지 않는 한 소멸되지 않는다.
    모든 스레드에서 정보가 공유된다.

  3. Stack
    지역변수, 메소드의 매개변수와 같이 잠시 사용되고 필요가 없어지는 데이터가 저장되는 공간이다. LIFO구조이며 변수에 새로운 데이터가 할당되면 이전 데이터는 지워진다.
    스레드마다 하나씩 존재한다.

  4. PC register
    스레드가 생성되면서 생기는 공간으로 스레드가 어느 명령어를 처리하고 있는지 그 주소를 등록한다. JVM이 실행하고 있는 현재 위치를 저장하는 역할

  5. Native method stack
    java가 아닌 다른 언어 (c언어 등)로 구성된 메소드를 실행이 필요할 때 사용하는 공간

각 메모리 영역에 할당되는 시점

Method 영역 : JVM이 동작해서 클래스가 로딩될 때 생성
Stack 영역 : 컴파일 타임 시 할당
Heap 영역 : 런타임 시 할당

컴파일 타입 : 소스코드가 기계어로 변환되어 실행가능한 프로그램이 되는 과정
런타임 : 컴파일 타임 이후 프로그램이 실행되는 때

Class loader

컴파일 결과로 만들어진 바이트 코드 파일을 읽어 메모리에 배치하는 역할

클래스 로드 과정

클래스 로더는 새로운 클래스를 로드해야 할 때, 다음과 같은 방식으로 로드를 수행한다.
1. JVM의 메소드 영역에 클래스가 로드되어 있는지 확인한다. 만약 로드외어 있는 경우 해당 클래스를 사용한다.
2. 메소드 영역에 클래스가 로드되어 있지 않을 경우, 시스템 클래스 로더에 클래스 로드를 요청한다.
3. 시스템 클래스 로더는 확장 클래스 로더에 요청을 위임한다.
4. 확장 클래스 로더는 부트스트랩 클래스 로더에 요청을 위임한다.
5. 부트스트랩 클래스 로더는 부트스트랩에 해당 클래스가 있는지 확인한다.
6. 확장 클래스 로더는 확장에 해당 클래스가 있는지 확인한다.
클래스가 존재하지 않을 경우 시스템 클래스 로더에게 요청을 넘긴다.
7. 시스템 클래스 로더는 시스템 Classpath에 해당 클래스가 있는지 확인한다. 클래스가 존재하지 않는 경우 ClassNotFoundException을 발생시킨다.

java에서 제공하는 원시 타입들과 바이트

정수형 byte(1), short(2), int(4), long(8) 실수형 float(4), double(8), 문자형 char(2), 논리형 boolean(1)

오버라이딩, 오버로딩

오버라이딩(overriding) : 상위 클래스에 있는 메소드를 하위 클래스에서도 재정의하는 것
오버로딩(overloading) : 매개변수의 개수나 타입을 다르게 하여 같은 이름의 메소드를 여러 개 정의하는 것

불변객체

객체 생성 이후 내부의 상태가 변하지 않는 객체를 말한다.
예로 final이 있으며
불변객체나 final을 사용하는 이유?
--> 메소드 호출 시 파라미터 값이 변하지 않는 보장이 있으며 GC가 스캔하는 객체의 수가 줄기 때문에 GC의 성능을 높일 수 있다.

가비지 컬렉션

JVM의 메모리 관리 기법 중 하나로 시스템에서 동적으로 할당됐던 메모리 영역 중에서 필요없어진 메모리 영역을 회수하여 메모리를 관리해주는 기법

가비지컬렉션 과정

JVM이 어플리케이션의 실행을 잠시 멈추고 GC를 실행하는 쓰레드를 제외한 모든 쓰레드들의 작업을 중단 후 사용하지 않는 메모리를 제거하고 작업이 재개
GC의 작업은 young영역에 대한 minor GC, major GC로 구분된다.

추상 클래스와 인터페이스 설명

추상클래스는 클래스 내 추상 메소드가 하나 이상 포함되거나 abstract로 정의된 경우를 말하고, 인터페이스는 모든 메소드가 추상 메소드로만 이루어져 있는 것을 말한다.

공통점

  • new 연산자로 인스턴스 생성 불가능
  • 사용하기 위해서는 하위 클래스에서 확장/구현해야 한다.

차이점

  • 인터페이스는 그 인터페이스를 구현하는 모든 클래스에 대해 특정한 메소드가 반드시 존재하도록 강제함에 있다.
  • 추상크래스는 상속받는 클래스들의 공통적인 로직을 추상화시키고, 기능 확장을 위해 사용한다.
  • 추상 클래스는 다중 상속이 불가능하지만 인터페이스는 다중 상속이 가능하다.
profile
안녕

0개의 댓글