20장. 가장 많이 쓰는 패키지는 자바랭

공부하는 감자·2023년 12월 11일
0

자바의 신 3판

목록 보기
20/30

들어가기 전

『자바의 신 3판』 을 읽고 내용 정리 및 공부한 내용을 정리한 글입니다.
서적: 자바의 신 3판 구입처

내용 정리

Java.lang 패키지

java.lang 패키지의 클래스들은 자바의 패키지 중에 유일하게 import를 하지 않아도 사용할 수 있다. 그만큼 자바에서 꼭 필요한 여러 기능들을 제공한다.

java.lang과 java.util 패키지를 제외한 대부분의 java로 시작하는 패키지들은 패키지 이름만 보고도 어떤 일을 할 때 사용하는지를 알 수 있다. 하지만, java.lang과 java.util 패키지 안에는 아주 다양한 일을 하는 클래스와 인터페이스들이 혼재되어 있다.

기본적으로 자바로 개발할 때 패키지를 지정할 때에는 같은 역할 및 용도로 묶어 구분해야 한다.

java.lang 패키지에서 제공하는 것들

이 패키지에서 제공하는 인터페이스, 클래스, 예외 클래스 등은 다음과 같이 분류할 수 있다.

  • 언어 관련 기본
  • 문자열 관련
  • 기본 자료형 및 숫자 관련
  • 쓰레드 관련
  • 예외 관련
  • 런타임 관련

💡 참고로 이 분류는 책의 저자가 정한 것으로, 다른 자바 기본서에서는 다르게 분류할 수 있다.

아래는 책의 분류에 따라 정리한 표로, 중요하게 표시한 항목들만 정리했다. 전체 표는 책에서 확인할 수 있다.

참고 사이트: 공식 Java API 문서 (21버전)
Java® Platform, Standard Edition & Java Development Kit Version 21 API Specification

구분
타입
항목들
언어 관련 기본인터페이스Cloneable, Comparable, Interable, Readable
문자열 관련인터페이스Appendable, CharSequence
클래스String, StringBuffer, StringBuilder
기본 자료형 및
숫자 관련
클래스Boolean, Byte, Character, Double, Float, Integer, Long, Math, Number, Short
쓰레드 관련인터페이스Runnable, Thread.UncaughtExceptionHandler
클래스Thread, ThreadGroup, ThreadLocal
예외 관련클래스Throwable
예외 및 에러Exception
런타임 관련클래스Process, ProcessBuilder, Runtime, RuntimePermission

그 외의 자주 보게 될 에러

  • OutOfMemoryError (OOME)

자바는 가상 머신에서 메모리를 관리하지만, 프로그램을 잘못 작성하거나 설정이 제대로 되어 있지 않을 경우에는 메모리가 부족하여 이러한 에러가 발생할 수 있다.

  • StackOverflowError

호출된 메소드의 깊이가 너무 깊을 때 발생한다. 자바에서는 스택(Stack)이라는 영역에 어떤 메소드가 어떤 메소드를 호출했는지에 대한 정보를 관리한다.

예를 들어, 메소드가 자기 자신을 호출하는 재귀 메소드를 잘못 작성했다면 스택에 쌓을 수 있는 메소드 호출 정보의 한계를 넘어설 수 있다. 이 경우에 발생하는 것이 바로 이 에러다.

자바의 기본 어노테이션

java.lang 패키지에는 앞서 살펴본 자바의 기본 어노테이션이 선언되어 있다.

  • Deprecated
  • Override
  • SuppressWarning

숫자를 처리하는 Wrapper Class

자바에서 간단한 계산을 할 때에는 대부분 기본 자료형(Primitive Type)을 사용한다.

이 기본 자료형은 자바의 힙(Heap)이라는 영역에 저장되지 않고, 스택이라는 영역에 저장되어 관리한다. 따라서, 계산할 때 보다 빠른 처리가 가능하다.

검색 키워드: java stack primitive types
1. 자바의 기본 자료형 소개
2. 자바의 초기화 가이드
변수가 할당된 메모리에 값을 보유하는 기본 유형과 달리 참조는 참조하는 객체의 값을 보유하지 않습니다.
대신, 참조는 객체가 위치한 메모리 주소를 저장하여 객체를 가리킵니다.

