Wrapper Class란

hyyyynjn·2021년 3월 21일
2

자바 스터디

목록 보기
4/15
post-thumbnail
  1. Wrapper Class란 무엇이고, Wrapping을 함으로써 얻는 이점과 일급 콜랙션에 대한 사용 예시를 들며 설명하기

Wrapper Class란

  • 자바 API 클래스중 하나이다.
  • 자바의 자료형은 primitive type(기본 타입)reference type(참조 타입)으로 나누어진다.
    • 기본 타입 : byte, short, char, int, long, float, double, boolean
    • 참조 타입 : class, interface ..
  • 8개의 기본 타입에 해당하는 데이터를 객체로 표현하기 위해 포장해 주는 클래스가 바로 wrapper class(래퍼 클래스)이다.
    • 예를 들어, 메소드의 파라미터로 객체 타입만이 요구될 경우
      • 기본 타입의 데이터를 그대로 사용할 수 도 있지만 (AutoBoxing을 통해 가능해진다.)
      • 기본 타입의 데이터를 먼저 객체로 변환후 작업을 수행해야한다.
    • 기본 타입은 값을 갖는 객체인 포장 객체를 생성할 수 있다. (기본 타입의 값을 내부에 두고 포장하기때문에 '포장 객체'라 칭한다.)
      • wrapper class는 각 타입에 해당하는 데이터를 파라미터로 전달받아, 해당 값을 가지는 객체로 만들어준다.
    • wrapper class로 감싸고 있는 기본 타입 값은 외부에서 변경할 수 없다.
      • 변경하기 위해서 새로운 포장객체를 만들어야 한다.

Wrapper Class 종류

Wrapper Class 구조

  • wrapper class들은 모두 java.lang패키지에 포함되어 제공된다.
  • Object 클래스 : 모든 wrapper class의 부모 클래스
  • Number 클래스 : 내부적으로 숫자를 다루는 wrapper class들의 부모 클래스

Boxing & UnBoxing

  • wrapper class 인스턴스에 저장된 값을 변경할 수 없다. (산술 연산을 위한 클래스가 아니기 때문이다.)
  • Boxing : 기본 타입의 데이터를 -> wrapper class의 인스턴스로 변환하는 과정
    • Integer num = new Integer(1);
  • UnBoxing : wrapper class의 인스턴스에 저장된 을 -> 기본 타입의 데이터로 꺼내는 과정
    • int n = num.intValue();

AutoBoxing & AutoUnBoxing

  • JDK 1.5부터 boxing,unboxing이 필요한 상황에서 자바 컴파일러가 이를 자동으로 처리해준다.
  • AutoBoxing : 자동화된 Boxing
    • Integer num1 = 1;
  • AutoUnBoxing : 자동회된 UnBoxing
    • int n1 = num1;

예시(Boxing & UnBoxing, AutoBoxing & AutoUnBoxing)

Integer num = new Integer(17);  // Boxing
int n = num.intValue(); // UnBoxing

Character ch = 'X'; // AutoBoxing : Character ch = new Character('X'); 
char c = ch; // AutoUnBoxing : char c = ch.charValue();  

Wrapper Class 비교연산 (==, equals)

 Integer num = new Integer(10); //래퍼 클래스1
 Integer num2 = new Integer(10); //래퍼 클래스2
 int i = 10; //기본타입
		 
 System.out.println("래퍼클래스 == 기본타입 : "+(num == i)); //true
 System.out.println("래퍼클래스.equals(기본타입) : "+num.equals(i)); //true
 System.out.println("래퍼클래스 == 래퍼클래스 : "+(num == num2)); //false
 System.out.println("래퍼클래스.equals(래퍼클래스) : "+num.equals(num2)); //true
  • wrapper class의 비교연산은 AutoUnBoxing에 가능하다.
    • 인스턴스에 저장된 값에 대한 동등 여부 판단은
      • 동등 연산자 ==으로 불가능하다. -> wrapper class 객체의 주소값을 비교한다.
      • equals() 메소드를 통해 가능하다.

Wrapping의 장점

  • 기본 자료형을 클래스화 하여 클래스의 장점을 활용할 수 있게 된다.
// : 어느 한 문자가 숫자인지 아닌지 판단하는 메소드 
System.out.println(Character.isDigit('A') ? "숫자다" : "숫자가 아니다"); 
System.out.println(Character.isDigit('2') ? "숫자다" : "숫자가 아니다"); 
System.out.println(Character.isDigit(65) ? "숫자다" : "숫자가 아니다"); 
System.out.println(Character.isDigit('가') ? "숫자다" : "숫자가 아니다"); 
System.out.println(Character.isDigit(44032) ? "숫자다" : "숫자가 아니다");


