원시값 포장이란?

허준기·2023년 5월 5일
0

자바

목록 보기
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클래스에는 쥐가 가진 동작들을 넣어야 하는데 nameage를 관리할 메소드까지 넣어야해서 클래스가 길어지게 된다.

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

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 이 있다. 그냥 원시타입에 대문자만 붙인 느낌이다. IntegerCharacter 제외!!

    VO(Value Object)란?

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

    equals()hashcode() 를 오버라이딩 → 재정의해야함!
    VO 관련해서 찾다보니 DTOEntity라는 개념이 나온다 나중에 조사해서 글을 써보자
    그리고 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개의 댓글