그런데, 이러한 기본 자료형의 숫자를 객체로 처리해야 할 필요가 있을 수도 있다. 따라서, 자바에는 다음과 같이 기본 자료형으로 선언되어 있는 타입의 클래스들이 선언되어 있다.

  • Byte
  • Short
  • Integer
  • Long
  • Float
  • Double
  • Character
  • Boolean

Character를 제외한 나머지 클래스들은 각 기본 자료형의 이름에서 첫 문자만 대문자로 바뀌었다고 보면 된다.

Character와 Boolean을 제외한 숫자를 처리하는 클래스들은 감싼(Wrapper) 클래스라고 불리며, 모두 Number라는 abstract 클래스를 확장(extends)한다.

  • 자바 컴파일러에서 자동으로 형 변환을 해주기 때문에 기본 자료형처럼 사용할 수도 있다.
  • Byte, Short, Integer, Long, Float, Double 타입들은 필요 시 기본 자료형처럼 사용할 수 있다. 따라서, new를 사용하여 객체를 만들지 않아도 값을 할당할 수 있다.
  • 참조 자료형이지만 더하기 연산자를 통해 서로 더할 수도 있다.

Character 클래스를 제외하고는 공통적인 메소드를 제공한다.

  • parse타입이름()
  • valueOf()

이 두 가지 메소드는 모두 static 메소드이므로, 타입의 객체를 생성할 필요 없이 바로 사용할 수 있다.

둘 다 같은 문자열을 숫자 타입으로 변환한다는 공통점이 있지만, parse타입이름() 메소드는 기본 자료형을 리턴하고, valueOf() 메소드는 참조 자료형을 리턴한다.

숫자를 처리하는 참조 자료형을 만든 이유

그 이유는 다음과 같다.

  • 매개 변수를 참조 자료형으로만 받는 메소드를 처리하기 위해서
  • 제네릭과 같이 기본 자료형을 사용하지 않는 기능을 사용하기 위해서
  • MIN_VALUE나 MAX_VALUE와 같이 클래스에 선언된 상수 값을 사용하기 위해서
  • 문자열을 숫자로, 숫자를 문자열로 쉽게 변환하고, 2, 8, 10, 16진수 변환을 쉽게 처리하기 위해서

각각의 숫자 참조 자료형에서는 수많은 메소드를 제공한다. 이 메소드들은 API 문서를 보면서 직접 익혀 봐야 한다.

상수값과 메소드

타입의 최소값과 최대값을 가진 상수

Boolean 클래스를 제외한 기본 자료형을 참조 자료형으로 만든 클래스들은 모두 MIN_VALUE나 MAX_VALUE라는 상수를 갖고 있다.

해당 타입이 나타낼 수 있는 값의 범위(최소값/최대값)를 확인하려면 static으로 선언되어 있는 이 상수들을 다음과 같이 사용하면 된다.

Byte.MAX_VALUE;
Short.MAX_VALUE;
Integer.MAX_VALUE;
Long.MAX_VALUE;
Float.MAX_VALUE;
Double.MAX_VALUE;
(int) Character.MAX_VALUE;

Character의 경우는 그냥 출력할 경우 char 타입으로 출력되므로, int 타입으로 변환하여 그 값을 확인해봐야 한다.

2진수, 16진수로 변환

그런데, 이렇게 상수 값들이 Integer와 Long처럼 길어질 경우, 그대로 출력하는 것보다는 2진수나 16진수로 표현해서 보면 조금 더 보기 편하다.

Integer.toBinaryString();
Integer.toHexString();

만약 어떤 값을 원하는 진수의 숫자로 표현하고 싶을 때에는, 이와 같이 숫자 클래스에서 제공하는 메소드를 사용하면 된다.

돈 계산과 같이 중요한 연산을 수행 시

정수형은 BigInteger, 소수형은 BigDecimal을 사용하여야 정확한 계산이 가능하다. 이 두 클래스들은 모두 java.lang.Number 클래스의 상속을 받았으며, java.math 패키지에 선언되어 있다.

각종 정보를 확인하기 위한 System 클래스

System 클래스의 가장 큰 특징은 생성자가 없다는 것이다. 이 클래스에는 3개의 static 변수가 선언되어 있다.

선언 및 리턴 타입변수명설명
static PrintStreamerr에러 및 오류를 출력할 때 사용
static InputStreamin입력값을 처리할 때 사용
static PrintStreamout출력값을 처리할 때 사용