// : 문자인지 아닌지(언어(한글,한문,영어,일본어 등)에 해당하는 것만)판단하는 메소드 
System.out.println("[isLetter 메소드]"); 
System.out.println(Character.isLetter('가'));// true 
System.out.println(Character.isLetter('A'));// true 
System.out.println(Character.isLetter('a'));// true 
System.out.println(Character.isLetter('家'));// true 
System.out.println(Character.isLetter('9'));// false 
System.out.println(Character.isLetter('@'));// false


// : 공백인지 아닌지 판단하는 메소드 System.out.println("[isWhitespace 메소드]"); 
System.out.println(Character.isWhitespace('가'));// false 
System.out.println((int) ' ');// true 
System.out.println(Character.isWhitespace(32));// 공백의 아스키 코드값 
System.out.println(Character.isWhitespace(' '));// true


// : 대문자를 소문자로, 소문자를 대문자로 System.out.println("[toUpperCase/toLowerCase 메소드]"); 
System.out.println(Character.toUpperCase('A')); 
System.out.println(Character.toUpperCase('a')); 
System.out.println(Character.toLowerCase('A')); 
System.out.println(Character.toLowerCase('a')); 
System.out.println(Character.toUpperCase('가')); 
System.out.println(Character.toLowerCase('가')); 
System.out.println(Character.toUpperCase('9'));


// 문자열 "TrUe"를 논리값 true로 String boolString = "TrUe"; 
System.out.println(Boolean.parseBoolean(boolString));// "TrUe" -> true
System.out.println(Boolean.parseBoolean(boolString) && false);// "TrUe" -> false 
System.out.println(Boolean.valueOf(boolString) && false);// "TrUe" -> false

일급 컬랙션

  • 콜렉션을 wrapping 할 때, 그 외의 다른 멤버 변수가 없는 상태를 일급 컬랙션이라고 한다.
    • 다시 말해, Collection들을 한번 Wrapping 한 컬렉션이다.

예시

  • Car라는 객체가 있다.
public class Car {
    private int position;
    public void move(MovingStrategy movingStrategy) {
        if (movingStrategy.isMove()) {
            position++;
        }
    }
    public int getPosition() {
        return position;
    }
}
  • Car라는 객체의 인스턴스를 3개 생성하는 경우
    • 이 인스턴스들을 모두 함께 관리해야할 때, 일급 컬렉션인 Cars 클래스를 만들면 용이하다.
    • public Cars(List<Car> cars)
Car aCar = new Car() // Car 인스턴스 1
Car bCar = new Car() // Car 인스턴스 2
Car cCar = new Car() // Car 인스턴스 3
public class Cars {
    private List<Car> cars;
    public Cars(List<Car> cars) {
        this.cars = this.cars;
    }
    public List<Car> getCars() {
        return cars;
    }
}

콜렉션을 wrapping 할 때 가지는 이점

1. 하나의 인스턴스에서 비지니스 로직을 관리할 수 있다.

일급 컬랙션을 사용하지 않을 경우

  • 자동차의 현재 위치가 3보다 큰 자동차를 가져오려 할 경우,
    • 일급 컬렉션 Cars가 없다면 하나씩 가져오거나, List로 묶어서 처리해야한다.
      • 중간에 빼먹는 실수를 할 수 있고, 비지니스 로직도 외부에서 관리하게 된다.
@Test
public void _3보다_큰_자동차가져오기() {
    Car aCar = new Car(); // Car 인스턴스 1
    Car bCar = new Car(); // Car 인스턴스 2
    Car cCar = new Car(); // Car 인스턴스 3

    List<Car> cars = new ArrayList<>();
    cars.add(aCar);
    cars.add(bCar);
    cars.add(cCar);

    cars.stream()
            .filter(car -> car.getPosition() > 3)
            .forEach(System.out::println);
}

일급 컬랙션을 사용할 경우

  • public List<Car> getCarsOverPosition(int position) 메소드를 정의하여 비지니스 로직을 내부에서(Cars 도메인에서) 관리할 수 있게 된다.
    • 다시 말해, 비지니스에 종속적인 자료구조를 만들 수 있게 된다.
public class Cars {

    private List<Car> cars;

    public Cars(List<Car> cars) {
        this.cars = cars;
    }

    public List<Car> getCars() {
        return cars;
    }
    
    public List<Car> getCarsOverPosition(int position) {
        return cars.stream()
                .filter(car -> car.getPosition() > position)
                .collect(Collectors.toList());
    }
}
  1. Collection의 불변성 보장
  2. 상태와 행위를 한 곳에서 관리
  3. 이름이 있는 컬랙션

0개의 댓글