Jasontreks Blog

DM 보내기


Send

모듈과 패키지

모듈과 패키지는 자바로 프로그램을 구축하는데에 있어 기능들을 분리하고 관 ` 협업을 용이하도록 하는 기능이다.


I. 패키지

패키지는 서로 관련있는 클래스나 인터페이스의 컴파일된 파일들을 한 곳에 묶어놓은 것이다. 디렉토리의 개념과 비슷하다.

패키지 선언

이클립스는 빈 프로젝트를 시작하더라도 자동으로 패키지로 감싼다. 따라서 폴더 구조는 다음과 같이 생겼다.

myproject
	|
	----bin
	|	 |
	|	 ----myproject // 패키지 폴더
	|			 |
	|			 ----Main.class		 
	----src
		 |
		 ----myproject // 소스파일 폴더
		 		 |
				 ----Main.java

bin 폴더 아래에 프로젝트명과 같은 이름의 패키지가 만들어진 것이다. 또한 Main.java의 맨 윗줄의 코드에는 이런 구문이 작성되어 있을 것이다

package study1;

이 구문은 패키지 선언으로, 이 클래스가 소속될 패키지 이름을 명시하는 것이다.

패키지 사용하기

자바에서 가장 대표적인 패키지 사용 예제는 Scanner 클래스를 사용할 때이다.

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner scn = new Scanner(System.in);
		System.out.println(scn.next());
	}
}

II. 모듈

JDK9 이후 패키지들을 모듈이라는 단위로 묶어 제공한다. .jmod 형태의 압축 파일로 저장하고 사용할 땐 JDK로 압축을 풀어 이용한다.

모듈 기반 자바 환경

기존에 자바는 자바 API의 모든 클래스들을 rt.jar에 압축하고 응용 프로그램 실행 시 이를 풀어 필요한 클래스를 메모리에 로드하는 방식으로 작동했다. 하지만 이는 하나의 클래스를 위해 전체를 압축 해제해야 하는 불필요한 비용을 발생시킨다. 자바9 이후부터는 rt,.jar 대신 자바 API를 수많은 모듈들로 분해하여 응용 프로그램 컴파일 시 필요한 모듈들만 조립해 프로그램이 구성되도록 개선하였다.

자바 API

자바 API는 JDK 설치시 개발자가 기본적으로 가져다 쓸 수 있도록 미리 만들어진 기능들이다. 이 기능들은 클래스 단위로 구현되어 있으며 비슷한 기능을 하는 것들끼리 패키지로 묶여있고, 이 패키지들은 다시 모듈에 담겨 제공된다.

주요 패키지

  • java.lang: System, 문자열, 수학, 입출력 등 기본적인 클래스와 인터페이스 제공. import 없이 자동 임포트
  • java.util: Scanner, 날짜, 시간, 벡터, 해시맵 등 다양한 유틸리티 제공
  • java.io: 키보드, 모니터, 프린터, 파일 등의 입출력 기능 제공
  • java.awt, java.swing: GUI 프로그래밍에 필요한 클래스와 인터페이스 제공

최신 자바 24에 대한 모듈, 패키지, 클래스 정보는 이 공식 문서에서 확인 가능하다.


III. 자바 API의 유용한 클래스들

자바로 프로그래밍을 하면서 자주 사용되는 유용하고 편리한 클래스들이 있다.

Object (java.lang)

모든 클래스에 강제로 상속되는 최상위 클래스이다. 주요 메소드는 다음과 같다.

  • boolean equals(Object obj): obj가 가리키는 객체와 현재 객체의 내용이 같으면 true 리턴. == 연산자는 같은 레퍼런스 값을 가지는지 비교하므로 객체의 동일성을 비교할 땐 equals() 이용.
  • Class getClass(): 현 객체의 런타임 클래스를 리턴
  • int hashCode(): 현 객체의 해시 코드 값 리턴
  • String toString(): 현 객체의 문자열 표현 리턴. 이는 오버라이딩하여 기본 문자열 표현이 아닌 원하는 필드 값을 출력하게 만들 수 있다.
  • void notify(): 현 객체에 대기하고 있는 하나의 스레드를 깨움
  • void notifyuAll(): 현 객체에 대기하고있는 모든 스레드를 깨움
  • void wait(): 다른 스레드가 깨울 때까지 현재 스레드를 대기하게 함

Wrapper 클래스

이름이 Wrapper인 클래스를 말하는것이 아니라, 자바의 8개 기본 타입을 객체로 다루기 위한 클래스이다. Byte, Short, Integer, Long, Character, Double, Float, Boolean 클래스가 있다.

Warpper 클래스를 생성할 땐 valueOf() 메소드를 이용한다.

Integer i = Integer.valueOf(10);
Double d = Double.valueOf(3.14);

Wrapper 클래스는 값 변환, 문자열 변환과 같이 기본 타입이 제공하지 않는 유틸리티 기능을 활용하기 위해 쓰인다.

숫자 관련 클래스 (Integer, Double, Long 등)

구분메소드설명예시
변환parseInt(String s)문자열을 기본 타입(int)으로 변환Integer.parseInt("10")
valueOf(String s)문자열을 Wrapper 객체로 변환Integer.valueOf("10")
toString(int i)숫자 데이터를 문자열로 변환Integer.toString(10)
비교/연산compare(x, y)두 값을 비교 (같으면 0, x가 크면 1, 작으면 -1)Integer.compare(10, 20)
max(x, y) / min(x, y)두 수 중 큰 값 / 작은 값 반환Integer.max(10, 20)
sum(x, y)두 수의 합을 반환Integer.sum(10, 20)
진법toBinaryString(int i)숫자를 2진수 문자열로 변환Integer.toBinaryString(8)

Character 클래스

메소드설명결과값
isDigit(char)숫자인지 여부 확인false
isLetter(char)문자인지 여부 확인true
isUpperCase(char)대문자인지 확인true
isLowerCase(char)소문자인지 확인false
isWhitespace(char)공백(스페이스, 엔터 등)인지 확인false
toUpperCase(char)대문자로 변환'A'
toLowerCase(char)소문자로 변환'a'

공통 인스턴스 메소드 (모든 Wrapper 공통)

메소드설명비고
typeValue()객체 안의 값을 기본 타입으로 반환intValue(), doubleValue()
equals(Object obj)두 객체가 가지고 있는 이 같은지 비교== 연산자는 주소를 비교하므로 주의
hashCode()객체의 해시코드 값을 반환컬렉션(HashMap 등)에서 사용

주요 상수(Constants)

상수설명
MAX_VALUE해당 타입이 가질 수 있는 최대값
MIN_VALUE해당 타입이 가질 수 있는 최소값
SIZE해당 타입의 비트(bit) 수
BYTES해당 타입의 바이트(byte) 수

String (java.lang)

String은 문자열을 다루는 클래스이다. 이 클래스를 생성할 때 두 가지 방법이 있는데, 스트링 리터럴new String() 이다.

String a = "Hello"; // 스트링 리터럴
String b = new String("World"); // new String()
  • 스트링 리터럴: 자바 가상머신에서 관리하는 상수 영역의 리터럴 테이블에 해당 문자열("Hello")를 할당하고 그것을 a가 참조하는 방식이다. 즉 같은 문자열이면 여러 String 객체가 같은 리터럴을 공유하게 됨으로서 비용을 줄인다.
  • new String(): 힙 메모리 영역에 그 객체만을 위한 새로운 문자열("World")를 할당하고, b가 그 객체를 참조한다.
String 객체는 수정 불가

한번 만들어진 String 객체는 리터럴이든 new로 생성했든 수정이 불가능하다. 그래서 concat과 같은 수정 메소드는 실제로는 새로운 객체를 만들어 반환하는 작업을 한다.

Stirng 클래스의 주요 메소드는 다음과 같다.

문자열 추출 및 정보 확인

메소드설명예시 ("Hello")
length()문자열의 길이를 반환length() → 5
charAt(int i)해당 인덱스의 문자를 반환charAt(1) → 'e'
indexOf(String str)특정 문자(열)가 시작되는 위치 반환 (없으면 -1)indexOf("l") → 2
lastIndexOf(String str)뒤에서부터 특정 문자(열)의 위치를 탐색lastIndexOf("l") → 3
substring(int begin, int end)지정된 범위의 문자열을 잘라서 반환substring(0, 2) → "He"

문자열 비교 및 검사

메소드설명예시 ("Java")
equals(Object obj)문자열의 내용이 같은지 비교 (대소문자 구분)equals("java") → false
equalsIgnoreCase(String s)대소문자 무관하게 내용 비교equalsIgnoreCase("JAVA") → true
contains(CharSequence s)특정 문자열이 포함되어 있는지 확인contains("av") → true
startsWith(String s)특정 문자열로 시작하는지 확인startsWith("J") → true
endsWith(String s)특정 문자열로 끝나는지 확인endsWith("a") → true
isEmpty()문자열의 길이가 0인지 확인"".isEmpty() → true

문자열 변환 및 치환

메소드설명예시
replace(old, new)특정 문자(열)를 새로운 문자(열)로 치환"abc".replace("a", "z") → "zbc"
toLowerCase() / toUpperCase()**소문자 / 대문자로 변환"AbC".toLowerCase() → "abc"
trim()문자열 앞뒤의 공백을 제거" hi ".trim() → "hi"
split(String regex)구분자를 기준으로 문자열을 분리하여 배열로 반환"a:b".split(":")b
concat(String s)두 문자열을 연결"A".concat("B") → "AB"

기타 유용한 정적(static) 메소드

메소드설명예시
valueOf(any type)기본 타입 데이터를 문자열로 변환String.valueOf(100) → "100"
format(format, args)형식 지정자(%d, %s 등)를 사용하여 문자열 생성String.format("%d원", 500) → "500원"
join(delimit, elements)여러 문자열을 구분자를 넣어 하나로 합침String.join("-", "010", "1234") → "010-1234"

StringBuffer (java.lang)

StringBuffer 역시 String처럼 문자열을 다루는 클래스지만 자체적으로 버퍼를 가지고 있어 문자열 수정이 가능하다.

StringBuffer의 생성자는 아래와 같다. 생성시 초기 버퍼크기를 지정할 수 있다.

생성자설명특징
StringBuffer()기본 생성자초기 용량(Capacity)이 16개 문자인 버퍼를 생성
StringBuffer(int capacity)용량 지정 생성자전달받은 capacity만큼의 크기를 가진 버퍼를 생성
StringBuffer(String str)문자열 포함 생성자전달받은 문자열을 저장하며, 문자열 길이 + 16의 여유 공간을 설정
StringBuffer(CharSequence seq)인터페이스 구현체 포함String뿐만 아니라 StringBuilderCharSequence 구현체를 인자로 받아 생성

주요 메소드는 아래와 같다.

메소드설명
StringBuffer append(String str)str 스트링을 스트링 버퍼에 덧붙인다.
StringBuffer append(StringBuffer sb)sb 스트링 버퍼를 현재의 스트링 버퍼에 덧붙인다. 이 결과 현재 스트링 버퍼의 내용이 변한다.
int capacity()스트링 버퍼의 현재 크기 리턴
StringBuffer delete(int start, int end)start 위치에서 end 위치 앞까지 부분 문자열 삭제
StringBuffer insert(int offset, String str)str 스트링을 스트링 버퍼의 offset 위치에 삽입
StringBuffer replace(int start, int end, String str)스트링 버퍼 내의 start 위치의 문자부터 end가 지정하는 문자 앞의 서브 스트링을 str로 대치
StringBuffer reverse()스트링 버퍼 내의 문자들을 반대 순서로 변경
void setLength(int newLength)스트링 버퍼 내 문자열 길이를 newLength로 재설정. 현재 길이보다 큰 경우 널 문자('\0')로 채우며 작은 경우는 기존 문자열이 잘린다.

StringTokenizer

문자열을 분리할 때 사용하는 클래스이다.

import java.util.StringTokenizer;

public class TokenizerExample {
    public static void main(String[] args) {
		// 분리할 문자열
        String query = "name=apple&addr=seoul&age=25";
        
        // '&'를 구분자로 사용하여 문자열을 분리
		// st에는 분리된 토큰들이 저장됨
        StringTokenizer st = new StringTokenizer(query, "&");
        
		// countTokens() 메소드로 개수 파악
        System.out.println("토큰 개수: " + st.countTokens());
        
        while (st.hasMoreTokens()) {
			// nextToken()으로 다음 토큰 을 가져옴
            String token = st.nextToken();
            System.out.println(token);
        }
    }
}

Math

수학과 관련된 여러 기능을 모아놓은 클래스이다.

메소드설명
static double abs(double a)실수 a의 절댓값 리턴
static double cos(double a)실수 a의 cosine 값 리턴
static double sin(double a)실수 a의 sine 값 리턴
static double tan(double a)실수 a의 tangent 값 리턴
static double exp(double a)eae^a 값 리턴
static double ceil(double a)올림. 실수 a보다 크거나 같은 수 중에서 가장 작은 정수를 실수 타입으로 리턴
static double floor(double a)내림. 실수 a보다 작거나 같은 수 중에서 가장 큰 정수를 실수 타입으로 리턴
static double max(double a, double b)두 수 a, b 중에서 큰 수 리턴
static double min(double a, double b)두 수 a, b 중에서 작은 수 리턴
static double random()0.0보다 크거나 같고 1.0보다 작은 임의의 실수 리턴
static long round(double a)반올림. 실수 a를 소수 첫째 자리에서 반올림한 정수를 long 타입으로 반환
static double sqrt(double a)실수 a의 제곱근 리턴

Calendar

컴퓨터의 현재 시간을 알아내거나 날짜 정보를 년, 월, 일, 요일로 저장하고 시간 정보도 시간, 분, 밀리초까지 다룰 수 있는 클래스이다.

Calendar는 추상 클래스이다. 따라서 객체를 직접 생성하지는 못하고 다음과 같이 static 메소드를 통해 간접적으로 생성한다.

// 현재 날짜와 시간 정보
Calendar now = Calendar.getInstance();

그리고 get()메소드를 통해 연, 월, 등을 설정할 수 있다. 이때 상수 필드를 이용해 얻고자 하는 정보를 클래스에 전달한다.

int year = now.get(Calendar.YEAR); // 현재 년
int month = now.get(Calendar.MONTH) + 1; // 현재 달

Calendar 클래스애서 get()set()에 사용되는 상수 필드들은 다음과 같다.

필드의미
YEAR년도
MONTH달 (0 ~ 11)
HOUR시간 (0 ~ 11)
HOUR_OF_DAY24시간을 기준으로 한 시간
SECOND
DAY_OF_MONTH한 달의 날짜
DAY_OF_WEEK한 주의 요일
AM_PM오전인지 오후인지 구분
MINUTE
MILLISECOND밀리초

Calendar 클래스로 생성한 객체에 개발자가 원하는 날짜와 시간 정보를 입력하는 예제는 다음과 같다.

Calendar date = Calendar.getInstance();
date.clear(); // 현재 시간 정보 초기화
date.set(2016, 11, 25); // 2016년 11월 25일
date.set(Calendar.HOUR_OF_DAY, 20); // 저녁 8시
date.set(Calendar.MINUTE, 30); // 30분