이제 System.out.println() 을 보자.

여기서 System 은 클래스 이름이다. 그 다음에 있는 out 은 System 클래스에 static으로 선언된 변수 이름이다.

위의 표를 보면 알 수 있듯이 out은 PrintStream 타입이다. 그러므로, println() 이라는 메소드는 PrintStream 클래스에 선언되어 있는 static 메소드라는 것을 알 수 있다.

출력과 관련된 메소드는 System 클래스가 아닌 PrintStream 클래스에서 찾아야만 한다. 참고로, 여기서 사용하는 PrintStream과 InputStream은 모두 java.io 패키지에 선언되어 있다.

💡 InputStream은 26장에서 살펴본다.

System 클래스에서 제공하는 메소드들

실제 System 클래스에 선언되어 있는 메소드들을 살펴보면 출력과 관련된 메소드들은 없다.

System 클래스는 이름 그대로 시스템에 대한 정보를 확인하는 클래스이며, 다음과 같이 다양한 역할을 제공한다.

  • 시스템 속성(Property) 값 관리
  • 시스템 환경(Environment) 값 조회
  • GC 수행
  • JVM 종료
  • 현재 시간 조회
  • 기타 관리용 메소드들

여기에서, “GC 수행”과 “JVM 종료” 관련 메소드들은 절대로 수행해서는 안 된다.

그리고 “기타 관리용 메소드들”은 거의 사용되지 않으므로 이 기본 책에서는 다루지 않는다.

시스템 속성(Property) 값 관리

Properties 클래스

Properties 클래스는 java.util 패키지에 속하며, Hashtable의 상속을 받은 클래스다.

자바 프로그램을 실행하면 Properties 객체가 생성된다. 그리고 이 값은 언제, 어디서든지 같은 JVM 내에서는 꺼내서 사용할 수 있다.

System.out.println(System.getProperty("java.version"));

💡 Hashtable이란
key와 value의 쌍으로 이루어진 여러 개의 값을 갖는 Map 형태의 자료 구조다.
배열이 위치(index)로 값을 찾는다면, Map 형태의 자료구조는 key로 값(value)를 찾는다.

메소드

리턴 타입
메소드 이름 및 매개 변수
설명
static StringclearProperty(String key)key에 지정된 시스템 속성을 제거한다.
static PropertiesgetProperties()현재 시스템 속성을 Properties 클래스 형태로 제공한다.
static StringgetProperty(String key)key에 지정된 문자열로 된 시스템 속성값(value)을 얻는다.
static voidsetProperties(Properties props)Properties 타입으로 넘겨주는 매개 변수에 있는 값들을 시스템 속성에 넣는다.
static StringsetProperty(String key, String value)key에 지정된 시스템 속성의 값을 value로 대체한다.

시스템 환경(Environment) 값 조회

Properties 라는 것은 추가할 수도 있고, 변경할 수도 있다. 하지만, 환경값 env라는 것은 변경하지 못하고 읽기만 할 수 있다. 이 값들은 대부분 OS나 장비와 관련된 것들이다.

System.out.println(System.getenv("JAVA_HOME"));

보통 자바를 사용할 때 JAVA_HOME이라는 값은 JDK가 설치되어 있는 경로를 말한다. java.exe나 java라는 명령어가 있는 위치가 아닌 자바의 가장 상위 디렉토리다.

만약 JAVA_HOME이 설정되어 있지 않다면, null로 나올 수도 있다.

메소드

리턴 타입
메소드 이름 및 매개 변수
설명
static Map<String, String>getenv()현재 시스템 환경에 대한 Map 형태의 리턴값을 받는다.
static Stringgetenv(String name)지정한 name에 해당하는 값을 받는다.

매개 변수가 없는 getenv() 메소드는 리턴 타입이 Map<String, String> 이므로, 지금 설명하지 않고 나중에 Map에 대해서 알아볼 때 다시 살펴본다.

GC 수행

리턴 타입
메소드 이름 및 매개 변수
설명
static voidgc()가비지 컬렉터를 실행한다.
static voidrunFinalization()GC 처리를 기다리는 모든 객체에 대하여 finalize() 메소드를 실행한다.

자바는 메모리 처리를 개발자가 별도로 하지 않는다. 따라서 System.gc 라는 메소드를 호출하면 가비지 컬렉션을 명시적으로 처리하도록 할 수 있다.

