가변 객체, 불변 객체 (feat. 일급 객체)

YH·2023년 3월 26일
0

가변 객체

: Java에서 Class의 인스턴스가 생성된 이후에 내부 상태 변경이 가능한 객체를 말함

  • 대표적인 가변 객체로 ArrayList, HaspMap, StringBuilder, StringBuffer 등이 있다.
  • 가변 객체는 말그대로 내부 상태 변경이 가능하므로 Thread Unsafe하기 때문에 별도의 동기화 처리를 해야한다.
  • 내부 상태를 변경할 수 있도록 만든 DTO 등의 경우에도 가변 객체에 해당된다.

불변 객체

: Java에서 Class의 인스턴스가 생성된 이후에 내부 상태 변경이 불가능한 객체를 말함

  • 대표적인 불변 객체로 String이 있다.
  • 불변이므로 Thread Safe하여 멀티 쓰레드에서 안전하게 사용 가능

불변 객체의 장점

  1. Thread Safe 하므로 안전하게 사용 가능하며 별도의 동기화 처리가 필요하지 않다.
  2. 실패 원자적인(Failure Atomic) 메소드를 만들 수 있다.
    • 실패 원자적(failure-atomic)이란, 호출된 메서드가 실패하더라도 해당 객체는 메서드 호출 전 상태를 유지하는 것
  3. Cache나 Map 또는 Set 등의 요소로 활용하기에 더욱 적합하다.
    • 불변 객체를 위의 요소로 사용하면, 별도의 부가 작업이 필요 없이 다른 작업들을 고려하지 않아도 되므로 사용하는데 용이하다.
  4. 부수 효과(Side Effect)를 피해 오류 가능성을 최소화할 수 있다.
    • 부수 효과(Side Effect)란, 변수의 값이나 상태가 변화에 따라 발생하는 효과로, 불변 객체는 변경 가능성이 적고 객체 사용이 상당 제한되므로 안전하게 객체 사용이 가능하다.
  5. 다른 사람이 작성한 함수를 예측 가능하며 안전하게 사용할 수 있다.
    • 불변성은 다른 사람이 개발한 함수를 위험성이 적은 상태로 사용할 수 있게 해준다.

불변 객체를 만드는 방법

  • 클래스를 final로 선언
  • 모든 클래스 변수를 private와 final로 선언
  • 필드에 참조 타입이 있을 경우, 해당 객체도 불변성을 보장하게 만들어야 한다.
  • 참조에 의해 변경 가능성이 있는 경우 방어적 복사를 수행한다.

일급 객체

'일급'이란 사용할 때 다른 요소들과 아무런 차별이 없다는 것을 뜻함

  • 일급 객체는 특정 언어에 국한되는 문법 단어가 아님
  • Java에서는 람다 또는 익명 함수로 일급 객체를 지원

일급 객체의 조건

  1. 모든 일급 객체는 변수나 데이터에 담을 수 있어야 한다.
  2. 모든 일급 객체는 함수의 파라미터로 전달 할 수 있어야 한다.
  3. 모든 일급 객체는 함수의 리턴 값으로 사용할 수 있어야 한다.

Java에서 람다로 일급 객체 사용 예시

  1. 변수나 데이터에 담을 수 있어야 한다.
import java.util.function.Consumer;

public class Main {
    public static void main(String[] args) {
        Consumer<String> c = (t) -> System.out.println(t); // 람다식을 인터페이스 타입 변수에 할당
        c.accept("Hello World");
    }
}
  1. 함수의 파라미터로 전달 할 수 있어야 한다.
import java.util.function.Consumer;

public class Main {
    // 메소드 매개변수로 람다 함수를 전달
    public static void print(Consumer<String> c, String str) {
        c.accept(str);
    }

    public static void main(String[] args) {
        print((t) -> System.out.println(t) ,"Hello World");
    }
}
  1. 함수의 리턴 값으로 사용할 수 있어야 한다.
import java.util.function.Consumer;

public class Main {
    public static Consumer<String> hello() {
        // 람다 함수 자체를 리턴함
        return (t) -> {
            System.out.println(t);
        };
    }

    public static void main(String[] args) {
        Consumer<String> c = hello();
        c.accept("Hello World");
    }
}

➕ Thread Safe에 대한 내용 추가

Thread Safe에 대한 정의

✔️ 멀티 쓰레드 프로그래밍이란, 하나의 프로세스에서 여러 개의 쓰레드를 만들어 자원의 생성과 관리의 중복을 최소화 하는 것
✔️ Thead Safe란, 멀티 쓰레드 프로그래밍에서 일반적으로 어떤 함수나 변수 또는 객체가 여러 쓰레드로부터 동시에 접근이 이루어져도 프로그램의 실행에 문제가 없는
✔️ 하나의 함수가 한 쓰레드로부터 호출되어 실행 중일 때, 다른 쓰레드가 해당 함수를 호출하여 동시에 실행되더라도 각 쓰레드에서의 함수의 수행 결과가 올바르게 나오는 것

➡️ 반대로 Thread Safe 하지 않다는 것은, 여러 쓰레드가 같은 함수, 변수, 객체 등을 호출하여 실행했을 때 수행 결과가 동일하지 않고 각기 제각기 다른 결과가 나오는 것으로, 각 쓰레드가 다른 쓰레드의 실행 결과에 영향을 주는 것이다.

<참고 URL>

profile
하루하루 꾸준히 포기하지 말고

0개의 댓글