Search
Duplicate
📒

[Java Study] 02-3. 래퍼 클래스

상태
완료
수업
Java Study
주제
4 more properties
참고

기본형의 한계

기본형은 객체가 아니다

NOTE
자바에서 기본형 데이터는 효율성과 성능을 위해 객체로 표현되지 않아 객체지향 프로그래밍의 특징을 활용하지 못하는 한계를 가집니다.
public static void main(String[] args) { int value = 10; int i1 = compareTo(value, 5); int i2 = compareTo(value, 11); int i3 = compareTo(value, 10); System.out.println("i1 = " + i1); System.out.println("i2 = " + i2); System.out.println("i3 = " + i3); } // 비교함수 public static int compareTo(int value, int targer) { if (value < targer) { return -1; } else if (value > targer) { return 1; }else{ return 0; } }
Java
복사
value는 비교 대상 값을 compareTo()라는 외부 메서드를 통해서 비교합니다.
만약 value가 객체라면 value 객체 스스로 자기 자신의 값과 다른 값을 비교하는 메서드를 만드는 것이 더 유용할 것입니다.
public class MyInteger { private final int value; public MyInteger(int value) { this.value = value; } public int getValue() { return value; } public int compareTo(int target) { if (value < target) { return -1; } else if (value > target) { return 1; } else { return 0; } } @Override public String toString() { return String.valueOf(value); //숫자를 문자로 변경 } }
Java
복사
public static void main(String[] args) { MyInteger myInteger = new MyInteger(10); int i1 = myInteger.compareTo(5); int i2 = myInteger.compareTo(11); int i3 = myInteger.compareTo(10); System.out.println("i1 = " + i1); System.out.println("i2 = " + i2); System.out.println("i3 = " + i3); }
Java
복사
객체의 메서드사용

기본형과 Null

NOTE
자바 기본타입은 Null 값을 가질 수 없이 항상 초기화되어야 합니다. 이는 아직 값이 초기화되지 않은 상태를 표현하는데 제약을 만들 수 있습니다.
public static void main(String[] args) { int[] intArr = {-1, 0, 1, 2, 3}; System.out.println(findValue(intArr, -1)); // -1 System.out.println(findValue(intArr, 0)); System.out.println(findValue(intArr, 1)); System.out.println(findValue(intArr, 100)); // -1 } private static int findValue(int[] intArr, int target) { for (int value : intArr) { if (value == target) { return value; } } return -1; // 데이터가 없다는 의미인 -1 }
Java
복사
데이터가 없다면 -1 반환
-1이 약속된 값이라고 하더라도, 처음 보는사람은 -1이 있어서 반환한것인지 아니면 값이 없어서 -1을 반환한것인지 명확하지가 않습니다.
객체의 경우에는 null이라는 명확한 값이 존재합니다.
public static void main(String[] args) { MyInteger[] intArr = {new MyInteger(-1), new MyInteger(0), new MyInteger(1)}; System.out.println(findValue(intArr, -1)); System.out.println(findValue(intArr, 0)); System.out.println(findValue(intArr, 1)); System.out.println(findValue(intArr, 100)); // null } private static MyInteger findValue(MyInteger[] intArr, int target) { for (MyInteger myInteger : intArr) { if (myInteger.getValue() == target) { return myInteger; } } return null; }
Java
복사
데이터가 없다면 Null 반환

래퍼 클래스

NOTE
자바는 위에서 다룬 기본형의 한계를 극복하기 위해서 기본형에 대한 객체를 제공하며 이를 래퍼 클래스라고 합니다.
public static void main(String[] args) { // 래퍼 클래스 생성(박싱) Integer newInteger = new Integer(10); //미래에 삭제 예정, 대신에 valueOf() 사용 Integer integerObj = Integer.valueOf(10); //-128 ~ 127 자주 사용하는 숫자 값재사용, 불변 Integer autoBoxing = 10; // 오토박싱 Long longObj = Long.valueOf(100); Double doubleObj = Double.valueOf(10.5); System.out.println("newInteger = " + newInteger); System.out.println("integerObj = " + integerObj); System.out.println("longObj = " + longObj); System.out.println("doubleObj = " + doubleObj); System.out.println("내부 값 읽기"); // 래퍼 클래스 -> 기본형(언박싱) int intValue = integerObj.intValue(); Integer intValue2 = intValue; // 오토 언박싱 System.out.println("intValue = " + intValue); long longValue = longObj.longValue(); System.out.println("longObj = " + longValue); System.out.println("비교"); System.out.println("==: " + (newInteger == integerObj)); System.out.println("equals: " + newInteger.equals(integerObj)); }
Java
복사
래퍼 클래스 예제코드
new Integer(10)과 같이 생성자를 통해 만들지말고 valueOf()를 통해 생성하는것을 권장합니다.
valueOf()에서도 new Integer()를 동일하게 사용하지만, 성능 최적화 기능이 존재합니다.
자바 1.5부터는 박싱-언박싱이 자동으로 이루어지도록 컴파일러가 개발자 대신 valueOf(), xxxValue()등의 코드를 추가해줄 수 있도록 지원해줍니다.

주요 메서드와 성능

NOTE
래퍼 클래스는 기본형 데이터를 객체로 사용할 수 있도록 돕고, 다양한 유틸리티 메서드를 제공하여 객체지향 코딩을 지원합니다. 그러나 박싱-언박싱 과정에서 오버헤드가 발생할 수 있습니다.
public static void main(String[] args) { Integer i1 = Integer.valueOf(10); // 숫자를 래퍼 객체로 반환 Integer i2 = Integer.valueOf("10"); // 문자열을 래퍼 객체로 반환 int intValue = Integer.parseInt("10"); // 문자열 전용, 기본형 반환 // 비교 - compareTo int compareResult = i1.compareTo(20); System.out.println("compareResult = " + compareResult); // 산술 연산 - sum, min, max System.out.println("sum: " + Integer.sum(10, 20)); System.out.println("min: " + Integer.min(10, 20)); System.out.println("max: " + Integer.max(10, 20)); }
Java
복사
parseInt()는 기본형을 반환하고, valueOf()는 래퍼 타입을 반환합니다. 따라서 원하는 타입에 맞는 메서드를 선택하여 사용하면 됩니다.
public static void main(String[] args) { int iterations = 1_000_000_000; long startTime, endTime; // 기본 타입 경우 long sumPrimitive = 0; startTime = System.currentTimeMillis(); for (long i = 0; i < iterations; i++) { sumPrimitive += i; } endTime = System.currentTimeMillis(); System.out.println("sumPrimitive = " + sumPrimitive); System.out.println("기본 자료형 long 실행 시간 " + (endTime - startTime) + "ms"); // 래퍼 클래스 경우 Long sumWrapper = Long.valueOf(0); startTime = System.currentTimeMillis(); for (long i = 0; i < iterations; i++) { sumWrapper += i; // 오토박싱이 수없이 발생함! } endTime = System.currentTimeMillis(); System.out.println("sumWrapper = " + sumWrapper); System.out.println("래퍼 클래스 Long 실행 시간 " + (endTime - startTime) + "ms"); }
Java
복사
기본타입과 래퍼클래스의 성능
위의 코드에서 래퍼 클래스를 이용해 기본형 long을 더하는 경우, 오토박싱으로 발생하는 오버헤드 때문에 일반적으로 기본 타입이 약 1초 더 빠르게 처리됩니다.
저의 경우, 10억 번의 연산에서 래퍼 클래스가 더 빠르게 처리되었습니다. 자바 버전과 컴퓨터 성능에 따라, 이제는 거의 의미 없는 성능 최적화 단계에 도달한 것 같습니다.
이상하게 기본형이 느리게 나온다..
그러나 10억 번의 연산에서 1초의 차이는 실질적으로 큰 의미를 가지지 않습니다. 최적화가 중요한 경우에는 고려해야 하지만, 일반적으로 유지보수 측면에서 래퍼 클래스가 더 유용하다면 래퍼 클래스를 사용하는 것이 바람직합니다.
대부분의 웹 애플리케이션에서 최적화는 메모리에서의 연산을 줄이는 것보다 네트워크 호출을 줄이는 것이 더 효과적인 경우가 많습니다.