왜 Java를 쓰는가
Java가 지금도 널리 쓰이는 이유와, 문법보다 플랫폼과 생태계 관점에서 어떤 강점을 가지는지 정리합니다.
Category Reference
기본문법, 객체지향, 컬렉션, 제네릭, 예외, 스트림, 동시성, 테스트, 빌드 도구까지 Java의 핵심 흐름을 카드형 레퍼런스로 정리합니다.
제목, 요약, 태그, 섹션 제목 기준으로 찾습니다.
섹션
1 cards
Java가 지금도 널리 쓰이는 이유와, 문법보다 플랫폼과 생태계 관점에서 어떤 강점을 가지는지 정리합니다.
4 cards
package com.example.app;
import java.util.List;
public class Main {
public static void main(String[] args) {
System.out.println("Hello, Java");
}
}Java 프로그램의 기본 단위인 package, import, 클래스 파일 구조, `main` 메서드 의미를 정리합니다.
int count = 3;
double price = 19.99;
boolean active = true;
String name = "RefDock";Java의 primitive type, 참조 타입, 변수 선언과 초기화 규칙, 자동 형변환 감각을 정리합니다.
for (int i = 0; i < 5; i++) {
System.out.println(i);
}Java의 `if`, `switch`, `for`, `while`을 어떤 상황에 고르는지와 기본 제어 흐름 감각을 정리합니다.
String[] names = {"Kim", "Lee", "Park"};
for (String name : names) {
System.out.println(name);
}Java의 배열과 `String`을 함께 보면서 길이, 변경 가능성, 순회 방식, 자주 하는 실수를 정리합니다.
4 cards
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
}Java 객체지향의 출발점인 class, field, method, constructor, instance 개념을 한 흐름으로 정리합니다.
class Animal {
void speak() {
System.out.println("...");
}
}
class Dog extends Animal {
@Override
void speak() {
System.out.println("woof");
}
}상속이 코드 재사용을 넘어서 타입 관계를 어떻게 만들고, 다형성이 왜 중요한지 정리합니다.
interface Payable {
int pay();
}
abstract class Employee implements Payable {
protected String name;
}공통 계약을 표현하는 interface와 부분 구현을 제공하는 abstract class를 어떻게 구분할지 정리합니다.
public final class User implements Comparable<User> {
private final long id;
private final String email;
public User(long id, String email) {
this.id = id;
this.email = email;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof User other)) return false;
return id == other.id && Objects.equals(email, other.email);
}
@Override
public int hashCode() {
return Objects.hash(id, email);
}
@Override
public int compareTo(User other) {
return Long.compare(this.id, other.id);
}
}객체 비교에서 참조 비교와 값 비교가 어떻게 다르고, equals/hashCode/Comparable 계약을 어떻게 맞춰야 하는지 정리합니다.
3 cards
List<String> names = new ArrayList<>();
names.add("Kim");
String first = names.get(0);Java 제네릭이 왜 필요한지, `List<String>` 같은 타입 매개변수가 컴파일 타임 안전성을 어떻게 높이는지 정리합니다.
List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
Map<String, Integer> map = new HashMap<>();Java Collections Framework의 핵심인 `List`, `Set`, `Map`을 어떤 상황에 고르는지 정리합니다.
users.sort(Comparator
.comparing(User::getAge)
.thenComparing(User::getName));
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}List와 Map을 어떻게 순회하고, 정렬 기준을 Comparable과 Comparator 중 어디에 둘지 정리합니다.
2 cards
try {
Files.readString(path);
} catch (IOException e) {
System.out.println("읽기 실패: " + e.getMessage());
}Java 예외 모델의 핵심인 checked exception과 unchecked exception 차이, `try-catch-throws` 흐름을 정리합니다.
Path path = Path.of("notes.txt");
try (BufferedReader reader = Files.newBufferedReader(path)) {
System.out.println(reader.readLine());
}`try-with-resources`가 왜 중요한지와 `Files`, `Path`를 이용한 기본 파일 처리 흐름을 정리합니다.
4 cards
names.sort((a, b) -> a.compareToIgnoreCase(b));
names.forEach(System.out::println);Java의 lambda expression과 method reference가 어떤 문제를 줄이고, 함수형 스타일과 어떻게 연결되는지 정리합니다.
List<String> result = names.stream()
.filter(name -> name.length() >= 3)
.map(String::toUpperCase)
.toList();Java Stream이 컬렉션과 어떻게 다르고, pipeline, intermediate, terminal operation을 어떻게 읽어야 하는지 정리합니다.
Optional<User> user = findUser(id);
String name = user.map(User::getName)
.orElse("anonymous");`Optional`이 null 자체를 없애는 도구가 아니라, 값이 없을 수 있음을 더 명시적으로 표현하는 방법이라는 점을 정리합니다.
record Point(int x, int y) {}
enum Role {
ADMIN, USER
}현대 Java에서 자주 만나는 `record`, `enum`, switch expression 같은 문법이 어떤 문제를 줄이는지 정리합니다.
3 cards
Runnable task = () -> {
System.out.println("work on " + Thread.currentThread().getName());
};
Thread thread = new Thread(task, "worker-1");
thread.start();
thread.join();Java 스레드가 무엇인지, Thread와 Runnable의 역할이 어떻게 다르고 lifecycle을 어떻게 읽어야 하는지 정리합니다.
ExecutorService pool = Executors.newFixedThreadPool(4);
Future<Integer> future = pool.submit(() -> 40 + 2);
int value = future.get();
pool.shutdown();직접 Thread를 만드는 방식과 thread pool 기반 실행 방식이 어떻게 다르고, Callable/Future를 왜 함께 쓰는지 정리합니다.
public class Counter {
private int value;
public synchronized void increment() {
value++;
}
public synchronized int getValue() {
return value;
}
}여러 thread가 같은 상태를 건드릴 때 왜 문제가 생기고, synchronized와 lock을 어떤 기준으로 고를지 정리합니다.
2 cards
class CalculatorTest {
@Test
void add_returnsSum() {
Calculator calculator = new Calculator();
int result = calculator.add(2, 3);
assertEquals(5, result);
}
}Java 테스트에서 JUnit이 어떤 역할을 하고, 테스트 메서드, assertion, fixture를 어떻게 조직하는지 정리합니다.
src/
main/
java/
test/
java/
pom.xml # Maven
build.gradle # GradleJava 프로젝트에서 Maven과 Gradle이 무엇을 해 주는지, dependency 관리와 build 흐름을 어떤 관점으로 이해하면 좋은지 정리합니다.