그리고, Object 클래스에 선언되어 있는 finalize() 메소드를 명시적으로 수행하도록 하는 runFinalization() 메소드가 있다.

이 두 개의 메소드들을 우리가 호출하지 않아도 알아서 JVM이 더 이상 필요 없는 객체를 처리하는 GC 작업과 finalization 작업을 실행한다. 만약 명시적으로 이 메소드들을 호출하는 코드를 집어 넣으면, 시스템은 하려던 일들을 멈추고 이 작업을 실행한다.

💡 개인적인 생각
GC는 수행될 때 실행 중인 프로그램을 잠시 멈춘다. 이를 Stop-The-World라고 하는데, 프로그램을 실행할 때 의도적으로 GC를 수행하면 애플리케이션의 속도가 저하되고 어떤 객체들이 정리될 지도 모르게 된다. 즉, 성능에 영향을 미치는 것이다.

또한, C언어는 원하는 객체를 지정해서 할당 해제하는 것이라면 GC는 전체 객체를 검사한다. 따라서 의도한 결과가 나오지 않을 수도 있다.
이러한 이유로 사용하지 않는 것이 좋다고 생각한다.

JVM 종료

리턴 타입메소드 이름 및 매개 변수설명
static voidexit(int status)현재 수행중인 JVM을 멈춘다.

status 는 0일 경우 정상적인 종료를 의미하고, 그 외의 숫자는 비정상적인 종료를 의미한다.

안드로이드 앱이나, 웹 애플리케이션에서 이 메소드를 사용하면 해당 애플리케이션의 JVM이 죽어버린다. 즉, 장애가 발생하는 것이다.

💡 장애가 발생하는 이유
보통 우리가 제공하는 프로그램들은 실시간으로 사용자들에게 제공하는 것이다. 따라서 사용 중에 갑자기 앱이 꺼지거나, 웹 사이트 접속이 끊기는 것은 당연히 장애가 된다.

현재 시간 조회

리턴 타입메소드 이름 및 매개 변수설명
static longcurrentTimeMillis()현재 시간을 밀리초 단위로 리턴한다.
static longnanoTime()현재 시간을 나노초 단위로 리턴한다.

currentTimeMillis() 메소드는 현재 시간을 나타낼 때 매우 유용한 메소드다. UTC라는 Universal time 기준으로 1970년 1월 1일 00:00부터 지금까지의 밀리초 단위의 차이를 출력한다.

밀리초는 11,0001 \over 1,000초다. 즉, 1,000밀리초는 1,000ms라고 표시하며 1초와 동일하다.

nanoTime() 메소드는 시간의 차이를 측정하기 위한 용도의 메소드다. 여기서 제공하는 시간은 나노초이며, 11,000,000,0001 \over 1,000,000,000초를 의미한다. 나노초를 11,000,0001 \over 1,000,000로 나누면 0.5ms이다.

// 메소드가 실행되는 시간을 구하는 법
public void numberMinMaxElapsedCheck() {
	long startTime = System.currentTimeMilis();
	long startNanoTime = System.nanoTime();
	// ... 메소드 등 실행
	System.out.println(System.currentTimeMilis() - startTime);
	System.out.println(System.nanoTime() - startNanoTime);
}

정리하자면,

  • currentTimeMillis() 메소드는 현재 시간을 확인하기 위한 메소드
  • 시간을 측정할 필요가 있을 때 나노초를 이용
    - nanoTime() 메소드는 시간 측정을 위해서 만들었기 때문이다.

System 클래스에는 이 외에도 관리용 메소드들이 있기는 하지만, 자바 개발을 하면서 그 메소드들을 사용할 일은 거의 없다.

System.out

System 클래스에 선언되어 있는 out과 err 변수는 PrintStream이라는 동일한 클래스의 객체다. 단지, 정상적인 출력인지 에러가 났을 때의 출력 결과인지의 차이만 존재한다.

PrintStream 클래스는 static하게 사용되므로, 생성자는 따로 살펴보지 않는다. 대신 이 클래스에 선언되어 있는 출력을 위한 메소드들을 살펴본다.

PrintStream 클래스의 출력을 위한 주요 메소드

  • print()
  • println()
  • format()
  • printf()
  • write()

여기서 제일 많이 사용되는 것은 print()println() 이다.

