원시값 포장이란?

허준기·2023년 5월 5일

자바

목록 보기
5/9

원시값 포장

 원시타입을 `Wrapper Class`로 포장해서 객체로 만듦
원시타입의 값을 이용해 속성을 표현하지 않고 , 의미가 있는 객체로 표현
클래스 내부에 검증 로직을 만들어 `스스로 상태를 관리하게 되어 책임을 분리`

블로그 여러개 보면서 원시값 포장을 어디에 사용하는건가 고민하고 있었는데 우테코 2기 오렌지 원시값 포장 이 글을 보고 어디에 쓸 지 감이 잡혔다.

원시값을 클래스에 넣어서 사용하게 되면 그 클래스에서는 어떠한 동작만 하고 싶은데 변수들을 관리하느라 자잘한 메소드들이 생겨나게 된다. 그러면 클래스가 길어지게 되고 가독성이 안좋아지게 된다.

그리고 이런식으로 코드를 짜게 되면 유지보수가 쉬워지고, 값의 유효성 검증을 하기 편해진다.

자 그럼 원시값 포장을 알아보기에 앞서 먼저 원시타입에 대해서 알아보자
자바에는 원시타입과 참조타입 두가지의 타입이 있다.

원시타입

 정수, 실수, 문자, 논리 리터럴(boolean) 등 실제 데이터 값을 저장하는 타입 
  1. Null을 담을 수 없다
  2. 제네릭 타입에서 사용할 수 없다

참조타입

 기본 타입을 제외한 타입으로, 객체의 주소를 저장하는 타입 → 문자열, 배열, 열거형 상수, 클래스, 인터페이스 등 
  1. Null을 담을 수 있다
  2. 제네릭 타입에서 사용할 수 있다

이렇게 보면참조타입과 비교해서 장점이 없어 보이는데 원시타입을 왜 사용할까?

  1. 접근속도
  2. 원시타입은 스택메모리에 값이 존재한다. 반면 참조 타입은 하나의 인스턴스이기 때문에 스택 메모리에는 참조값만 있고, 실제 값은 힙 메모리에 존재하게 된다. 그리고 값을 필요로 할 떄마다 언박싱 과정을 거쳐야ㅑ 하니 원시 타입과 비교해 접근 속도가 느려지게 된다!
  3. 차지하는 메모리 양
  4. 차지하는 메모리의 양도 다르다. 원시타입은 boolean - 1bit, byte - 8bits, short/char - 16bits, int/float - 32bits, long/double - 64bits를 차지하는데에 비해 참조타입은 모든 타입들이 128bits씩 차지해서 메모리의 낭비가 크다.

이제 코드로 살펴보자!

public class Mouse {
    private String name;    // 쥐의 이름
    private int age;        // 쥐의 나이

    public Mouse(String name, int age){
        validateName(name);
        validateAge(age);
        this.name = name;
        this.age = age;
    }

    private void validateName(String name) {
        if (name.length() < 2) {
            throw new RuntimeException("이름은 두 글자 이상이어야 합니다.");
        }
    }

    private void validateAge(int age) {
        if (age < 1) {
            throw new RuntimeException("나이는 0살부터 시작합니다.");
        }
    }

    public void printNameAge(){
        System.out.println(name + " " + age);
    }
}

Mouse라는 클래스를 만들어줬다. 클래스 이름이 Mouse인 이유는 이번에 알고리즘 팀플하는데 쥐가 미로찾기하는 프로그램 만드는 거라서 그렇게 지었다. → 아무의미 없음

아무튼 이 코드는 이름과 나이를 private 점근제어자를 써서 원시값 형태로 가지고 있다. 이렇게 되면 원래 Mouse클래스에는 쥐가 가진 동작들을 넣어야 하는데 name과 age를 관리할 메소드까지 넣어야해서 클래스가 길어지게 된다.

그래서 이 원시값들을 객체로 관리해보자

