Java 치트시트 — 빠른 참조
Java 17+ 문법, OOP, 컬렉션, 자주 쓰는 표준 라이브러리를 모은 빠른 참조로, 일상 작업의 약 80%를 커버합니다.
Java Java 17 (LTS)
JDK (OpenJDK / Oracle) · OOP · 제네릭 · 함수형 · 정적 · 강한 타입 · 공칭 타입
추천 학습 경로
먼저 "Hello World와 빌드 환경"(javac/java 또는 Maven)을 실행해 보고 → 변수, 타입, 제어 흐름에 익숙해지고 → 컬렉션과 Stream API로 데이터를 처리한 뒤 → 객체 지향(상속/인터페이스/제네릭)을 파고 → 예외 처리와 람다를 익히고 → 마지막에 필요할 때 파일, 네트워크, 시간, 빌드/디버깅을 찾아봅니다. FAQ 섹션은 나중에 함정을 피하기 위해 다시 보는 것이 좋습니다.
1.Hello World와 빌드 환경
Java 프로그램을 처음부터 작성·컴파일·실행합니다: main 메서드, javac/java, 패키지, 빌드 도구.
최소 프로그램
모든 Java 프로그램은 main 메서드부터 시작합니다: public static void main(String[] args). System.out.println으로 한 줄을 출력합니다.
컴파일과 실행
javac는 .java를 .class 바이트코드로 컴파일하고, java가 JVM을 띄워 실행합니다. javap으로 바이트코드를 디스어셈블해 봅니다.
명령줄 인수
main(String[] args)는 명령줄 인수를 받으며, args[0]이 첫 번째 사용자 인수입니다. args.length로 개수를 확인합니다.
종료 코드
System.exit(code)는 JVM을 종료하고 종료 코드를 반환합니다: 0 성공, 0 이외 실패. main이 아닌 스레드가 실행 중이어도 강제 종료합니다.
패키지 선언
package는 소속 패키지를 선언하고 디렉터리 구조와 대응하며, 완전한 한정 이름으로 타입을 식별합니다. 생략하면 무명 패키지에 속합니다.
import 문
import는 다른 패키지의 클래스나 static 멤버를 가져와 완전한 한정 이름을 생략하게 합니다. java.lang은 기본으로 import됩니다.
클래스와 파일명
public 클래스 이름은 파일명과 일치해야 합니다. 한 .java 파일에 public이 아닌 여러 클래스를 둘 수 있지만, public 클래스는 하나만 둘 수 있습니다.
Maven / Gradle
대형 프로젝트는 빌드 도구를 사용합니다: Maven(pom.xml)과 Gradle(build.gradle)이 의존성, 컴파일, 테스트, 패키징을 관리합니다.
2.변수와 상수
변수 선언, 타입 추론, final 상수, 스코프, 타입 변환.
변수 선언
선언 = 타입 + 이름 + 선택적 초기화. Java의 지역 변수는 사용 전 초기화가 필수이며, 필드에는 기본값이 있습니다.
var 타입 추론
var(Java 10+)는 컴파일러가 타입을 추론합니다. 지역 변수에만 사용할 수 있습니다. 타입이 모호하면 명시적 선언이 더 읽기 좋습니다.
final 상수
final 지역 변수는 한 번만 대입할 수 있습니다. final 필드는 선언 시 또는 생성자에서 초기화해야 하며, static final은 상수입니다.
스코프
블록 스코프: 중괄호 안의 변수는 그 블록에서만 보입니다. 중첩 블록에서 외부의 같은 이름 변수를 가릴 수 있지만 권장하지 않습니다.
명명 규칙
클래스명은 UpperCamelCase, 변수/메서드명은 lowerCamelCase, 상수는 UPPER_SNAKE_CASE, 패키지명은 모두 소문자입니다.
타입 변환
암시적 변환은 좁은 타입에서 넓은 타입으로(int→long→double). 명시적 캐스트는 정밀도를 잃을 수 있습니다(절단).
null과 NPE
null은 참조 타입의 빈 값입니다. null에 대해 메서드 호출이나 필드 접근을 하면 NullPointerException(NPE)이 발생합니다. Objects 유틸리티로 안전하게 처리할 수 있습니다.
리터럴
정수 리터럴은 _로 구분할 수 있고(가독성), 0x는 16진, 0b는 2진입니다. long은 L, float은 f를 붙입니다.
3.데이터 타입
기본 타입과 래퍼 클래스, 문자열, 배열, 열거형, 제네릭, record.
기본 타입
Java의 8가지 기본 타입: byte/short/int/long(정수), float/double(부동소수), char, boolean. 값이 직접 저장됩니다.
래퍼 클래스
Integer/Double/Boolean 같은 래퍼 클래스는 기본 타입을 객체로 감쌉니다. 필요 시 자동 박싱/언박싱이 일어납니다.
문자열
String은 불변 문자 시퀀스이며, equals는 내용 비교, ==는 참조 비교입니다. 수정은 매번 새 객체를 생성합니다.
배열
배열은 고정 길이, 인덱스로 접근, length 속성을 갖습니다. int[]로 선언, new int[n]로 생성, {}로 초기화합니다.
열거형
enum은 상수 집합을 정의하며, 필드와 메서드를 포함할 수 있습니다. switch는 열거형 값을 바로 사용할 수 있습니다. 컴파일 시점 타입 안전성.
제네릭
제네릭은 타입을 매개변수화합니다: List<T>, Map<K,V>. 컴파일 시 타입 검사를 하고, 런타임에는 소거됩니다(type erasure).
record 타입
record(Java 14 프리뷰, 16 정식)는 불변 데이터 캐리어를 한 줄로 선언하며, 생성자/equals/hashCode/toString이 자동 생성됩니다.
자동 박싱 함정
박싱/언박싱은 ==/연산에서 함정을 숨깁니다: -128~127의 Integer는 캐시되지만, 범위를 벗어나면 ==가 false일 수 있습니다.
Object 루트 클래스
모든 클래스는 암묵적으로 Object를 상속합니다: toString, equals, hashCode, clone, finalize. equals를 오버라이드하면 hashCode도 반드시 오버라이드합니다.
4.참조와 메모리
참조 의미, null, 객체 복사, 힙/스택, GC, 문자열 풀.
참조 의미
Java에는 포인터가 없고, 객체 변수는 참조를 보관합니다(포인터와 유사). 대입은 같은 객체를 공유하여 변경이 모든 별칭에 보입니다.
null 참조
null은 참조가 어떤 객체도 가리키지 않음을 의미합니다. null 비교는 ==/!=를 쓰고, 메서드에 null을 넘기면 NPE가 발생합니다. 방어적으로 null 체크하세요.
Object 메서드
toString은 객체를 설명하고, equals는 내용 비교를, hashCode는 해시를 수행합니다. 기본 구현은 참조 비교이며, 내용 의미론을 원하면 재정의해야 합니다.
힙과 스택
객체는 힙에 할당되고(GC가 관리), 지역 변수와 참조는 스택에 있습니다. new로 만든 객체의 참조는 스택, 본체는 힙에 있습니다.
GC 가비지 컬렉션
JVM이 도달 불가능한 객체를 자동으로 회수하므로 수동 free가 필요 없습니다. System.gc()는 힌트일 뿐 즉시 실행을 보장하지 않습니다.
복사 의미
배열/객체 대입은 참조를 공유합니다. 독립 사본이 필요하면 clone, Arrays.copyOf, 또는 수동 복사를 씁니다. 깊은 복사는 계층별로 복사해야 합니다.
문자열 상수 풀
리터럴 문자열은 상수 풀에 캐시되어 같은 리터럴은 같은 객체를 공유합니다. new String(...)은 풀 밖의 새 객체를 만듭니다. intern()으로 풀에 넣습니다.
finalize와 Cleaner
finalize는 GC 전에 호출되지만 시점이 보장되지 않습니다(비추천). 외부 자원은 AutoCloseable + try-with-resources로 해제하세요.
5.제어 흐름
if/else, switch, for/while 루프, break/continue, 삼항 연산자.
if / else
if/else는 조건으로 분기합니다. 조건은 boolean 식이어야 합니다. else-if 체인으로 다중 분기할 수 있습니다.
switch 식
switch(Java 14+)는 ->로 값을 반환하거나 case를 합칠 수 있습니다. 기존 switch 문도 화살표 구문을 사용할 수 있습니다.
for 루프
전통적 for: 초기화, 조건, 증감. 인덱스나 역방향이 필요할 때 사용합니다. 컬렉션 순회는 향상된 for를 우선하세요.
향상된 for
for-each는 배열과 Iterable 컬렉션을 인덱스 없이 순회합니다. 컬렉션 구조를 변경해서는 안 됩니다(예외 발생).
while / do-while
while은 조건을 먼저 검사하고 실행, do-while은 최소 한 번 실행합니다. 횟수가 정해지지 않은 경우(스트림 읽기, 폴링)에는 while을 사용합니다.
break와 continue
continue는 현재 회차를 건너뛰고, break는 루프를 빠져나가며, 라벨이 있는 break/continue는 중첩 루프를 제어합니다.
삼항 연산자
cond ? a : b는 if/else를 한 줄로 표현합니다. 양쪽 타입은 호환되어야 합니다. 중첩 삼항은 가독성이 떨어지니 피하세요.
return과 조기 반환
return은 메서드를 종료하고 값을 반환합니다(void는 return;). 조기 반환은 메서드를 읽기 쉽게 합니다(가드 절).
6.메서드와 람다
메서드 시그니처, 매개변수, 오버로딩, 재귀, 람다, 함수형 프로그래밍.
메서드 정의
메서드 = 접근 제한자 + 반환 타입 + 이름 + 매개변수 목록 + 본문. void는 반환값이 없음을 의미합니다.
인자 전달
Java는 항상 값 전달입니다: 기본 타입은 값의 복사본, 참조 타입은 참조의 복사본이 전달됩니다(멤버 변경은 호출자에 영향, 참조 재대입은 영향 없음).
가변 인자
...(가변 인자)는 같은 타입의 임의 개수 인자를 받으며, 본질적으로 배열입니다. 매개변수 목록의 마지막에 하나만 둘 수 있습니다.
메서드 오버로딩
같은 이름에 매개변수 목록(개수/타입)이 다른 메서드는 오버로딩입니다. 인자 타입에 따라 가장 일치하는 버전이 선택됩니다. 반환 타입은 구분에 포함되지 않습니다.
재귀
메서드가 자신을 호출하는 것이 재귀입니다. 기저 조건이 없으면 호출 스택이 오버플로합니다.
람다식
람다는 (매개변수) -> 식이며, 함수형 인터페이스의 인스턴스입니다. 타입 추론과 단일 매개변수 괄호는 생략 가능합니다.
메서드 참조
:: 메서드 참조는 람다의 단축형입니다: ClassName::staticMethod, obj::instanceMethod, ClassName::new.
함수형 인터페이스
추상 메서드가 하나만 있는 인터페이스는 람다 타깃이 될 수 있습니다. 대표: Runnable, Function, Consumer, Predicate, Supplier.
Stream API
Stream은 컬렉션을 체인으로 처리합니다: filter, map, collect. Lazy하며 원본을 변경하지 않습니다.
7.문자열
문자열 리터럴, 연결, StringBuilder, 자주 쓰는 메서드, 포맷팅.
문자열 리터럴
큰따옴표 문자열, \n 이스케이프, 그리고 Java 15+의 텍스트 블록은 큰따옴표 3개로 여러 줄을 그대로 유지합니다.
연결
+로 문자열을 연결하며, 다른 타입과 연결하면 자동으로 문자열로 변환됩니다. 적은 횟수라면 충분하고, 루프 내에서는 StringBuilder를 사용하세요.
자주 쓰는 메서드
자주 쓰는 메서드: length, substring, indexOf, replace, split, trim, 대소문자 변환.
StringBuilder
대량 연결은 StringBuilder(스레드 비안전) 또는 StringBuffer(스레드 안전)를 사용합니다: append 후 toString.
포맷팅
String.format: %d 정수, %s 문자열, %.2f 소수, %n 줄바꿈. 폭과 플래그도 지원합니다.
정규식 매칭
String.matches는 전체 매칭, replaceAll은 정규식 치환, split은 정규식 분할. 정규식 메타문자 이스케이프에 주의하세요.
문자 처리
charAt로 문자를 가져오고, Character.isDigit/isLetter/isWhitespace로 분류합니다. 문자열은 불변이지만 문자는 순회 가능합니다.
문자열 변환
Integer.parseInt는 문자열을 숫자로, valueOf/toString은 숫자를 문자열로 변환합니다. 실패 시 NumberFormatException이 발생합니다.
8.컬렉션과 Stream
List/Set/Map/Queue의 일반 구현, 순회, Stream, 정렬.
List
List는 순서 있는 컬렉션. ArrayList는 배열 기반(조회 빠름), LinkedList는 연결 리스트 기반(삽입/삭제 빠름). List.of는 불변 리스트입니다.
Set
Set은 중복을 제거합니다. HashSet은 무순서 O(1), LinkedHashSet은 삽입 순서 유지, TreeSet은 정렬. 중복 add는 false를 반환합니다.
Map
Map은 키-값 매핑. HashMap은 O(1), LinkedHashMap은 삽입 순서 유지, TreeMap은 키 기준 정렬. getOrDefault로 안전하게 조회합니다.
Queue / Deque
Queue는 FIFO(offer/poll/peek), Deque는 양쪽 끝 큐(addFirst/addLast). ArrayDeque가 LinkedList보다 빠릅니다.
순회와 반복
향상된 for / Iterator / forEach로 컬렉션을 순회합니다. 순회 중 삭제는 Iterator.remove 또는 모아둔 뒤 삭제합니다.
정렬
List.sort 또는 Collections.sort로 정렬, Comparator로 순서를 정의, comparing으로 체이닝합니다.
Stream 체이닝
filter/map/sorted/distinct/limit를 체인으로 연결하고, 최종 연산이 실행을 트리거합니다. collect로 다시 컬렉션으로 모읍니다.
그룹화와 집계
Collectors.groupingBy는 키로 그룹화, partitioningBy는 boolean으로 분할, summarizingInt는 통계를 냅니다.
불변 컬렉션
List.of, Set.of, Map.of는 불변 컬렉션을 만듭니다. Collections.unmodifiableList는 읽기 전용 뷰를 감쌉니다.
9.메모리와 성능
GC, 약한 참조, 메모리 누수, 문자열 연결 성능, 버퍼.
문자열 연결 성능
루프 내 + 연결은 매번 (불변의) String을 새로 만듭니다. StringBuilder로 한 번에 모으면 성능이 크게 향상됩니다.
약한 참조와 부드러운 참조
WeakReference는 GC를 막지 않습니다(캐시용), SoftReference는 메모리 부족 시에만 회수, PhantomReference는 회수 후 정리합니다.
메모리 누수
흔한 누수: 정적 컬렉션이 객체를 보유, 자원을 닫지 않음, 리스너 미해제, ThreadLocal 미정리. 긴 수명의 보유자가 짧은 수명의 객체를 붙잡지 않도록 합니다.
ThreadLocal
ThreadLocal은 스레드마다 독립된 변수 사본을 둡니다. 웹 컨테이너 스레드 풀에서는 remove()를 잊으면 요청 간 누수가 발생합니다.
ByteBuffer
ByteBuffer의 다이렉트 메모리(allocateDirect)는 GC 압력을 줄여 NIO와 대량 전송에 적합합니다. 수동 관리가 필요합니다.
OutOfMemoryError
OOM은 메모리 고갈을 뜻합니다: Heap Space 포화, Metaspace 클래스 과다, Direct buffer 과다. JVM 플래그를 조정하거나 누수를 찾으세요.
배열 복사
System.arraycopy는 배열 구간을 빠르게 복사합니다. Arrays.copyOf는 복사하고 필요 시 늘립니다. 수동 루프는 느립니다.
객체 풀 재사용
큰 객체를 자주 생성하면 GC 압력이 커집니다. 객체 풀로 재사용 인스턴스를 캐시하지만, 스레드 안전과 반환 경로에 주의하세요.
10.객체 지향
클래스, 캡슐화, 상속, 다형성, 추상 클래스, 인터페이스, 접근 제한자.
클래스와 객체
class는 데이터 타입을 정의합니다: 필드는 상태, 메서드는 동작, 생성자는 초기화, new는 인스턴스 생성.
캡슐화
필드는 private, 메서드는 public으로 접근을 제어합니다. getter/setter에 검증 로직을 넣어 불변식을 보호합니다.
상속
extends는 베이스 클래스를 상속합니다. Java는 단일 상속입니다. super로 부모 생성자/메서드를 호출하며, 자식은 부모의 일종(is-a)입니다.
다형성
부모 클래스/인터페이스 참조가 자식 인스턴스를 가리키고, 가상 메서드는 실제 타입으로 디스패치됩니다. @Override로 명시하세요.
추상 클래스
abstract 클래스는 인스턴스화할 수 없으며, abstract 메서드를 가질 수 있습니다(자식이 반드시 구현). 상태를 공유하는 템플릿 베이스로 사용합니다.
인터페이스
interface는 계약을 정의합니다: 메서드는 기본적으로 public abstract. Java 8+에서 default/static 메서드가 추가되었고, 다중 구현 가능합니다.
접근 제한자
public은 전체 공개, protected는 패키지+자식, 기본은 패키지, private는 같은 클래스만. 클래스 멤버는 기본적으로 패키지 비공개.
static 멤버
static 필드/메서드는 클래스 소속이며 인스턴스 소속이 아닙니다. static 메서드는 인스턴스 멤버에 접근할 수 없습니다. static 블록으로 초기화합니다.
내부 클래스와 익명 클래스
내부 클래스, 익명 클래스, 람다는 콜백을 간결하게 합니다. static 내부 클래스는 외부 인스턴스를 잡지 않아 메모리 누수를 피합니다.
11.예외 처리
try/catch/finally, 예외 계층, 검사/비검사 예외, try-with-resources, 사용자 정의 예외.
try / catch / finally
try는 오류 가능 코드, catch는 처리, finally는 성공/실패 상관없이 실행(자원 정리). 예외는 상위로 전파됩니다.
다중 catch
여러 catch는 타입으로 매칭되며, 구체적인 예외를 먼저, 광범위한 예외를 뒤에 둡니다. 멀티 catch | 로 관련 없는 타입을 묶을 수 있습니다.
throw와 재throw
throw new는 예외를 던집니다. catch 안의 throw;(Java 7+)는 원본을 그대로 재던지며 스택을 유지합니다. 메서드의 throws로 검사 예외 가능성을 선언합니다.
사용자 정의 예외
사용자 정의 예외는 Exception(검사) 또는 RuntimeException(비검사)을 상속합니다. 관례상 클래스명은 Exception으로 끝냅니다.
검사 예외와 비검사 예외
검사 예외(IOException 등)는 catch 또는 선언이 필수이며, 비검사 예외(RuntimeException 계열)는 컴파일 시 강제되지 않습니다.
try-with-resources
try (resource) { }는 AutoCloseable.close()를 자동으로 호출하며, 예외 시에도 닫습니다. 수동 finally 닫기를 대체합니다.
예외의 비용
예외 포획은 비용이 크므로(스택 워킹) 제어 흐름에 쓰지 마세요. 예측 가능한 오류는 반환값, null 체크, Optional을 사용합니다.
로깅과 예외
예외는 (스택과 함께) 로깅하고, System.out으로 찍고 넘기지 마세요. 로깅 프레임워크(SLF4J + Logback)로 레벨별 출력합니다.
12.파일과 IO
Files/Path 기반 모던 IO, Scanner, Reader/Writer, 스트림 읽기.
Files 읽기/쓰기
java.nio.file.Files는 모던 API: readString/writeString, readAllLines, copy/move/delete.
Scanner 입력
Scanner는 콘솔이나 파일을 읽습니다: nextLine은 한 줄, nextInt/nextDouble은 타입별. hasNext로 입력 잔여를 확인합니다.
Reader / Writer
문자 스트림으로 텍스트를 입출력: BufferedReader로 줄 단위 읽기, BufferedWriter로 쓰기, try-with-resources로 자동 닫기.
바이트 스트림
InputStream/OutputStream은 바이트 단위: FileInputStream, BufferedInputStream으로 버퍼링. 데이터 이동에는 transferTo.
콘솔 IO
System.out은 출력, System.in은 입력, System.err은 오류. printf로 포맷 출력.
Path 경로
Path는 경로를 나타냅니다. resolve로 결합, getFileName으로 이름, toAbsolutePath로 절대 경로, exists로 존재 확인, Files.walk로 재귀 순회.
직렬화
ObjectOutputStream/ObjectInputStream으로 객체를 직렬화(클래스는 Serializable 구현 필요). 실무에서는 JSON이 더 흔합니다.
임시 파일
Files.createTempFile은 시스템 임시 디렉터리에 파일을 만듭니다. 사용 후 Files.deleteIfExists로 정리해 잔여를 남기지 마세요.
13.자주 겪는 함정 (FAQ)
Java 개발자가 가장 자주 겪는 함정: == vs equals, 박싱 캐시, 동시성, 예외, 컬렉션 변경.
== vs equals
문자열/객체의 내용 비교는 반드시 equals를, ==는 참조 비교입니다. 리터럴 풀로 ==가 우연히 true가 될 수 있지만 의존하면 안 됩니다.
Integer 캐시 풀
자동 박싱된 -128~127은 캐시되어 ==가 true일 수 있으나, 범위를 벗어나면 false입니다. 객체 비교는 항상 equals를 쓰세요.
null 체크와 NPE
null에 대해 메서드를 호출하면 반드시 NPE가 납니다. nullable 값은 Optional 또는 사전 null 체크로 처리하고, 여기저기 try-catch NPE를 쓰지 마세요.
예외 삼키기
catch 후 아무 처리도 하지 않으면 예외를 삼키는 것이며 디버깅이 어렵습니다. 최소한 로깅하거나 적절한 예외로 감싸 재던지세요.
equals와 hashCode
equals를 오버라이드하면 hashCode도 반드시 오버라이드해야 합니다. 그렇지 않으면 HashSet/HashMap 동작이 깨집니다(논리적으로 같은 객체가 다른 키로 취급).
순회 중 삭제
향상된 for 안에서 List.remove를 호출하면 ConcurrentModificationException이 발생합니다. Iterator.remove 또는 모아둔 뒤 삭제하세요.
날짜의 가변성
구 Date/Calendar는 가변이라 오류가 많습니다. java.time(LocalDate, LocalDateTime)으로 통일하면 불변이고 안전합니다.
스레드 안전성
HashMap/ArrayList는 스레드 안전하지 않아 다중 스레드 쓰기에서 깨집니다. ConcurrentHashMap 또는 동기 래퍼를 사용하세요.
Stream의 null
Stream 요소가 null이면 filter/map에서 NPE가 날 수 있습니다. 먼저 filter(Objects::nonNull)로 거르세요.
루프 내 연결
루프 내 += 연결은 중간 String을 대량 생성해 느립니다. StringBuilder를 사용하세요.
14.동시성과 스레드
Thread, synchronized, 스레드 풀 (ExecutorService), CompletableFuture.
Thread
Thread 또는 Runnable로 스레드를 만들고, start로 시작, join으로 대기, sleep으로 일시정지합니다. 대부분의 경우 스레드 풀이 더 적합합니다.
synchronized
synchronized는 락으로 상호배제를 보장합니다. 인스턴스 메서드는 this, 정적 메서드는 Class를 잠그고, 블록은 임의 객체를 잠글 수 있습니다.
volatile
volatile은 가시성(다른 스레드에서 즉시 보임)을 보장하지만 원자성은 보장하지 않습니다. 플래그는 volatile, 카운터는 AtomicInteger.
스레드 풀
ExecutorService는 스레드 재사용을 관리합니다. newFixedThreadPool / newCachedThreadPool을 쓰고, 끝나면 shutdown을 호출합니다.
Future와 Callable
Callable은 반환값이 있는 태스크, Future.get은 결과를 블록해 가져옵니다. FutureTask는 수동 제어가 가능합니다.
CompletableFuture
비동기 조합: thenApply로 변환, thenCombine으로 결합, allOf로 다수 대기. 콜백은 체인되며 호출 스레드를 막지 않습니다.
동시성 컬렉션
ConcurrentHashMap, CopyOnWriteArrayList, BlockingQueue는 스레드 안전합니다. 수동 락의 일반 컬렉션보다 이들을 우선하세요.
Lock 인터페이스
ReentrantLock은 synchronized보다 유연합니다: 타임아웃, 인터럽트, 공정. finally에서 반드시 unlock해야 합니다.
15.네트워크와 HTTP
HttpClient, URL 요청, JSON 직렬화, WebSocket.
HttpClient 기본
java.net.http.HttpClient(Java 11+)로 HTTP 요청을 보냅니다. send는 동기, sendAsync는 비동기. 빌더로 설정합니다.
POST와 JSON
JSON 바디를 가진 POST 요청. Jackson 또는 Gson으로 JSON을 (역)직렬화합니다.
비동기 요청
sendAsync는 CompletableFuture를 반환하며 호출 스레드를 막지 않습니다. 다중 요청을 thenApply로 병렬 처리합니다.
URL과 URLConnection
구 API인 URL/HttpURLConnection은 단순 요청용. 대부분은 HttpClient가 더 간결합니다. 쿼리 파라미터는 URL 인코딩이 필요합니다.
JSON 파싱
Jackson과 Gson이 주류 JSON 라이브러리입니다. @JsonProperty로 필드명을 매핑하고, Java 17의 record와 결합할 수 있습니다.
Web API 호출
조합: 요청 구성 → 상태 코드 확인 → 역직렬화. 404/500 같은 비성공 상태를 처리합니다.
WebSocket
java.net.http.WebSocket은 양방향 장기 연결입니다. Listener 콜백으로 메시지를 받고, onOpen/onText에서 처리합니다.
타임아웃과 재시도
HttpRequest.timeout은 요청 타임아웃, HttpClient.connectTimeout은 연결 타임아웃입니다. 타임아웃 시 HttpTimeoutException이 발생합니다.
16.날짜와 시간
java.time 로컬 날짜/시간, Instant, Duration/Period, 포맷팅.
LocalDate
LocalDate는 날짜만(시간 없음): now, of, plusDays, minusMonths. 불변이며 스레드 안전합니다.
LocalTime
LocalTime은 시간만(날짜 없음): now, of, plusMinutes. LocalDate와 합쳐 LocalDateTime을 만듭니다.
Instant 타임스탬프
Instant는 UTC 시점(에포크 초/나노초)이며, 타임존을 넘나드는 저장에 적합합니다. 시스템 시각은 System.currentTimeMillis를 사용합니다.
Duration과 Period
Duration은 시간 기반 양(초/나노초), Period는 날짜 기반 양(년/월/일)입니다.
포맷과 파싱
DateTimeFormatter로 포맷과 파싱. ISO 등 내장 포맷과 yyyy-MM-dd HH:mm:ss 같은 커스텀 패턴을 지원합니다.
시간대
ZonedDateTime은 시간대를 포함하고, ZoneOffset는 고정 오프셋입니다. ZoneId.systemDefault는 로컬. 저장은 UTC로 합니다.
구 API 변환
java.util.Date/Calendar와 새 API의 상호 변환. Date는 가변이고 오류가 많으니 새 코드는 java.time을 사용하세요.
타임스탬프 유틸
System.currentTimeMillis는 밀리초, nanoTime은 나노초 차이(간격 측정 전용, 절대 시각 아님). 타임스탬프와 포맷 간 상호 변환.
17.프로세스와 시스템
ProcessBuilder로 프로세스 시작, 시스템 속성, 환경 변수, 런타임 정보.
ProcessBuilder
ProcessBuilder는 외부 프로그램을 실행합니다. 인자는 리스트로 전달해 인젝션을 피하세요. redirectErrorStream으로 출력을 합칩니다.
시스템 속성
System.getProperty로 JVM 시스템 속성을 읽습니다: user.home, java.version, os.name. setProperty로 설정합니다.
환경 변수
System.getenv는 환경 변수를 읽습니다(읽기 전용), getenv()는 전부. 시스템 속성과 환경 변수를 구분하세요.
Runtime 정보
Runtime은 JVM 정보를 제공합니다: availableProcessors, maxMemory, totalMemory. gc()는 힌트입니다.
명령줄 인수 파싱
main args에서 옵션을 파싱: 단순한 경우 수동 루프, 복잡하면 picocli/JCommander 라이브러리.
셧다운 훅
Runtime.addShutdownHook은 JVM 종료 시 정리를 등록합니다. System.exit도 트리거합니다. 훅에서 무거운 작업은 피하세요.
작업 디렉터리
user.dir 시스템 속성은 프로세스의 현재 작업 디렉터리입니다. ProcessBuilder.directory로 자식 프로세스의 시작 디렉터리를 지정합니다.
시스템 플랫폼 정보
시스템 속성은 플랫폼 정보를 제공합니다: os.name(OS), os.arch(아키텍처), file.separator(경로 구분자), line.separator(줄바꿈).
18.정규 표현식
Pattern/Matcher, 매칭, 캡처 그룹, 치환, 자주 쓰는 패턴.
Pattern과 Matcher
Pattern.compile로 정규식을 컴파일(캐시·재사용)하고, matcher로 텍스트에 매칭합니다. find, matches, lookingAt 세 가지가 있습니다.
캡처 그룹
괄호는 부분 문자열을 캡처하고, group(1)은 첫 그룹, 명명 그룹 (?<name>...)은 group("name")을 씁니다. find 루프로 전부 추출합니다.
전체 검색
find 루프 또는 matcher.results로 전체 매치를 얻습니다. 전체 치환은 replaceAll($1 같은 그룹 참조 가능).
치환
replaceAll / replaceFirst은 정규식으로 치환하며 $1/$2로 그룹을 참조합니다. Matcher.appendReplacement는 구간별로 처리합니다.
Pattern 플래그
Pattern.CASE_INSENSITIVE는 대소문자 무시, MULTILINE은 ^/$를 줄마다, DOTALL은 .이 줄바꿈에도 매칭되도록 합니다.
자주 쓰는 패턴
이메일, URL, IP, 휴대폰의 자주 쓰는 정규식. 운영 환경의 검증(실제 이메일 등)은 전용 라이브러리를 사용하세요.
수량자와 앵커
* 0회 이상, + 1회 이상, ? 0 또는 1회, {n,m} 지정 횟수. ^ 줄 시작, $ 줄 끝, \b 단어 경계.
전방탐색과 후방탐색
전방탐색 (?=...)은 뒤를 살피고, 부정 전방탐색 (?!...)은 뒤를 제외하며, 후방탐색 (?<=...)은 앞을 살핍니다. 모두 문자를 소비하지 않습니다.
19.빌드와 디버깅
Maven/Gradle, javac/jar, JUnit, JVM 디버깅.
Maven 라이프사이클
mvn compile/test/package/install은 Maven 라이프사이클 단계입니다. target 디렉터리에 class와 jar가 출력됩니다.
pom.xml
pom.xml은 프로젝트를 정의합니다: groupId/artifactId/version 좌표, dependencies, properties.
Gradle
Gradle은 Groovy/Kotlin DSL 기반입니다. task가 빌드 단계를 정의하고, 의존성은 중앙 저장소에서 해석됩니다.
JUnit 테스트
JUnit 5: @Test는 테스트 메서드, @BeforeEach는 초기화, assert*는 단언. mvn test로 실행.
jar 패키징
jar 명령으로 class를 패키징. 실행 가능 jar는 매니페스트에 Main-Class가 필요합니다. java -jar로 실행.
JVM 플래그
-Xmx 최대 힙, -Xms 초기 힙, -XX:+PrintGCDetails GC 로그, -D 시스템 속성.
로깅 설정
SLF4J를 파사드, Logback을 구현으로. logback.xml에서 레벨과 출력을 설정. 운영에서는 System.out 사용 금지.
의존성 관리
Maven 의존성은 scope로 분류: compile/test/runtime. exclusions로 전이 의존을 제외하고, 버전 충돌은 dependencyManagement에서 통일합니다.
이 치트시트에 대해
이 페이지는 Java 17(LTS)의 자기 완결형 빠른 참조로, 언어 핵심, JDK의 자주 쓰는 라이브러리, 빌드 생태계가 실제 프로젝트에서 차지하는 일상 사용의 약 80%를 다룹니다. 내용은 모던한 관용구를 중심으로 합니다: var 지역 변수 타입 추론, switch 식, 텍스트 블록, record, sealed 클래스, Stream API. Java는 1995년 Sun Microsystems가 출시했으며, "한 번 작성하고 어디서나 실행"하는 JVM 생태계로 유명하고, 엔터프라이즈 백엔드, Android 개발, 빅 데이터에서 가장 널리 쓰이는 언어 중 하나입니다. 19개 섹션은 각각 한 주제에 집중합니다: 기본 문법, 변수, 타입과 참조, 제어 흐름, 함수, 문자열, 컬렉션 프레임워크(List/Set/Map), 메모리 관리(GC), 객체 지향, 예외 처리, 입출력, 흔한 실수, 동시성, 네트워크, 시간, 프로세스, 정규식, 빌드 도구(Maven/Gradle). 각 서브섹션은 "개념 소개 + 바로 복사할 수 있는 코드 스니펫"의 짝으로 구성됩니다. 모든 코드와 텍스트는 브라우저에서 로컬로 렌더링되며, 어떤 데이터도 기기를 떠나지 않습니다. 권위 있는 참조는 Oracle 공식 Java 문서를 보세요.
버전 2.1.0