print()와 println()

  • print() 메소드는 매개 변수에 있는 내용들을 출력하고 줄 바꿈을 하지 않고,
  • println() 메소드는 매개 변수에 있는 내용들을 출력하고 줄바꿈 처리를 한다.
  • println() 메소드는 매개 변수가 없는 메소드가 존재한다.
  • 두 메소드 모두 기본 자료형과 참조 자료형을 매개 변수로 사용할 수 있다.

만약 줄바꿈만 처리하고 싶을 경우, println(""); 로 사용하면 필요 없는 String 객체가 생기므로, println(); 를 사용하는 것이 깔끔하다.

메소드의 매개 변수 목록

  • boolean b
  • char c
  • char[] s
  • double d
  • float f
  • int i
  • long l
  • Object obj
  • String s
  • (println일 경우,) 매개변수 없음

byte 타입이나 short 타입을 매개 변수로 받는 메소드가 선언되어 있지 않다.

하지만, byte나 short 타입을 print() 메소드나 println() 메소드에 넘겨주면 int 타입을 매개 변수로 받는 메소드에서 알아서 처리해주므로 문제는 없다.

null인 객체를 출력할 경우

null인 Object는 아무런 할당이 되어 있지 않기 때문에 메소드를 호출할 수가 없다.

하지만, print()println() 메소드에서는 컴파일도 잘 되고 실행 시 문제가 되지도 않는다.

이 두 메소드에서는 단순히 toString() 메소드 결과를 출력하는 것이 아니라, String의 valueOf()라는 static 메소드를 호출하여 결과를 받은 후 출력한다.

즉, String.valueOf(null)가 호출된 것이다. 이렇듯 객체를 출력할 때에는 toString() 보다는 valueOf()를 사용하는 것이 훨씬 안전하다.

null인 객체와 문자열을 합쳤을 경우

컴파일러에서는 이 더하기 문장을 StringBuilder로 변환하기 때문에, 문제 없이 출력된다.

format()와 printf()

이 두 메소드는 JDK 5부터 추가되었다. 이름만 다르고 처리하는 것은 동일하므로, 편한 대로 선택하여 사용하면 된다.

💡 책의 저자는 “C 언어로 오랫동안 개발한 경험이 있는 개발자들은 예전의 자바 버전에 이 두 가지 메소드가 없어 많이 불편해했다”고 한다.
즉, C언어에서 사용하는 것들을 도입한 것으로 추측된다.

정리해 봅시다.

Q. 같은 패키지에 있는 클래스를 제외하고, 별도로 import 하지 않아도 되는 패키지는 무엇인가요?

Me: java.lang 패키지

Q. 자바의 메모리가 부족해서 발생하는 에러는 무엇인가요?

Me: OutOfMemoryError

Q. 메소드 호출관계가 너무 많아서 발생하는 에러는 무엇인가요?

Me: StackOverflowError

Q. java.lang 패키지에 선언되어 있는 3개의 어노테이션에는 어떤 것들이 있고, 각각의 역할은?

Me: @Deprecated, @Override, @SuppressWarning

Q. Double과 Integer 같은 숫자 타입에서 처리할 수 있는 최대, 최소값을 알 수 있는 상수의 이름은?

Me: MAX_VALUE, MIN_VALUE

Q. Integer값을 2진법으로 표현하려면 어떤 메소드를 사용해야 하나요?

Me: toBinaryString()

Q. Integer값을 16진법으로 표현하려면 어떤 메소드를 사용해야 하나요?

Me: toHexString()

Q. 속성(Properties)과 환경(Environment) 값의 차이는 무엇인가요?

Me: 속성은 변경할 수 있는 정보이고, 환경은 변경할 수 없는 정보이다. (정답은 좀 더 개념적인 것에서 설명해야 한다.)

Q. System.out과 System.err 에서 사용할 수 있는 메소드들은 어떤 클래스의 API를 봐야 하나요?

Me: PrintStream

Q. System 클래스에서 현재 시간을 조회하는 용도로 사용하는 메소드 이름은 무엇인가요?

Me: currentTimeMillis()

Q. System 클래스에서 시간 측정 용도로 사용하는 메소드 이름은 무엇인가요?

Me: nanoTime()

Q. System.out.print() 메소드와 System.out.println() 메소드의 차이는 무엇인가요?

Me: print()는 한 줄에 이어 출력해주고, println은 맨 끝에 줄바꿈 문자를 포함한 출력이다.

