System
public final class System {
private static native void registerNatives();
static {
registerNatives();
}
private System() {
}
public static final InputStream in = null;
public static final PrintStream out = null;
public static final PrintStream err = null;
// Initial values of System.in and System.err, set in initPhase1().
private static @Stable InputStream initialIn;
private static @Stable PrintStream initialErr;
// indicates if a security manager is possible
private static final int NEVER = 1;
private static final int MAYBE = 2;
private static @Stable int allowSecurityManager;
// current security manager
@SuppressWarnings("removal")
private static volatile SecurityManager security;
// read by VM
// `sun.jnu.encoding` if it is not supported. Otherwise null.
// It is initialized in `initPhase1()` before any charset providers
// are initialized. private static String notSupportedJnuEncoding;
기본 개요
- 패키지:
java.lang
- 선언:
public final class System
- 특징:
final로 선언되어 상속 불가능
- 생성자가
private이므로 인스턴스 생성 불가능
- 모든 메서드와 필드는
static!
- JVM 운영환경(standart input/output, properties, security, GC 등)을 다루는 중앙 유틸리티 클래스
System은 JVM 레벨에서 제공되는 전역 자원 접근 창구이다.
주요 정적 필드
System.in: 표준 입력 스트림(InputStream)
System.out: 표준 출력 스트림(PrintStream)
System.err: 표준 에러 출력 스트림(PrintStream)
주요 정적 메서드
- 시간 관련
currentTimeMillis() : UTC 기준 현재 시각(밀리초 단위)
nanoTime() : 상대적 시간 측정용(나노초 단위, 벤치마크 등에서 사용)
- 환경 변수 및 시스템 속성
getProperty(String key) : 시스템 속성 조회
(예: "java.version", "os.name")
setProperty(String key, String value) : 속성 설정
getProperties() : 모든 속성 Properties 객체로 반환
getenv(String name) : 환경 변수 조회
getenv() : 모든 환경 변수 Map 반환
- 입출력 스트림 관리
setIn(InputStream in)
setOut(PrintStream out)
setErr(PrintStream err)
→ 표준 입출력 스트림 교체 가능 (테스트 코드에서 자주 활용)
- GC, 종료
gc() : GC 실행 요청
runFinalization() : 종료될 객체의 finalizer 실행 요청
exit(int status) : JVM 종료
halt(int status) : 강제 종료 (보안 관리자 무시)
- 배열, 객체 관련
arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
→ 네이티브 메서드, 배열 복사
identityHashCode(Object x)
→ hashCode() 오버라이딩 무시하고 원래 객체 해시코드 반환
내부 구현 특징
- 네이티브 메서드 다수 포함:
arraycopy, currentTimeMillis, nanoTime, identityHashCode, gc, mapLibraryName 등은 네이티브로 구현된다.
- JVM 부트스트랩 과정에서 초기화:
System 클래스는 VM 클래스와 협력하여 초기화 시점에 표준 스트림과 시스템 속성들을 설정한다.
- 안전성: 보안 관리자가 활성화되어 있다면, 특정 메서드 호출(
exit, setSecurityManager 등)은 SecurityException 발생 가능하다.
설계 관점
System은 사실상 싱글톤 패턴(전역 접근점)의 극단적인 형태 : 인스턴스 없음, 모든 기능이 static
final + private 생성자 -> 불변적이며 확장 불가
- 유틸리티 클래스이자, JVM과 OS 레벨의 브릿지 클래스예시 코드
public class SystemExample {
public static void main(String[] args) {
// 시간
long now = System.currentTimeMillis();
System.out.println("현재 시간(ms): " + now);
// 환경 변수
String path = System.getenv("PATH");
System.out.println("PATH 환경변수: " + path);
// 시스템 속성
String javaVersion = System.getProperty("java.version");
System.out.println("Java 버전: " + javaVersion);
// 배열 복사
int[] src = {1, 2, 3, 4, 5};
int[] dest = new int[5];
System.arraycopy(src, 0, dest, 0, src.length);
System.out.println("복사된 배열: " + java.util.Arrays.toString(dest));
// 종료 (status 0은 정상 종료)
// System.exit(0);
}
}
System 클래스는 불변적이며 상태가 없는 final 유틸리티 클래스
- JVM과 OS 자원(시간, 환경 변수, 속성, 표준 입출력, GC, 종료 등)을 관리하는 전역 접근 API
Math
public final class Math {
private Math() {}
public static final double E = 2.718281828459045;
public static final double PI = 3.141592653589793;
public static final double TAU = 2.0 * PI;
private static final double DEGREES_TO_RADIANS = 0.017453292519943295;
private static final double RADIANS_TO_DEGREES = 57.29577951308232;
기본 개요
- 패키지:
java.lang
- 선언:
public final class Math
- 특징:
final 클래스 -> 상속 불가
- 생성자가
private -> 인스턴스 생성 불가
- 모든 메서드와 필드는
static
- 수학 연산(삼각함수, 지수, 로그, 제곱근, 반올림, 난수 생성 등)을 위한 유틸리티 클래스
Math는 순수 함수 집합처럼 쓰이는 클래스이다.
주요 필드
public static final double E = 2.718281828459045; // 자연로그 밑
public static final double PI = 3.141592653589793; // 원주율
주요 메서드 분류
- 절대값, 부호 관련
abs(int a), abs(long a), abs(float a), abs(double a)
signum(double a), signum(float a) → 양수/음수/0 구분
- 올림/내림/반올림
ceil(double a) : 올림
floor(double a) : 내림
round(double a) : 반올림 → long 반환
rint(double a) : 가장 가까운 정수(double)
- 최대/최소
max(x, y), min(x, y) (int, long, float, double 오버로드)
- 제곱, 제곱근, 거듭제곱
pow(double a, double b)
sqrt(double a)
cbrt(double a) : 세제곱근
hypot(double x, double y) : √(x² + y²)
- 로그, 지수
exp(double a) : e^a
log(double a) : 자연로그
log10(double a) : log10
expm1(double a) : e^a - 1
log1p(double a) : log(1+a)
- 삼각함수
sin, cos, tan
asin, acos, atan
atan2(y, x)
- 기타
random() : 0.0 이상 1.0 미만의 난수 반환 (내부적으로 Random 사용)
toRadians(double angdeg)
toDegrees(double angrad)
내부 구현 특징
- 네이티브 메서드 포함:
많은 메서드(sin, cos, sqrt, log, exp, …)가 StrictMath 또는 OS 네이티브 라이브러리를 호출함.
- 성능 최적화:
JIT 컴파일러가 핫스팟 메서드(abs, max, min, pow 등)를 인라이닝하여 성능을 높임.
StrictMath와의 관계:
StrictMath는 항상 동일한 결과(플랫폼 독립적 보장)
Math는 성능 최적화를 위해 하드웨어/FPU/OS 라이브러리 함수를 사용할 수 있음
설계적 의미
Math는 상태 없는 불변 유틸리티 클래스
- 사실상 싱글턴 패턴의 극단 형태(인스턴스 없음, 확장 불가, 전역 접근만 가능)
- 난수 생성(
random())만 내부적으로 상태(Random 인스턴스)를 갖고 변하기도 하지만 그 상태는 Math 클래스 외부에 노출되지 않는다. -> 불변성을 유지한다.
불변성
Math는 인스턴스를 만들 수 없고 상태도 없으며 모든 메서드가 static이므로 사실상 불변적이다.
- 엄밀한 의미의 "불변 클래스"라기 보다는 상태 없는 final 유틸리티 클래스로 보는 것이 맞다.
정리
Math는 final + private 생성자로 만들어진 순수 유틸리티 클래스
- 모든 메서드가
static -> 인스턴스가 필요없다.
- 수학 상수와 연산을 효율적이고 빠르게 제공
- 불변성 개념을 충족하며 성격 상 immutable utility class로 보는 것이 맞다.
Number
public abstract class Number implements java.io.Serializable {
public Number() {super();}
public abstract int intValue();
public abstract long longValue();
public abstract float floatValue();
public abstract double doubleValue();
public byte byteValue() {
return (byte)intValue();
}
public short shortValue() {
return (short)intValue();
}
@java.io.Serial
private static final long serialVersionUID = -8742448824652078965L;
}
기본 개요
- 패키지:
java.lang
- 선언:
public abstract class Number implements java.io.Serializable
- 특징:
abstract 클래스 -> 직접 인스턴스화 불가능
- 여러 숫자 타입 클래스(Byte, Short, Integer, Long, Float, Double, BigInteger, BigDecimal 등)의 추상 부모 클래스
- 직렬화 가능(Serializable
주요 메서드
- 추상 메서드 => 하위 클래스에서 구현 필요
int intValue()
long longValue()
float floatValue()
- `double doubleValue()
- 일반 메서드 => 기본 구현 제공
byte byteValue() -> intValue 결과를 byte로 캐스팅
short shortValue() -> intValue 결과를 short로 캐스팅
설계적 의미
Number 클래스는 타입 계층의 다형성을 보장하는 뼈대이다. -> List<Number>에는 Integer, Double, BigDecimal을 다 저장할 수 있다.
- 그러나 제네릭스와 오토박싱/언박싱이 등장하면서, 실무에서 직접
Number를 다루는 경우는 적고, 보통 Integer, Double 같은 구체 클래스나 Number를 상속받은 특수 타입을 사용한다.
- 불변성:
- JDK 기본 래퍼 클래스는 모두 불변 클래스
- 따라서
Number의 하위 클래스도 불변성을 갖도록 하는 것이 일반적
정리
Number는 추상 클래스이자 숫자 계열 타입의 공통 조상
- 여섯 가지 기본 변환 메서드를 정의(
intValue, longValue, floatValue, doubleValue, byteValue, shortValue)
- 실체 클래스(
Integer, Double, BigDecimal 등)는 이를 구현
Number의 설계 목적은 다형성 확보 + 타입 변환 공통 API 제공
- 실제 코딩에서는
Number 자체보다는 구체 래퍼 클래스들을 직접 사용하는 경우가 많다.
Wrapper 클래스
- 자바는 기본 타입(
byte, char, short, int, long, double, boolean)의 값을 갖는 객체를 생성할 수 있는데 이런 객체를 포장 객체, 즉 Wrapper 객체라고 한다.
- 8개의 기본형을 객체로 다뤄야할 때 사용하는 클래스이다.
- 포장 객체(Wrapper 객체)의 특징은 객체가 포장하고 있는 기본 타입의 값은 외부에서 변경할 수 없다는 점이다.
- 만약 내부의 값을 변경하고 싶다면 새로운 포장 객체를 만들어야 한다.
- 즉, Wrapper 객체는 불변 객체라는 것이다.
- Wrapper 클래스는 모두
java.lang 패키지에 속한다.
| 기본형 |
래퍼 클래스 |
| byte |
Byte |
| char |
Character |
| short |
Short |
| int |
Integer |
| long |
Long |
| float |
Float |
| double |
Double |
| boolean |
Boolean |
박싱과 언박싱
- 기본 타입의 값을 포장 객체로 만드는 과정을 박싱(boxing)이라 한다.
- 반대로 포장 객체에서 기본 타입의 값을 얻어내는 과정을 언박싱(unboxing)이라고 한다.
- 래퍼 클래스의 생성자로 박싱: 매개값으로 기본 타입의 값 또는 문자열을 전달
| 기본 타입의 값을 전달 |
문자열을 전달 |
| Byte obj = new Byte(10); |
Byte obj = new Byte("10"); |
| Character obj = new Character('가'); |
없음 |
| Short obj = new Short(100); |
Short obj = new Short("100"); |
| Integer obj = new Integer(1000); |
Integer obj = new Integer("1000"); |
| Long obj = new Long(10000); |
Long obj = new Long("10000"); |
| Float obj = new Float(2.5F); |
Float obj = new Float("2.5F"); |
| Double obj = new Double(3.5); |
Double obj = new Double("3.5"); |
| Boolean obj = new Boolean(true); |
Boolean obj = new Boolean("true"); |
|
|
- 생성자가 아닌 정적 메서드
valueOf 로 박싱
// Integer.java
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Integer obj = Integer.valueOf(1000);
Integer obj = Integer.valueOf("1000");
기본 타입 + Value() 메서드로 언박싱: 기본 타입의 값 얻어내기
| 기본 타입의 값을 이용 |
| byte num = obj.byteValue(); |
| char ch = obj.charValue(); |
| short num = obj.shortValue(); |
| int num = obj.intValue(); |
| long num = obj.longValue(); |
| float num = obj.floatValue(); |
| double num = obj.floatValue(); |
| boolean bool = obj.booleanValue(); |
public class BoxingUnBoxingExample {
public static void main(String[] args) {
// 박싱
Integer obj1 = new Integer(100);
Integer obj2 = new Integer("200");
Integer obj3 = Integer.valueOf("300");
// 언박싱
int value1 = obj1.intValue();
int value2 = obj2.intValue();
int value3 = obj3.intValue();
System.out.println(value1); // 100
System.out.println(value2); // 200
System.out.println(value3); // 300
}
}
자동 박싱과 자동 언박싱
- 래퍼 클래스 타입에 기본 타입의 값이 대입될 경우에 자동 박싱
- 자동 박싱은 컴파일 시 래퍼의
valueOf(...) 정적 메서드 호출로 변환된다.
Integer obj = 100; // 자동 박싱 -> 컴파일 타임에 Integer.valueOf(100)으로 변환
// Integer.java
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
- 자동 언박싱은 인스턴스의
xxxValue() 메서드 호출로 변환된다.
- 기본 타입의 변수에 래퍼 객체가 대입되는 경우에 자동 언박싱
Integer obj = new Integer(200); // 박싱
int value = obj; // 자동 언박싱 -> 컴파일 타임에 obj.intValue()로 변환
- 기본 타입의 값에 래퍼 객체가 연산되는 경우에도 자동 언박싱
Integer obj = new Integer(300); // 박싱
int value = obj + 100; // + 연산 시 자동 언박싱 -> 컴파일 타임에 obj.intValue()로 변환
문자열을 기본 타입 값으로 변환
- 래퍼 클래스는 문자열을 기본 타입의 값으로 변환할 때에도 많이 사용한다.
parse+기본 타입 이름 형식의 정적 메서드는 문자열을 매개값으로 전달받아 기본 타입의 값으로 변환
| 기본 타입의 값으로 변환 |
| byte num = Byte.parseByte("10"); |
| short num = Short.parseShort("100"); |
| int num = Integer.parseInt("1000"); |
| long num = Long.paseLong("10000"); |
| float num = Float.parseFloat("2.5F"); |
| double num = Double.parseDouble("3.5"); |
| boolean bool = Boolean.parseBoolean("true'); |
포장값 비교: 박싱된 값 비교
- 포장 객체는 내부의 값을 비교하기 위해 == 와 != 연산자를 사용하지 않는 것이 좋다.
- == 와 != 연산자는 내부의 값을 비교하는 것이 아니라 포장 객체의 참조를 비교하기 때문이다.
Integer obj1 = 300; // 자동 박싱 -> 컴파일 타임에 Integer.valueOf(300)으로 변환
Integer obj2 = 300; // 자동 박싱 -> 컴파일 타임에 Integer.valueOf(300)으로 변환
System.out.println(obj1 == obj2); // false
- 다만 래퍼 클래스 별로
valueOf 메서드를 이용하여 기본 타입 값을 박싱하는 경우 특정 범위의 기본 타입 값은 캐싱되기 때문에 valueOf 메서드를 이용하여 박싱한 기본 타입 값이 그 특정 범위 안의 값이라면 == 와 != 연산자로 내부의 값을 바로 비교할 수 있다.
- 언제 캐시가 쓰이나?
- 정적 팩토리:
Integer.valueOf(int) 직접 호출 -> 캐시 적용
- 문자열 변환:
Integer.valueOf("42") -> 내부적으로 parseInt 후 valueOf(int) 호출 -> 캐시 적용
- 생성자:
new Integer(42)는 항상 새 객체 생성 => 캐시 미사용
// Integer.java
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
private static final class IntegerCache {
static final int low = -128;
static final int high;
@Stable
static final Integer[] cache;
static Integer[] archivedCache;
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
h = Math.max(parseInt(integerCacheHighPropValue), 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
// Load IntegerCache.archivedCache from archive, if possible
CDS.initializeFromArchive(IntegerCache.class);
int size = (high - low) + 1;
// Use the archived cache if it exists and is large enough
if (archivedCache == null || size > archivedCache.length) {
Integer[] c = new Integer[size];
int j = low;
for(int i = 0; i < c.length; i++) {
c[i] = new Integer(j++);
}
archivedCache = c;
}
cache = archivedCache;
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
- 그 외의 경우에는 언박싱한 값을 비교해야 하며 포장 객체에 정확히 어떤 값이 저장될 지 모르는 상황이라면 == 와 != 연산자는 사용하지 않고 직접 내부 값을 언박싱해서 비교하거나
equals 메서드를 이용해서 내부 값을 비교하는 것이 좋다.
- 기본 타입 별 캐싱되는 값의 범위:
Float/Double은 캐싱 미사용
Integer 클래스 캐싱 범위 튜닝
- 확장 가능: JVM 시작 시 시스템 프로퍼티로
Djava.lang.Integer.IntegerCache.high=<값>을 전달하면 상한을 127 이상으로 넓힐 수 있다.
- 하한 -128은 고정
- 캐시는 클래스 초기화 시 배열 한 번 만들어 채워두며 스레드 안전
| 래퍼 클래스 |
캐싱되는 값의 범위 |
| Boolean |
true, false |
| Character |
\u0000\u007f(0127) |
| Byte, Short, Integer, Long |
-128 ~ 127 |
- equals 메서드: 내부의 값을 비교하도록 재정의되어 있다.
// Integer.java
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
// Integer.java
public int hashCode() {
return Integer.hashCode(value);
}
public static int hashCode(int value) {
return value;
}
public class ValueCompareExample {
public static void main(String[] args) {
System.out.println("[-128~127 초과값일 경우]");
Integer obj1 = 300;
Integer obj2 = 300;
System.out.println("==결과: " + (obj1==obj2)); // false
System.out.println("언박싱 후 ==결과: "
+ (obj1.intValue()==obj2.intValue()); // true
System.out.println("equals() 결과: "
+ (obj1.equals(obj2))); // true
System.out.println();
System.out.println("[-128~127 범위값일 경우]");
Integer obj1 = 10;
Integer obj2 = 10;
System.out.println("==결과: " + (obj1==obj2)); // true
System.out.println("언박싱 후 ==결과: "
+ (obj1.intValue()==obj2.intValue()); // true
System.out.println("equals() 결과: "
+ (obj1.equals(obj2))); // true
}
}
BigInteger와 BigDecimal
공통점
- 패키지 :
java.math
- 특징:
final 클래스 -> 상속 불가
immutable(불변 객체) -> 값이 변하지 않는다. 새로운 연산 결과는 항상 새 인스턴스 반환
Serializable, Comparable 인터페이스 구현
- 정밀한 수치 연산 지원 (정수/실수)
Number 클래스의 하위 클래스 -> intValue(), longValue(), doubleValue() 등 변환 메서드 제공
- 둘 다 기본 타입으로는 다룰 수 없는 큰 수치나 정밀도를 다룰 때 사용된다.
BigInteger
- 개요
- 임의 정밀도의 정수 표현 클래스
int, long 범위를 넘어서는 정수도 표현 가능(메모리가 허용하는 한 무한대 크기 지원)
- 생성 방법
BigInteger big1 = new BigInteger("12345678901234567890");
BigInteger big2 = BigInteger.valueOf(42L);
- 주요 메서드
- 사칙연산:
add, subtract, multiply, divide, remainder
- 거듭제곱:
pow(int exponent)
- 최대공약수:
gcd(BigInteger val)
- 소수 관련:
isProbablePrime(int certainty), nextProbablePrime()
- 비트 연산:
and, or, xor, shiftLeft, shiftRight
- 예시
BigInteger a = new BigInteger("12345678901234567890");
BigInteger b = new BigInteger("98765432109876543210");
BigInteger sum = a.add(b);
System.out.println("합: " + sum);
BigDecimal
- 개요
- 임의 정밀도의 소수(부동소수점) 표현 클래스
float, double 은 부동소수점 오차 문제가 있지만, BigDecimal 은 오차 없이 정밀한 계산 가능
- 금융, 과학 계산 등 정밀도가 중요한 연산에 필수
- 생성 방법:
new BigDecimal(double) 사용 시 부동소수점 표현 오류가 그대로 반영되므로 문자열 생성자 권장
BigDecimal d1 = new BigDecimal("0.1"); // 문자열 권장(double 생성자 X)
BigDecimal d2 = BigDecimal.valueOf(0.1); // 내부적으로는 String 변환
- 주요 메서드
- 사칙연산:
add, subtract, multiply, divide
divide 시 반드시 RoundingMode 지정 필요 (ROUND_HALF_UP, RoundingMode.HALF_EVEN 등)
- 스케일(scale): 소수점 자릿수 조정
setScale(int newScale, RoundingMode roundingMode)
- 비교:
compareTo(BigDecimal val) (equals()는 scale까지 비교 → 1.0 과 1.00 은 equals로는 false)
- 예시
BigDecimal x = new BigDecimal("1.0");
BigDecimal y = new BigDecimal("0.9");
BigDecimal z = x.subtract(y);
System.out.println("결과: " + z); // 0.1 (정확)
BigInteger vs BigDecimal
| 구분 |
BigInteger |
BigDecimal |
| 표현 |
정수 |
소수(부동소수점) |
| 범위 |
메모리 제한까지 무한 |
메모리 제한까지 무한 |
| 불변성 |
✅ (불변 객체) |
✅ (불변 객체) |
| 연산 |
사칙연산, 거듭제곱, GCD, 소수 판별, 비트 연산 |
사칙연산, 스케일 조정, 반올림 모드 |
| 주요 용도 |
암호학, 해시, 큰 수 계산 |
금융, 과학 계산, 정밀 소수 연산 |
| equals() |
값만 비교 |
값 + scale 비교 (1.0 ≠ 1.00) |
| 성능 |
단순 정수 연산이라 BigDecimal보다 빠름 |
소수점 처리 포함이라 BigInteger보다 느림 |
BigInteger 와 BigDecimal 은 wrapper class(래퍼 클래스) 가 아니다.
- Wrapper Class(래퍼 클래스)란?
- 기본 타입(primitive type) 을 객체로 감싸는 클래스
java.lang 패키지에 존재
boolean → Boolean, byte → Byte, short → Short,
int → Integer, long → Long, float → Float, double → Double, char → Character
- 특징:
- 모두
final + immutable
- 오토박싱/언박싱 지원 (JDK 1.5 이후)
즉, 래퍼 클래스는 기본형 타입을 OOP 세계에서 쓸 수 있게 해주는 클래스
- BigInteger / BigDecimal 의 위치
- 패키지:
java.math
- 공통점:
Number 추상 클래스 상속, Serializable, Comparable 구현
- 차이점: 기본 타입을 감싸는 클래스가 아님
BigInteger → 임의 정밀도 정수 표현 (기본형 int나 long 을 감싸는 게 아님)
BigDecimal → 임의 정밀도 소수 표현 (기본형 float, double 을 감싸는 게 아님)
즉, 별도의 수치 연산을 위한 "고정밀 수치 클래스"이지, primitive type을 감싸는 래퍼는 아니다**
| 구분 |
Wrapper Class |
BigInteger / BigDecimal |
| 예시 |
Integer, Double, Boolean 등 |
BigInteger, BigDecimal |
| 패키지 |
java.lang |
java.math |
| 대상 |
primitive type 감싸기 |
임의 정밀도 수치 표현 |
| 역할 |
기본형 → 객체화, 오토박싱/언박싱 지원 |
매우 큰 수 / 소수 정밀 계산 |
| 불변성 |
✅ |
✅ |
Number 상속 |
✅ |
✅ |
Number, Wrapper, BigInteger, BigDecimal 상속 구조
Object
├─ Boolean
├─ Character
└─ Number(추상 클래스)
├─ Byte
├─ Short
├─ Integer
├─ Long
├─ Float
├─ Double
├─ BigInteger
└─ BigDecimal