도도한 개발자
[Java] #20-1. java.lang - 특별한 자바랭, 숫자처리 본문
* 특별한 java.lang
자바의 패키지 중 유일하게 java.lang 패키지에 있는 클래스들은 import를 안해도 사용할 수 있다. java.lang과 java.util 패키지를 제외한 대부분의 java로 시작하는 패키지들은 패키지 이름만 보고도 어떤 일을 할 때 사용하는지를 알 수 있다. java.lang 패키지에서 제공하는 인터페이스, 클래스, 예외 클래스 등은 다음과 같이 분류할 수 있다.
º 언어 관련 기본
º 문자열 관련
º 기본 자료형 및 숫자 관련
º 쓰레드 관련
º 예외 관련
º 런타임 관련
각 분류에는 어떤 인터페이스, 클래스, 예외 및 에러가 있는지 알아보자.
구분 | 타입 | 항목들 |
언어 관련 기본 | 인터페이스 | Cloneable, Comparable, Iterable, Readable |
클래스 | Class, ClassLoader, Compiler, Enum, Object, Package, SecurityManager, StackTraceElement, System, Void | |
예외 및 에러 | ArrayIndexOutOfBoundsException, ArrayStoreException, ClassCastException, ClassNotFoundException, CloneNotSupportedException, EnumConstantNotPresentException, IllegalAccessException, IllegalArgumentException, IndexOutOfBoundsException, InstantiationException, NegativeArraySizeException, NoSuchFieldException, NoSuchMethodException, NullPointerException, RuntimeException, SecurityException, TypeNotPresentException, UnsupportedOperationException | |
문자열 관련 | 인터페이스 | Appendable, CharSequence |
클래스 | String, StringBuffer, StringBuilder | |
예외 및 에러 | StringIndexOutOfBoundsException | |
기본 자료형 및 숫자 관련 | 클래스 | Boolean, Byte, Character, Character.Subset, Character.UnicodeBlock, Double, Float, Integer, Long, Math, Number, Short, StrictMath |
예외 및 에러 | ArithmaticException, NumberFormatException | |
쓰레드 관련 | 인터페이스 | Runnable, Thread.UncaughtExceptionHandler |
클래스 | InheritableThreadLocal, Thread, ThreadGroup, ThreadLocal, Thread.State(Enum 타입) | |
예외 및 에러 | IllegalMonitorStateException, IllegalThreadStateException, InterruptedException | |
예외 관련 | 클래스 | Throwable |
예외 및 에러 | Exception | |
런타임 관련 | 클래스 | Process, ProcessBuilder, Runtime, RuntimePermission |
예외 및 에러 | IllegalStateException |
Bold체 항목들의 90% 이상은 알고 있자. 추가로 java.lang 패키지에 정의되어 있는 "에러" 중 가끔 볼 수 있는 에러가 있는데 바로 OutOfMemoryError(OOME)와 StackOverflowError다. OOME의 경우 메모리가 부족하여 발생하는 에러다. 자바는 가상 머신에서 메모리를 관리하지만, 프로그램을 잘못 작성하거나 설정이 제대로 되어 있지 않을 경우 이러한 에러가 발생할 수 있다.
StackOverflowError는 호출된 메소드의 깊이가 너무 깊을 때 발생한다. 자바에서 스택이라는 영역에 어떤 메소드가 어떤 메소드를 호출했는지에 대한 정보를 관리한다. 예를 들어 메소드가 자기 자신을 호출하는 재귀 메소드를 잘못 작성했다면 스택에 쌓을 수 있는 메소드 호출 정보의 한계를 넘어설 수 있다.
그리고 java.lang 패키지에는 기본 어노테이션이 선언되어 있다.
º Deprecated
º Override
º SuppressWarnings
이제 java.lang 패키지에 선언되어 있는 클래스들을 살펴보자.
* 숫자 처리 클래스
자바에서 간단한 계산을 할 때는 대부분 기본 자료형을 사용한다. 기본 자료형은 자바의 힙(Heap)이라는 영역에 저장되지 않고, 스택이라는 영역에 저장 및 관리된다. 그런데 이런 기본 자료형의 숫자를 객체로 처리해야 할 필요가 있을 수도 있다.
º Byte
º Short
º Integer
º Long
º Float
º Double
º Character
º Boolean
Character 클래스 제외하고 나머지 클래스들은 각 기본 자료형의 이름에서 첫 문자만 대문자로 바뀌었다고 보면 된다. 그러나 Character와 Boolean을 제외한 숫자를 처리하는 클래스들은 감싼 클래스라고 불리며, 모두 Number라는 abstract 클래스를 확장한다. 그리고 겉으로 보기에는 참조 자료형이지만, 기본 자료형처럼 사용할 수 있다. 왜냐하면 자바 컴파일러에서 자동으로 형 변환을 해주기 때문이다.
그리고 Character 클래스를 제외하고는 공통적인 메소드를 제공한다. parse타입이름() 메소드와 valueOf()라는 메소드다.
다음과 같이 JavaLangNumber 클래스를 만들고 숫자 타입을 테스트 할 numberTypeCheck() 메소드도 만들어 자동 형 변환이 발생하는 것을 확인해보자.
public class JavaLangNumber {
public static void main(String[] args) {
JavaLangNumber sample = new JavaLangNumber();
sample.numberTypeCheck();
}
public void numberTypeCheck() {
String value1 = "3";
String value2 = "5";
byte byte1 = Byte.parseByte(value1); // 1
byte byte2 = Byte.parseByte(value2); // 1
System.out.println(byte1 + byte2); // 2
Integer refInt1 = Integer.valueOf(value1); // 3
Integer refInt2 = Integer.valueOf(value2); // 3
System.out.println(refInt1 + refInt2 + "7"); // 4
}
}
1 : 3과 5라는 String 값을 parseByte() 메소드를 사용하여 byte로 변환하고
2 : 두 값을 더한 결과를 출력했다.
3 : valueOf() 메소드를 사용하며 Integer 타입으로 변환한 후 두 값을 더한 후
4 : "7"이라는 String을 더하여 출력했다.
이 두 메소드는 모두 static 메소드가. 따라서 따로 객체를 생성할 필요 없이 바로 사용할 수 있다. 둘 다 String과 같은 문자열을 숫자 타입으로 변환한다는 공통점이 있지만, parse타입이름() 메소드는 기본 자료형을 리턴하고, valueOf() 메소드는 참조 자료형을 리턴한다.
결과는 어떨끼?
8
87
첫 번째 결과가 byte 타입을 더한 것이니 8로 출력되는 것은 납득할 수 있다. 그러나 두 번째 결과가 87로 나온 것은 조금 의아하다. 왜냐하면 참조 자료형은 두 값을 더할 수 없는데 숫자 연산이 된 8이라는 값이 출력되고, "7"이 그 뒤에 붙었기 때문이다. 참조 자료형 중 더하기 연산이 가능한 것은 String 뿐이라고 했는데, 참조 자료형 중 Byte, Stort, Integer, Long, Float, Double 타입들은 필요시 기본 자료형처럼 사용할 수 있다. 따라서 new를 사용하여 객체를 만들지 않아도 값을 할당할 수 있다.
따라서 다음과 같이 사용해도 전혀 문제 되지 않는다.
public void numberTypeCheck2() {
Integer refInt1;
refInt1 = 100;
System.out.println(refInt1.doubleValue());
}
컴파일도, 실행도 모두 잘 된다. 그렇다면 왜 혼란스럽게 이러한 숫자를 처리하는 참조 자료형을 만들었을까?
º 매개 변수를 참조 자료형으로만 받는 메소드를 처리하기 위해서
º 제네릭과 같이 기본 자료형을 사용하지 않는 기능을 사용하기 위해서.
º MIN_VALUE(최소값)나 MAX_VALUE(최대값)와 같이 클래스에 선언된 상수 값을 사용하기 위해서
º 문자열을 숫자로, 숫자를 문자열로 쉽게 변환하고, 2, 8, 10, 16 진수 변환을 쉽게 처리하기 위해서
기본 자료형을 참조 자료형으로 만든 클래스들은 Boolean 클래스를 제외하고 모두 MIN_VALUE와 MAX_VALUE라는 상수를 갖고 있다. 해당 타입이 나타낼 수 있는 값의 범위를 확인하려면 static으로 선언된 이 상수들을 다음과 같이 사용하면 된다.
public void numberMinMaxCheack() {
System.out.println("Byte min = " + Byte.MIN_VALUE + " max = " + Byte.MAX_VALUE);
System.out.println("Short min = " + Short.MIN_VALUE + " max = " + Short.MAX_VALUE);
System.out.println("Integer min = " + Integer.MIN_VALUE + " max = " + Integer.MAX_VALUE);
System.out.println("Long min = " + Long.MIN_VALUE + " max = " + Long.MAX_VALUE);
System.out.println("Float min = " + Float.MIN_VALUE + " max = " + Float.MAX_VALUE);
System.out.println("Double min = " + Double.MIN_VALUE + " max = " + Double.MAX_VALUE);
System.out.println("Character min = " + (int)Character.MIN_VALUE
+ " max = " + (int)Character.MAX_VALUE);
}
마지막의 Character의 경우 그냥 출력할 경우char 타입으로 출력되므로 알아보기 힘들다. 따라서 int 타입으로 변환하여 그 값을 확인하도록 해놨다. 결과를 보자.
Byte min = -128 max = 127
Short min = -32768 max = 32767
Integer min = -2147483648 max = 2147483647
Long min = -9223372036854775808 max = 9223372036854775807
Float min = 1.4E-45 max = 3.4028235E38
Double min = 4.9E-324 max = 1.7976931348623157E308
Character min = 0 max = 65535
Integer 타입과 Long 타입을 읽기가 어려워 보인다. 이 값을 2진수나 16진수로 표현해서 봐보자. Integer의 최소값과 최대값을 2진수와 16진수로 나타낸 결과를 보려면, Integer에서 제공하는 toBinaryString()라는 메소드를 사용하면 된다.
public void integerMinMaxCheckBinary() {
System.out.println("Integer BINARY min = " + Integer.toBinaryString(Integer.MIN_VALUE));
System.out.println("Integer BINARY max = " + Integer.toBinaryString(Integer.MAX_VALUE));
System.out.println("Integer HEX min = " + Integer.toHexString(Integer.MIN_VALUE));
System.out.println("Integer HEX max = " + Integer.toHexString(Integer.MAX_VALUE));
}
결과는 다음과 같다.
Integer BINARY min = 10000000000000000000000000000000
Integer BINARY max = 1111111111111111111111111111111
Integer HEX min = 80000000
Integer HEX max = 7fffffff
어떤 값을 원하는 진수의 숫자로 표현하고 싶을 때에는 직접 구현하는 것보단 이렇게 숫자 클래스에서 제공되는 메소드를 사용하면 된다.
돈 계산과 같이 중요한 연산을 수행할 때, 정수형은 BigInteger, 소수형은 BigDecimal을 사용하여야 정확한 계산이 가능하다. 이 두 클래스들은 모두 java.lang.Number 클래스의 상속을 받았으며, java.math 패키지에 선언되어 있다.
'Backend > Java' 카테고리의 다른 글
[Java] #21. Generic(제네릭) (0) | 2022.04.05 |
---|---|
[Java] #20-2. java.lang - System 클래스 (0) | 2022.04.04 |
[Java] #19. 자바의 역사 (0) | 2022.04.02 |
[Java] #18-3. 중간 점검 및 실습 (0) | 2022.04.01 |
[Java] #18-2. 기본 문법 정리(2) (0) | 2022.03.31 |