Q. System.out.println() 메소드에 객체가 매개변수로 넘어 왔을 때 String의 어떤 메소드가 호출되어 결과를 출력하나요? 그리고, 그 메소드를 사용하는 이유는 무엇인가요?

Me: String의 valueOf() 메소드가 호출된다. 객체가 null일 경우 NullException이 나는 것이 아니라, "null"로 출력해주기 때문이다.

Q. 숫자 계산을 위해서 필요한 메소드들을 모아 놓은 클래스는 무엇인가요?

Me: Math

Q. 위의 문제의 답인 클래스에 있는 메소드는 객체를 생성해서 사용해야 하나요?

Me: X

Q. 숫자의 절대값을 구하는 메소드는 무엇인가요?

Me: abs()

Q. 숫자의 반올림을 하는 메소드는 무엇인가요?

Me: round()

Q. 각도를 라디안으로 변환하는 메소드와 라디안을 각도로 변환하는 메소드는 각각 무엇인가요?

Me: toDegrees(), toRadians()

Q. 5의 4 제곱 값을 구하려고 하면 어떤 메소드를 사용해야 하나요?

Me: pow()

질문

💡 책에 있는 내용이 아닙니다.

책을 읽으며 설명이 더 필요하거나, 추가로 궁금한 점에 대해 질문 형식으로 작성 후, 답을 구해보고 있습니다.
참고한 사이트나 영상은 [출처]로 달아두었으며, 오류 지적은 언제나 환영합니다.

Q. java.lang 패키지가 static인 이유는 뭘까?

java.lang 패키지는 자바의 기본적인 클래스와 인터페이스를 제공한다. 즉, 자바의 핵심 부분을 담당하며 프로그램의 모든 부분에서 자주 사용된다.

따라서, 이를 사용하지 않고서는 자바 프로그램을 작성하기 어렵다.

즉, 프로그램의 전반적인 부분에서 자주 사용되는 용도이기 때문에, 별도에 import 문 없이 사용할 수 있도록 한 것이다.

Q. main 메소드에서 Java.lang에 있는 걸 쓸 수 있나?

사용할 수 있다. 애초에 매개변수로 받는 값부터 Java.lang 패키지의 String을 사용 중이다.

args 타입은 왜 String만 허용하는가?

앞서 3장에서 설명했지만, 외부에서 입력받는 명령행 인자는 String이기 때문이다. 다른 타입을 허용하면 타입 변환을 해줘야하는 번거로움과, 변환 시 오류가 발생할 수도 있다.

명령행 인자는 왜 String을 사용하는가?

문자열은 다양한 타입의 값을 표현할 수 있기 때문에, 명령줄에서 전달되는 값은 일반적으로 문자열 형태로 표현된다.

또한, 문자열은 일반적으로 파싱하기가 상대적으로 간편하고 유연하기 때문에 명령줄 인자로 사용하기에 적합하다.

만약, 명령줄 인자가 다양한 타입으로 지원된다면, 그에 따른 파싱 및 타입 변환 작업을 수행해야 한다. 이는 복잡성을 증가시키고 사용자와의 상호 작용을 어렵게 만들 수 있다.

따라서, 문자열로 표현된 값들을 명령줄에서 전달받아 적절히 해석하는 것이 간편하며 표준화된 방법이다.

Q. 메소드 호출 시 Stack 동작 과정

공부했던 내용을 리마인드하는 느낌으로 적어보았다.

메모리 영역

프로그램에서는 코드 실행 영역과 데이터 저장 영역을 가지고 있다. 객체 지향 프로그램에서는 데이터 저장 영역을 총 3개의 영역으로 분할해서 사용한다.

  • Static 영역
    • 클래스의 정보가 올라가는 영역이다.
  • Stack 영역
    • 메소드가 호출될 때마다 이 영역에 Stack Frame(스택 프레임)이 할당된다.
    • 기본자료형은 이 영역 안에 저장되어 관리된다.
  • Heap 영역
    • 객체가 생성되면 이 영역에 할당된다.

Stack 메모리

아주 간단한 예제로 보겠다.

public static void main(String[] args) {
	int i = 3;
}
  1. main() 메소드의 중괄호를 만나면 스택 프레임이 하나 생성된다.
  2. 스택 프레임 안에 변수 i와 그 값을 저장한다.
  3. main() 메소드의 닫는 중괄호를 만나면 스택 프레임은 소멸된다.