public class Mouse {
    private Name name;
    private Age age;


    public Mouse(String name, int age) {
        this.name = new Name(name);
        this.age = new Age(age);
    }

    public void printNameAge() {
        System.out.println(this.name + " " + this.age);
    }
}

class Name {
    private String name;    // 쥐의 이름

    public Name(String name) {
        if (name.length() < 2) {
            throw new RuntimeException("이름은 두 글자 이상이어야 합니다.");
        }
        this.name = name;
    }
}

class Age {
    private int age;        // 쥐의 나이

    public Age(int age) {
        if (age < 1) {
            throw new RuntimeException("나이는 0살부터 시작합니다.");
        }
        this.age = age;
    }
}

클래스를 나눠서 Name 클래스와 Age 클래스로 각 변수들의 유효성 검사를 해주고 Mouse 클래스에서는 출력만 담당하게 해줬다.
이렇게 하면 훨씬 코드가 보기 편하다.

Primitive Type과 Wrapper Class

Wrapper Class

 원시타입을 객체로 포장한것

Wrapper Class에는 Null값을 넣을 수 있다. 원시타입은 당연히 안된다. 그리고 객체이다 보니 == 이 아닌 .equals() 메소드로 값 비교를 한다. 만약 ==을 사용하게 된다면 값이 아닌 주소를 비교하게 되므로 false가 반환된다!

그렇다면 이 Wrapper Class를 언제 사용할까?

  • 매개변수로 객체가 요구 될 떄
  • 기본형 값이 아닌 객체로 저장해야 될 때
  • 객체간의 비교가 필요할 때
  • 이럴때 사용한다고 하는데 아직은 잘 모르겠다...

    제네릭<>이 들어가면 필수로 Wrapper Class를 사용해야 한다고 한다. → ArrayList, LinkedList 등에 쓰인다.
    저번에 썼을때는 모르고 썼는데 하나 배웠다..

    ArrayList<Integer> arr = new ArrayList<>();	// 올바른 형식
    ArrayList<int> arr = new ArrayList<>();	// 잘못된 형식

    위에서 말했듯이 원시타입에는 byte, short, int, long, float, double, boolean, char 이 있다.

    그리고 Wrapper Class에는 Byte, Short, Integer, Long, Float, Double, Boolean, Character 이 있다. 그냥 원시타입에 대문자만 붙인 느낌이다. Integer 랑 Character 제외!!

    VO(Value Object)란?

     값으로 쓰일 수 있는 객체 
     객체의 불변성 보장
     로직 포함 가능

    equals() 와 hashcode() 를 오버라이딩 → 재정의해야함!
    VO 관련해서 찾다보니 DTO와 Entity라는 개념이 나온다 나중에 조사해서 글을 써보자
    그리고 MVC 패턴들도 자주 보이는데 이것도 조사해서 글을 써봐야겠다.

    원시값 포장과 VO의 차이는?

    내가 이해한 바로는 VO도 원시값 포장에 속하기는 하는데 더 좁은 의미인것 같다. 불변성을 갖기 때문에 set을 하지 못하고 메서드들도 재정의 해주어야 한다.
    둘 다 도메인 객체를 포장하기 위해 사용하는 것은 같다. 음.. 이건 코드를 많이 짜보면서 익숙해져야할 것 같다..

    알아보면서 뭔가 배운다는 느낌은 좋은데 어렵다.. 공부를 하면 할수록 알아야할게 많아지고 있다..... 그래도 알아가는 재미는 있다. 좀 더 재미를 붙여보자!!!!!

    참고사이트

    https://siyoon210.tistory.com/139
    https://tecoble.techcourse.co.kr/post/2020-05-29-wrap-primitive-type/
    https://wildeveloperetrain.tistory.com/12
    https://velog.io/@myspy/%EC%9B%90%EC%8B%9C%EA%B0%92-%ED%8F%AC%EC%9E%A5VO

    profile
    나는 허준기

    0개의 댓글