Java 추가 문법의 제한적 포함
짧은 코드에서 타입과 호출 결과를 확인할 범위로만 학습한다.
실기 학습 목표
짧은 코드에서 타입과 호출 결과를 확인할 범위로만 학습한다.
핵심 이론
제네릭은 타입 매개변수를 사용하는 기본 형식과 주어진 객체·배열의 참조 관계만 확인한다. 타입 소거와 오버로딩을 결합한 세부 문제는 기본 출제에서 제외한다.
enum의 values()는 선언 순서의 상수 배열, name()은 선언된 이름, ordinal()은 0부터의 순서다. toString()은 재정의될 수 있어 name()과 항상 같지는 않다.
람다는 하나의 추상 메서드를 갖는 함수형 인터페이스의 구현으로 사용된다. 매개변수와 반환식의 타입을 확인하고, 캡처하는 지역변수는 final 또는 사실상 final이어야 한다.
Runnable.run()을 직접 호출하면 현재 스레드에서 실행한다. Thread.start()는 새 스레드 실행을 시작한다. 동기화·join 등 순서 보장이 없으면 병렬 출력의 하나의 고정 순서를 단정하지 않는다. 고급 제네릭 증명과 동시성 라이브러리 내부는 여기서 확장하지 않는다.
추가 문법도 기본 호출과 배열 규칙으로 읽는다
enum은 이름이 있는 제한된 값들의 집합이다. WAIT·LOAD·RUN·STOP 네 상수가 선언되면 ordinal은 각각 0·1·2·3이다. values()로 얻은 배열에서 인덱스를 선택하고 name()으로 이름을 출력하는 흐름을 일반 배열 문제처럼 계산한다. enum에 필드가 있으면 상수별 필드 값을 함께 적는다.
람다 x -> x+3은 전달받은 x로 계산해서 결과를 돌려주는 간단한 동작이다. 실행 시점은 람다를 만들 때가 아니라 함수형 인터페이스의 메서드를 호출할 때다. 캡처한 배열의 원소는 나중에 바뀔 수 있으므로 두 번 호출했다면 각 호출 시점의 원소 값을 읽는다.
| 작업 | 추적할 대상 |
|---|---|
| enum 순환 | 이전 ordinal, 이동량, 나머지, 새 상수 |
| 람다 호출 | 전달 인수, 캡처한 객체의 현재 값, 반환 |
| Holder<int[]> | Holder 객체와 그 안의 배열 참조를 각각 표시 |
| run/start/join | 현재 스레드 호출인지, 새 실행 시작인지, 완료 대기인지 |
join 이후에는 대상 스레드가 종료되었으므로 그 완료가 보장된 뒤의 상태를 읽는다. 반대로 별도 순서 보장이 없는 병렬 출력을 하나로 확정하지 않는다. 여기서는 기본 문법과 객체 공유만 다룬다. 제네릭 타입 소거에 의한 오버로딩 선택과 이미 끝난 스레드의 재시작 예외 같은 세부 규칙 암기는 제외한다.
풀이 예시
다음 Java 17 프로그램이 표준 출력에 기록하는 내용을 쓰시오. 마지막 줄바꿈의 유무는 답안에서 구별하지 않는다.
public class Main {
enum Phase { WAIT, LOAD, RUN, STOP }
public static void main(String[] args) {
Phase p = Phase.LOAD;
int[] jumps = {2, 3, 1};
for (int j : jumps)
p = Phase.values()[(p.ordinal() + j) % Phase.values().length];
System.out.println(p.name());
}
}
예시 정답
STOP
풀이 과정
LOAD의 ordinal은 1이다. 이동 후 인덱스는 (1+2)%4=3, (3+3)%4=2, (2+1)%4=3이다. 3번 열거 값은 STOP이다.
답안 점검
위 풀이 예시의 답을 가린 뒤, 핵심 이론의 규칙을 적용해 직접 풀어 보세요. 코드와 계산 문제는 중간값·단위·최종 출력의 순서를, 용어 문제는 지문의 핵심 단서와 답의 의미를 점검하세요. 해설과 다른 부분이 있으면 어느 조건을 놓쳤는지 확인하고 연결된 실기 문제로 다시 연습하세요.