Q. 왜 스택 영역에 있으면 계산할 때 빠른 처리가 가능한가?

스택이 효율적인 데이터 구조이기 때문이다. 후입선출(LIFO), 즉 가장 최근에 추가된 데이터가 가장 먼저 제거되는 구조를 가지고 있어, 메모리의 스택 영역에서의 데이터 액세스 및 관리를 효과적으로 할 수 있다.

  • 간단한 구조를 가지고 있어 데이터를 저장하고 꺼내는 과정이 단순하다.
  • 함수 호출 시 프레임을 쌓고, 반환 시 프레임을 제거하는 방식으로 사용되므로 프레임의 관리가 효율적이다.
  • 스택은 지역성이 뛰어나서 캐시 효과를 누릴 수 있다.
    • 스택은 연속적인 메모리 위치에 데이터가 순서대로 저장된다.
    • 스택 프레임에 저장된 지역 변수나 함수 호출 정보 등은 해당 함수가 수행되는 동안 반복적으로 참조될 가능성이 높다.

Q. Number 라는 추상 클래스는 무엇인가?

Charater와 Boolean 을 제외한 숫자를 처리하는 Wrapper 클래스는 모두 Number 추상 클래스를 확장한다.

Number 추상 클래스 안에는 Wrapper 클래스 안에 있는 기본 자료형의 값을 특정 숫자 타입으로 변환해서 반환해주는 메소드들이 선언되어 있다.

Q. Character 클래스만 parse와 valueOf 없는 이유

parseChar 메소드가 없는 이유

아래 내용은 ChatGPT의 도움을 받았다.

parse 메소드는 문자열을 해당 클래스의 기본 자료형을 반환한다.

그런데, 일반적으로 ‘char’ 값은 단일 문자로 구성되어 있어서 문자열로 표현할 이유가 없다.

또한 Character 클래스에는 이미 문자열을 char 값으로 변환하는 charAt() 메소드와 같은 다양한 방법이 있다.

valueOf 메소드가 없는 이유

자바8 문서를 찾아봤는데, 실제로는 존재한다.

Charater.valueOf()

Q. properties와 environment 차이

속성(properties)은 프로그램 내에서 동적으로 설정 정보를 관리할 때 활용되고, 환경(environment)은 운영 체제 수준에서 설정되어 프로세스에 영향을 미치는 변수들이다.

정리하자면, 속성은 JVM이나 애플리케이션의 설정 정보이고, 환경은 운영 체제에서 관리하는 환경 변수를 말하는 것이다.

Q. GC를 명시적으로 호출하면 어떤 일이 벌어지는가?

자바에서는 System.gc() 메소드로 명시적으로 호출할 수 있다고 한다.

하지만, JVM이 동적으로 가비지 컬렉션을 관리하고 있기 때문에 이 메소드를 호출한다고 해도 가비지 컬렉션의 실행은 보장되지 않는다.

이 메소드를 명시적으로 호출하는 것은 특정 시점에 가바지 컬렉션이 실행되도록 유도하려는 의도를 나타내는 것이지, 실제로 즉시 실행되도록 강제하는 것이 아니다.

따라서 일반적으로 개발자가 명시적으로 System.gc() 메소드를 호출할 일은 거의 없으며, JVM이 동적으로 가비지 컬렉션을 관리하는 것이 바람직하다.

Q. Print할 때 toString() 쓴다고 했는데?

앞 장에서 toString() 을 호출한다고 말했고, 이 장에서는 valueOf() 메소드를 사용한다고 정정했다.

사실 이건, valueOf() 메소드를 살펴보면 알 수 있다.

자바8의 문서인데, 내용을 보면 null 이 경우 String “null”을 반환하고, 그렇지 않을 경우 내부적으로 toString() 메소드를 호출하여 반환하고 있다.

즉, valueOf() 메소드 내부에서 toString() 메소드를 호출하도록 되어있으므로 앞 장에서 그렇게 설명한 것이다.

참고 사이트

Java Platform SE 8

☕ 자바 Wrapper 클래스와 Boxing & UnBoxing 총정리

자바의 기본 자료형 소개

자바의 초기화 가이드

profile
책을 읽거나 강의를 들으며 공부한 내용을 정리합니다. 가끔 개발하는데 있었던 이슈도 올립니다.

0개의 댓글