static 은 하나뿐이고, 예외는 catch 로 뛰고 finally 는 무조건이며, == 는 주소이고 참조 복사는 같은 집이다
왜 이걸 하나 — Java 34문항 중 17문항이 이 장이고, 2024년 3회 · 2025년 2회에는 3문항씩 나왔다.
11회분 220문항 중 이 장의 기출은 17문항이다. 11회 중 10회에 나왔고(2023년 3회만 빠짐 — 그 회차의 컴파일 오류 문제가 여기 있다), 2025년 이후 람다 · enum · 제네릭 같은 새 문법이 섞이기 시작했다. 훈련 Java 20문항이 붙는다.
| 꼴 | 몇 문항 | 무엇을 적나 | 보기 |
|---|---|---|---|
| static · 싱글톤 | 3 | 공유되는 값 · 컴파일 오류 줄 | 2023-1회 1번 · 2023-3회 12번 · 2024-1회 1번 |
| 예외 흐름 | 3 | catch 선택 · finally · 람다 안의 throw | 2024-3회 16번 · 2025-1회 5번 · 2025-2회 9번 |
| == · equals · 참조 | 5 | 문자열 비교 · 배열 참조 · 객체 배열 교환 | 2023-2회 8번 · 2024-2회 1번 · 2024-3회 1번 · 2025-2회 5번 · 15번 |
| 문자열 · 배열 처리 | 3 | split · charAt · 재귀 역순 중복 제거 · 연결 순서 | 2024-2회 17번 · 20번 · 2026-1회 17번 |
| 재귀 · enum | 3 | 음수까지 내려가는 재귀 · 이분 재귀 · enum values | 2025-1회 16번 · 2025-3회 5번 · 2026-2회 14번 |
→ == 와 참조가 5문항으로 가장 많다. new 한 것끼리 == 는 false(2024년 2회 1번 NNN), 리터럴끼리는 true(2023년 2회 8번), 배열 · 객체는 대입하면 같은 집(2025년 2회 5번 · 15번) — 세 문장이 이 다섯을 다 푼다.
E01 진단의 14번(compute(5) → 1)이 이 장이다. 종료 조건이 num <= 1 이라 음수까지 내려가는 재귀였고, 「종료 조건에서 무엇을 돌려주나」를 안 보면 답이 바뀐다. 실무에서는 안 쓰는 꼴이지만 시험은 이런 자리를 고른다.
문항 수는 이 노트의 문제 데이터에서 ch=E06 인 것을 센 값이다(2026-09-14). 기출 코드는 grandlife.co.kr 복원에서 옮겼고, 17문항 전부 JDK 17 로 실행하거나 컴파일해 정답을 확인했다. 컴파일 오류 문제(2023-3회 12번)는 javac 가 7번 줄에서 오류를 내는 것을 확인했다.
왜 이걸 하나 — 시험 전날 규칙 9개를 다시 본다.
클래스명.변수 로도 접근. static 메서드에서 인스턴스 변수를 직접 쓰면 컴파일 오류. 싱글톤은 static 인스턴스 하나를 getInstance 로 돌려준다.new String("A") == new String("A") 는 false. 내용 비교는 equals.int[] b = a; 는 같은 배열. b[0] = 9 면 a[0] 도 9. a.clone() 은 새 배열. 객체도 같다 — 메서드 안에서 words[0] = label 은 밖에 반영, label = "Z" 는 지역 참조만 바뀜.+ 는 왼쪽부터. 숫자 + 숫자는 덧셈, 문자열이 한 번 끼면 그 뒤는 전부 연결. 9 + 2 + "2" + "3" = "1123". char + int 는 숫자.length() · charAt(i) · substring(a, b)(b 미포함) · indexOf · split(",") → 배열 · equals · toUpperCase · StringBuilder append · reverse.num <= 1 이면 음수도 반환). 두 갈래 재귀는 표로 아래부터. 출력이 재귀 호출 앞이면 들어가며, 뒤면 되감으며 찍힌다.value -> value + 9 는 함수형 인터페이스의 추상 메서드를 즉석 구현. 람다 안에서 던진 예외는 부른 쪽의 catch 로 간다.values() 는 전체 배열(선언 순서), ordinal() 은 0부터 순번, name() 은 이름 문자열. 생성자로 값을 붙일 수 있다.왜 이걸 하나 — 규칙 9개는 「무엇이 하나이고 무엇이 여럿인가」로 묶인다. static 은 하나, 참조가 가리키는 집도 하나, 문자열 리터럴도 하나.
static int count 는 객체마다가 아니라 클래스에 하나다. 2023년 1회 1번에서 StaticData.count = value 로 10 을 넣고, StaticData.count++ 는 10 을 찍은 뒤 11 이 되며, item.count 는 같은 static 이라 11 이다. 지역변수 value 는 10 그대로, 인스턴스 필드 item.value 는 20 → 네 줄이 10 · 11 · 10 · 20.
static 메서드는 객체 없이 도는 것이라 그 안에서 인스턴스 필드를 직접 쓸 수 없다. 2023년 3회 12번의 public static String getName() { return name; } 이 7번 줄에서 컴파일 오류인 이유다(non-static variable name cannot be referenced from a static context). 싱글톤(2024년 1회 1번)은 static 인스턴스 하나를 getInstance 로 돌려주므로 a 와 b 가 같은 객체라 add 네 번이 전부 한 value 에 쌓여 4 다.
try 안에서 예외가 나면 그 줄에서 멈추고 아래 catch 중 맞는 첫 것으로 뛴다. 2025년 1회 5번은 number / divisor 에서 ArithmeticException 이 나 첫 catch 의 출력1 을 찍고, finally 의 출력5 를 찍는다 — 출력2 · 출력4 는 안 찍힌다. catch 는 위에서부터 보므로 자식 예외를 위에 둔다.
2024년 3회 16번은 fail() 이 NullPointerException 을 던져 첫 catch 에서 +1, finally 에서 +100 → 101. Exception catch 는 첫 것이 잡았으니 건너뛴다. 2025년 2회 9번은 람다 안의 throw 가 run 의 catch 로 잡혀 7, 두 번째 람다는 3 + 9 = 12, 합 19 — 람다도 결국 메서드 호출이라 예외는 부른 쪽으로 올라간다.
Java 의 참조 변수는 집 주소를 든 쪽지다. == 는 두 쪽지에 같은 주소가 적혔는지를 묻고, equals 는 그 집의 내용이 같은지를 묻는다. 2024년 2회 1번은 new 로 만든 두 KOREA 가 다른 집이라 N, c 는 a 의 쪽지를 복사한 것이라 같은 집인데 b == c 를 물어 N, 세 번째도 새 집이라 N → NNN.
리터럴은 다르다. "Programming" 을 두 변수에 적으면 상수 풀의 같은 집이라 == 도 true 이고, new 로 만든 셋째와는 false, equals 는 셋 다 true(2023년 2회 8번, true false true true). 2024년 3회 1번은 equals 로 인접한 두 단어를 비교해 같으면 O, 다르면 A 를 찍어 OOAAA 다.
배열과 객체도 쪽지다. 2025년 2회 5번의 change 는 words[0] 을 바꿔 원본 배열의 첫 칸이 B 가 되지만, label = "Z" 는 지역 쪽지만 바꾼 것이라 밖의 label 은 B 그대로 → BB. 2025년 2회 15번은 배열 칸의 쪽지를 바꾼 뒤 boxes[1].value = boxes[0].value 로 b 의 값을 3 으로 만들어 a · b · c 가 1 · 3 · 3, 출력 1a3b3.
+ 는 왼쪽부터 계산한다. 숫자끼리는 더하고, 문자열이 한 번 끼면 그 뒤로는 전부 이어 붙인다. 2026년 1회 17번의 9 + 2 + "2" + "3" 은 11 → "112" → "1123" 이고, a + b + "결과" + a + b 는 8결과53(예상 1회 8번)이다. 괄호가 없으면 왼쪽부터라는 것만 지키면 된다.
2024년 2회 17번은 재귀로 문자열을 뒤에서부터 보며 처음 나온 글자만 남긴다(되감으며 앞에 붙이므로 dcba). 2025년 1회 16번은 배열을 반씩 나눠 가운데 값을 더하는 이분 재귀라 표를 아래부터 채워 20 이다. 2026년 2회 14번은 num <= 1 에서 num 을 그대로 돌려주므로 compute(−1) = −1 이 위로 올라와 1 이 된다 — 종료 조건이 0 이 아니라는 것을 놓치면 답이 바뀐다.
enum(2025년 3회 5번)은 values() 가 선언 순서의 배열이고 Word.B.name() 은 "B" 라 길이 1, values()[1] 은 B, getText 는 AB 다. 새 문법이 나와도 배열 첨자와 문자열 길이라는 옛 규칙으로 풀린다.
label = "Z" 는 지역 쪽지만 바꾼다. 다만 쪽지가 가리키는 집의 내용(words[0] = label)을 바꾸면 밖에서도 보인다. 2025년 2회 5번의 BB 가 이 둘의 차이다.if (num <= 1) return num; 은 −1 이 오면 −1 을 돌려주고, 2026년 2회 14번의 답 1 은 그 −1 이 더해진 결과다.왜 이걸 하나 — 코드를 보면서 쪽지와 집을 그리는 연습이다. == 가 보이면 그림부터 그린다.
변수는 쪽지, new 는 새 집으로 그린다. 예외 문제는 try 안의 줄에 번호를 붙이고 어느 번호에서 뛰는지 표시한다. 정답을 연 뒤 그림과 다른 자리가 규칙 9개 중 빠진 것이다.
다음 Java 프로그램의 실행 결과를 쓰시오.
답 — 네 줄: 10 / 11 / 10 / 20. static 인 count 는 클래스에 하나뿐이라 어디서 고치든 같은 칸이고, count++ 는 찍은 뒤에 올린다.
원리 — static 이 붙은 필드는 객체마다 따로 있지 않고 클래스에 딱 하나 있다. StaticData.count(클래스 이름으로)와 item.count(객체 이름으로)는 표기만 다르고 같은 칸이다. static 이 없는 value 는 객체마다 하나씩 생기며 new 할 때 20 으로 채워진다. main 의 지역 변수 value 는 이름만 같은 다른 칸이다. 후위 count++ 는 "지금 값을 쓰고 나서 1 올린다"라 println 에는 올리기 전 값이 찍힌다.
따라가기
헷갈리는 자리 — 첫 줄을 11 로 적는 것(++count 였다면 11). item.count 를 "객체 것이니 0"으로 보는 것 — static 은 객체 것이 아니라 클래스 것 하나다. 마지막 줄은 println 이 아니라 print 라 줄바꿈이 없다.
복원 코드를 JDK 17 로 컴파일 · 실행해 같은 출력을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 Java 프로그램의 실행 결과를 줄마다 쓰시오.
답 — true / false / true / true. == 는 같은 객체인지, equals 는 글자 내용이 같은지를 묻는다.
원리 — 자바에서 문자열 변수는 글자 자체가 아니라 글자 덩어리가 놓인 자리(참조)를 든다. "Programming" 처럼 따옴표로 쓴 글자는 같은 글자면 하나만 만들어 공유한다(문자열 풀). 그래서 first 와 second 는 같은 덩어리를 가리키고 == 가 true 다. new String(…) 은 "무조건 새 덩어리를 만들어라"이므로 third 는 다른 자리에 있고, first 와 == 하면 false 다. 내용을 견주려면 equals 를 써야 하고 그것은 세 변수 모두 true 다.
따라가기
헷갈리는 자리 — 둘째 줄을 true 로 적는 것. 글자가 같아도 new 는 새 객체다. 반대로 첫째 줄을 false 로 적는 것 — 따옴표 글자는 공유된다. == 는 "같은 집인가", equals 는 "같은 내용인가"로 나눠 외운다.
복원 코드를 JDK 17 로 컴파일 · 실행해 같은 출력을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 Java 코드에서 컴파일 오류가 발생하는 줄 번호를 쓰시오.
답 — 7번 줄. static 메서드 안에서 인스턴스 필드 name 을 읽으려 해서 컴파일이 막힌다.
원리 — 인스턴스 필드(name)는 객체가 만들어져야 생기는 칸이다. static 메서드는 객체 없이 클래스 이름만으로 불릴 수 있는 메서드라, 그 안에는 "어느 객체의 name 인가"를 가리킬 this 가 없다. 그래서 static 메서드에서 인스턴스 필드나 인스턴스 메서드를 그냥 쓰면 컴파일러가 막는다. 반대로 인스턴스 메서드 print() 는 this 가 있으니 10번 줄은 문제없다. private 은 같은 클래스 안이라 상관없다.
따라가기
return name → "non-static field cannot be referenced from a static context" → 7번 줄헷갈리는 자리 — 6번 줄(선언부)을 적는 것. 선언 자체는 오류가 아니고 그 안에서 name 을 쓴 줄이 오류다. 2번 줄의 private 을 의심하는 것 — 같은 클래스 안이라 문제없다. 고치려면 static 을 빼거나 name 을 static 으로 만들면 된다.
복원 코드를 JDK 17 로 컴파일해 그 줄에서 오류가 나는 것을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 Java 프로그램의 실행 결과를 쓰시오.
답 — 4. getInstance 가 늘 같은 객체 하나를 돌려주므로 a 와 b 는 같은 Counter 이고, add 네 번이 전부 그 한 칸에 쌓인다.
원리 — 이 클래스는 싱글톤 꼴이다. 생성자가 private 이라 밖에서 new Counter() 를 못 하고, 클래스 안에서 static final INSTANCE 로 딱 한 번 만든 객체를 getInstance() 가 돌려준다. 그래서 몇 번을 받아 와도 같은 객체다. a 와 b 는 이름만 둘이지 가리키는 것은 하나라, a.add() 도 b.add() 도 같은 value 를 올린다.
따라가기
헷갈리는 자리 — a 와 b 를 다른 객체로 보고 a 의 add 두 번만 세어 2 를 적는 것. private 생성자 + static 인스턴스 + getInstance 의 세 줄이 보이면 "객체는 하나"다. 디자인 패턴 장의 싱글톤이 코드로 나온 것이다.
복원 코드를 JDK 17 로 컴파일 · 실행해 같은 출력을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 Java 프로그램의 실행 결과를 쓰시오.
답 — NNN. new 로 만든 문자열은 전부 다른 객체라 == 가 모두 false 이고, c 는 a 와 같지만 비교 상대가 b 다.
원리 — new String("KOREA") 는 글자가 같아도 매번 새 덩어리를 만든다. == 는 두 변수가 같은 덩어리를 가리키는지만 본다. String c = a 는 a 가 가리키는 덩어리를 c 도 가리키게 한 것이라 a == c 는 true 겠지만, 코드가 묻는 것은 b == c 라서 false 다. 삼항 연산자는 참이면 "Y", 거짓이면 "N" 을 찍는다.
따라가기
헷갈리는 자리 — 둘째를 Y 로 적는 것. c 가 a 와 같다는 것에 눈이 가지만 비교 상대는 b 다. 문자열 풀은 따옴표 글자(literal)에만 적용되고 new 에는 적용되지 않는다는 것이 2023년 2회 8번과 짝이 되는 규칙이다.
복원 코드를 JDK 17 로 컴파일 · 실행해 같은 출력을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 Java 프로그램의 실행 결과를 쓰시오.
답 — dcba. 재귀가 앞 글자부터 돌아오면서 아직 없는 글자만 앞에 붙이므로, 중복을 뺀 뒤집힌 문자열이 된다.
원리 — 이 재귀는 index 를 줄이며 끝까지 내려간 뒤(index < 0 이면 빈 문자열) 돌아오면서 결과를 만든다. 돌아오는 순서는 index 0 → 1 → 2 → … 라 앞 글자부터 처리되고, 각 단계에서 current + rest 로 "새 글자를 앞에" 붙인다. 앞에 붙이니 뒤집힌다. 단 rest.indexOf(current) >= 0, 즉 이미 그 글자가 있으면 붙이지 않고 rest 를 그대로 넘긴다. 그래서 "중복 없는 역순"이다.
따라가기 — abacad, index 5 부터 내려가 0 부터 돌아온다.
헷갈리는 자리 — 내려가는 순서(뒤 글자부터)로 붙여 "dacaba" 류를 적는 것. 재귀의 결과는 돌아올 때 만들어진다. 중복을 안 거르면 "dacaba" 가 뒤집힌 전체가 되고, 앞이 아니라 뒤에 붙였다면(rest + current) "abcd" 가 된다 — 붙이는 방향과 거름 조건 두 가지를 본다.
복원 코드를 JDK 17 로 컴파일 · 실행해 같은 출력을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 Java 프로그램의 실행 결과를 쓰시오.
답 — S. split("/") 이 문자열을 / 마다 잘라 배열로 만들고, 그 첫 조각이 S 다.
원리 — split(구분자) 는 구분자를 기준으로 문자열을 잘라 String 배열을 돌려준다. 구분자 자체는 결과에 들어가지 않는다. "S/W/ENGINEER" 를 / 로 자르면 "S", "W", "ENGINEER" 세 조각이고, 배열 첨자는 0 부터이므로 words[0] 은 첫 조각이다. 조각 수는 구분자 수 + 1 이다.
따라가기
헷갈리는 자리 — words[0] 을 "첫 번째"가 아니라 "0번째 = 없음"으로 보거나, 구분자 / 가 조각에 포함된다고 보는 것. 자바 split 은 정규식을 받으므로 "." 이나 "|" 로 자를 때는 "\\." 처럼 이스케이프가 필요하다 — / 는 특수문자가 아니라 그대로 쓴다. words.length 는 3 이고 words[3] 을 읽으면 ArrayIndexOutOfBoundsException 이 난다는 것도 같은 문제 꼴에서 자주 묻는다.
복원 코드를 JDK 17 로 컴파일 · 실행해 같은 출력을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 Java 프로그램의 실행 결과를 쓰시오.
답 — OOAAA. 이웃한 문자열을 equals 로 견주면 내용이 같아 두 번 다 O 이고, 이어서 세 원소 A 를 찍는다.
원리 — equals 는 글자 내용을 견주는 메서드라 new String("A") 로 만든 다른 객체여도 "A" 와 같다고 본다. 만약 == 였다면 셋째 원소는 다른 객체라 N 이 나왔을 것이다 — 이 문제는 그 차이를 반대로 찌른다. 첫 반복은 i = 1 부터 size − 1 까지 "앞 원소와 지금 원소"를 견주므로 두 번 돈다. 둘째 반복(향상된 for)은 배열의 원소를 순서대로 하나씩 꺼내 찍는다. 둘 다 print 라 한 줄이다.
따라가기
헷갈리는 자리 — 셋째 원소가 new 라서 둘째 비교를 N 으로 적는 것. equals 는 객체가 달라도 내용이 같으면 true 다. 첫 반복이 i = 0 이 아니라 1 부터라 비교가 두 번(원소 수 − 1)이라는 것도 놓치기 쉽다.
복원 코드를 JDK 17 로 컴파일 · 실행해 같은 출력을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 Java 프로그램의 실행 결과를 쓰시오.
답 — 101. 던져진 NullPointerException 은 첫 catch 에 잡혀 1 이 더해지고, finally 는 항상 돌아 100 이 더해진다.
원리 — try 안에서 예외가 나면 그 아래 줄은 건너뛰고 catch 들을 위에서부터 훑어 "예외 종류에 맞는 첫 catch" 하나만 실행한다. NullPointerException 은 Exception 의 자식이라 둘째 catch(Exception)에도 맞지만, 이미 첫 catch 에 잡혔으니 둘째는 안 돈다. finally 는 예외가 났든 안 났든, 잡혔든 안 잡혔든 마지막에 반드시 돈다. fail() 의 throws Exception 은 "이 메서드가 예외를 던질 수 있다"는 선언일 뿐 무엇을 던지는지는 몸통이 정한다.
따라가기
헷갈리는 자리 — 둘째 catch 도 맞으니 10 을 더해 111 로 적는 것. catch 는 하나만 잡는다. finally 를 빼고 1 로 적는 것 — finally 는 언제나 돈다. catch 순서가 반대(Exception 이 먼저)였다면 컴파일 오류다 — 넓은 것이 위에 오면 아래는 닿을 수 없기 때문이다.
복원 코드를 JDK 17 로 컴파일 · 실행해 같은 출력을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 Java 프로그램의 실행 결과를 쓰시오.
답 — 출력1출력5. 5 를 0 으로 나눠 ArithmeticException 이 나고, 그것을 잡는 첫 catch 와 finally 만 돈다.
원리 — 정수를 0 으로 나누면 자바는 ArithmeticException 을 던진다(실수 나눗셈이면 Infinity 가 되어 예외가 없다). 예외가 나는 순간 System.out.print(number / divisor) 는 아무것도 찍지 못하고 catch 로 넘어간다. catch 는 위에서부터 종류가 맞는 첫 하나만 돈다 — ArithmeticException 은 첫 catch 에 정확히 맞고, 셋째 catch(Exception)도 맞지만 이미 잡혔다. finally 는 마지막에 반드시 돈다. 출력2 · 출력4 는 이 흐름에서 닿을 수 없다.
따라가기
헷갈리는 자리 — 출력4 까지 적는 것(Exception 도 맞으니까) — catch 는 하나만. 출력1 과 출력5 사이에 줄바꿈이나 공백을 넣는 것 — 전부 print 라 붙는다. 출력3 이 코드에 없는 것은 미끼가 아니라 그냥 없는 것이다.
복원 코드를 JDK 17 로 컴파일 · 실행해 같은 출력을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 Java 프로그램의 실행 결과를 쓰시오.
답 — 20. 가운데 값을 더하고 왼쪽 · 오른쪽 반쪽 중 큰 쪽을 택하는 재귀라, 8 + max(8, 12) = 20 이다.
원리 — search(start, end) 는 구간의 가운데 첨자 middle 을 잡고 data[middle] 에, 왼쪽 구간(start~middle)과 오른쪽 구간(middle + 1~end)의 결과 중 큰 것을 더한다. start >= end 면 0 으로 멈춘다. 즉 "가운데를 하나 더하고, 반쪽 중 큰 길로 계속 간다"는 뜻이다. 가운데 첨자는 (start + end) / 2 의 정수 나눗셈이라 (0 + 4) / 2 = 2, (0 + 2) / 2 = 1, (0 + 1) / 2 = 0 이다. 재귀는 작은 구간부터 값을 정해 올라오면 된다.
따라가기 — data = [3, 5, 8, 12, 17].
헷갈리는 자리 — 오른쪽 구간을 middle 부터 시작한다고 보고 8 을 두 번 더하는 것 — 오른쪽은 middle + 1 부터다. search(2, 2) 처럼 start == end 인 구간이 0 이라는 것(원소가 하나 있어도 0)을 놓치면 8 이 더 붙는다. 조건이 start > end 였다면 답이 달라진다.
복원 코드를 JDK 17 로 컴파일 · 실행해 같은 출력을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 Java 프로그램의 실행 결과를 쓰시오.
답 — BB. 배열은 주소가 넘어가 words[0] 이 B 로 바뀌지만, String 변수 label 은 복사본이라 함수 안의 "Z" 대입이 main 에 안 보인다.
원리 — 자바는 값을 넘긴다. 배열 변수 words 의 "값"은 배열이 놓인 자리(참조)라, 함수 안의 words 도 같은 배열을 가리켜 words[0] = label 이 원본 배열을 고친다. label 도 참조를 복사해 받지만 label = "Z" 는 "함수 안의 label 이 다른 문자열을 가리키게" 할 뿐, main 의 label 이 가리키는 곳은 그대로다. 문자열은 바꿀 수 없는(불변) 객체라 내용을 고치는 길도 없다. "칸 안의 값을 고치면 밖에 보이고, 변수 자체를 새것으로 바꾸면 안 보인다"가 규칙이다.
따라가기
헷갈리는 자리 — BZ 로 적는 것. 매개변수에 새 객체를 대입한 것은 호출한 쪽에 안 돌아간다. AB 로 적는 것 — 배열 칸 대입은 원본에 닿는다. 배열 · 객체의 칸 고치기(보임)와 변수 갈아끼우기(안 보임)를 나눈다.
복원 코드를 JDK 17 로 컴파일 · 실행해 같은 출력을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 Java 프로그램의 실행 결과를 쓰시오.
답 — 19. 첫 람다는 3 > 2 라 예외를 던져 catch 가 7 을 돌려주고, 둘째 람다는 3 + 9 = 12 다.
원리 — 람다 value -> {…} 는 인터페이스 Operation 의 유일한 메서드 apply 를 그 자리에서 구현한 것이다. run 은 apply(3) 을 try 안에서 부르고, 예외가 나면 catch 에서 7 을 돌려준다. 첫 람다는 value 가 2 보다 크면 throw new Exception() 이라 3 을 넣으면 예외다 — return 까지 못 간다. 둘째 람다 value -> value + 9 는 한 줄이라 중괄호 없이 값이 곧 결과다. 두 run 의 결과를 더한다.
따라가기
헷갈리는 자리 — 첫 람다를 3 × 2 = 6 으로 계산해 18 을 적는 것. 조건이 참이라 return 줄은 안 돈다. 또 throws Exception 이 인터페이스에 있어야 람다 안에서 checked 예외를 던질 수 있다는 것 — 없으면 컴파일 오류라, 빈칸 문제로도 나올 수 있는 자리다.
복원 코드를 JDK 17 로 컴파일 · 실행해 같은 출력을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 Java 프로그램의 실행 결과를 쓰시오.
답 — 1a3b3. 배열 칸을 맞바꿔도 객체 a · b · c 자체는 그대로이고, boxes[1].value = … 만 객체 b 의 값을 3 으로 고친다.
원리 — 배열 boxes 에는 객체가 들어 있는 것이 아니라 객체를 가리키는 참조가 들어 있다. boxes[0] 과 boxes[2] 를 맞바꾸는 것은 참조의 자리만 바꾸는 것이라 a · b · c 어느 객체의 value 도 안 변한다. 반면 boxes[1].value = boxes[0].value 는 boxes[1] 이 가리키는 객체(b)의 칸을 고치는 것이라 b.value 가 바뀐다. 마지막 출력은 배열이 아니라 변수 a · b · c 로 찍으므로 객체의 값을 본다. "참조를 옮기는 것"과 "객체의 칸을 고치는 것"을 나눈다.
따라가기
헷갈리는 자리 — 배열을 맞바꿨으니 a 와 c 의 값도 바뀌었다고 보고 3a3b1 로 적는 것. 참조 자리 바꾸기는 객체를 안 건드린다. boxes[1] 이 b 라는 것을 놓치고 다른 객체를 고치는 것 — 자리 1 은 교환에 끼지 않았다.
복원 코드를 JDK 17 로 컴파일 · 실행해 같은 출력을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 Java 프로그램의 실행 결과를 쓰시오.
답 — AB. Word.B.name() 은 "B" 라 길이 1 이고, values()[1] 은 둘째 상수 B 라 그 text "AB" 가 나온다.
원리 — enum 은 정해진 상수들의 목록이고, 각 상수는 생성자를 통해 자기 값(text)을 가진다. name() 은 상수의 이름 자체("B")를 문자열로 돌려주고, getText() 는 우리가 넣은 값("AB")을 돌려준다 — 둘은 다르다. values() 는 상수를 선언 순서대로 담은 배열이라 [0] A, [1] B, [2] C 다. 그러니 values()[Word.B.name().length()] 는 values()[1] = B 이고, 그 text 가 답이다.
따라가기
헷갈리는 자리 — name() 을 text("AB")로 읽어 길이 2 → values()[2] = C → "ABC" 를 적는 것. name 은 상수 이름이다. 첨자가 0 부터라는 것을 잊고 values()[1] 을 A 로 보는 것도 있다.
복원 코드를 JDK 17 로 컴파일 · 실행해 같은 출력을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 Java 프로그램을 실행했을 때 출력되는 값을 쓰시오.
답 — 1123. 왼쪽부터 계산해 9 + 2 = 11 이 먼저 정수로 더해지고, 그다음부터는 문자열 붙이기라 "11" + "2" + "3" 이다.
원리 — + 는 두 쪽이 모두 숫자면 덧셈이고, 한쪽이라도 문자열이면 붙이기다. 그리고 왼쪽에서 오른쪽으로 하나씩 계산한다. x1 + x2 는 둘 다 int 라 11(덧셈), 그 결과 11 과 "2" 는 한쪽이 문자열이라 "112"(붙이기), 이어서 "112" + "3" → "1123". 문자열이 한 번 끼어든 뒤부터는 되돌아가지 않는다. 괄호가 없으니 순서를 바꿔 읽을 여지가 없다.
따라가기
헷갈리는 자리 — 전부 문자열로 보고 9223 을 적는 것(첫 덧셈은 정수). 전부 숫자로 보고 16 을 적는 것("2" 와 "3" 은 문자열). "2" + x1 + x2 였다면 "292" 가 되듯 순서가 답을 바꾼다. 괄호로 x1 + (x2 + "2") 라고 묶으면 안쪽이 먼저 붙기라 "9223" 이 된다 — 괄호 유무도 본다.
복원 코드를 JDK 17 로 컴파일 · 실행해 같은 출력을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 Java 프로그램의 실행 결과를 쓰시오.
답 — 1. 규칙이 n − 1 과 n − 3 이고 멈춤 조건이 1 이하일 때 그 수 자체라, 음수 −1 이 섞여 값이 작아진다.
원리 — 재귀는 작은 입력부터 표로 만들면 안전하다. 멈춤 조건 num <= 1 은 "1 이하이면 그 수를 그대로 돌려준다"라, compute(0) = 0, compute(−1) = −1 처럼 음수도 값이 된다. 이것을 0 으로 잘못 두면 답이 어긋난다. 규칙은 두 개 앞이 아니라 "하나 앞 + 셋 앞"이라 피보나치와 다르다.
따라가기 — c(n) = c(n − 1) + c(n − 3).
헷갈리는 자리 — c(−1) 을 0 으로 두면 c(2) = 1, c(3) = 1, c(4) = 2, c(5) = 3 이 된다. 피보나치로 풀어 5 를 적는 것도 흔하다. 2023년 3회 14번(같은 규칙으로 compute(7) = 2)과 짝이다.
복원 코드를 JDK 17 로 컴파일 · 실행해 같은 출력을 확인했다. 복원 출처 grandlife.co.kr(2026-09-14) — 공식 원문이 아니라 문장 · 변수명이 실제와 다를 수 있다.
다음 코드의 출력을 쓰시오.
답 — 1EFG. arr[3] 에서 예외가 나 그 뒤 줄은 건너뛰고 catch → finally → 다음 문장 순으로 간다.
원리 — try 블록은 예외가 나는 순간 거기서 멈추고 나머지 줄은 실행하지 않는다. arr 은 3칸(0 · 1 · 2)이라 arr[3] 은 범위 밖이고 ArrayIndexOutOfBoundsException 이 던져진다. 그래서 arr[0] 의 1 은 찍혔지만 arr[1] 의 2 는 영영 찍히지 않는다. 예외는 타입이 맞는 catch 로 잡혀 E 를 찍고, finally 는 예외가 났든 안 났든 반드시 실행돼 F 를 찍는다. 예외가 처리됐으니 프로그램은 계속 진행해 G 를 찍는다.
따라가기
헷갈리는 자리 — 예외 뒤의 arr[1] 도 찍혀 12EFG 로 적는 것. 예외가 난 줄부터 try 의 나머지는 실행되지 않는다. 그리고 catch 가 없거나 타입이 안 맞았다면 finally 는 F 를 찍고 예외가 밖으로 나가 G 는 안 찍힌다 — "잡혔는가"가 뒤 문장의 운명을 정한다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 8결과53. + 는 왼쪽부터 계산되어 문자열을 만나기 전까지는 덧셈, 만난 뒤로는 이어 붙이기다.
원리 — 자바의 + 는 두 피연산자 중 하나라도 String 이면 문자열 연결이고, 둘 다 숫자면 덧셈이다. 그리고 같은 우선순위라 왼쪽에서 오른쪽으로 하나씩 계산한다. a + b 는 5 + 3 = 8(숫자). 8 + "결과" 는 "8결과"(문자열). "8결과" + a 는 "8결과5", 거기에 + b 는 "8결과53". 한 번 문자열이 되면 그 뒤의 숫자는 전부 붙는다. 같은 식이라도 괄호를 (a + b) 로 뒤에 두면 "8결과8" 이 된다.
따라가기
헷갈리는 자리 — 뒤의 a + b 도 더해 "8결과8" 로 적는 것. 문자열 뒤에서는 더하기가 없다. println 이라 줄바꿈이 붙지만 답에는 안 적는다. 이 유형은 문자열 위치만 바꿔 여러 번 나온다 — 왼쪽부터 한 칸씩 계산하면 된다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 3123. static 변수 total 은 클래스에 하나뿐이라 객체를 만들 때마다 1 씩 올라 3 이고, 각 객체의 num 은 만들어질 때의 total 값 1 · 2 · 3 을 갖는다.
원리 — static 필드는 객체마다 있는 것이 아니라 클래스 전체에 하나만 있다. 생성자가 total++ 를 하면 그 하나가 커진다. 반면 num 은 인스턴스 필드라 객체마다 따로 있고, 생성자에서 num = total 로 그 순간의 값을 복사해 둔다. a 는 total 이 1 일 때, b 는 2, c 는 3 일 때 만들어졌다. Counter.total + "" 은 숫자를 문자열로 바꾸는 관용구라 그 뒤의 + 는 전부 이어 붙이기가 되어 "3" + "1" + "2" + "3" 이다.
따라가기
헷갈리는 자리 — num 도 static 처럼 보고 3333 으로 적는 것. num 은 객체별 값이다. 그리고 + "" 가 없었다면 3 + 1 + 2 + 3 = 9 로 숫자 덧셈이 되었을 것이다 — 빈 문자열의 자리가 결과를 바꾼다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 923. b 는 a 와 같은 배열을 가리켜 b[0] = 9 가 a 에 반영되고, c 는 복사본이라 c[1] = 8 은 a 에 영향이 없다.
원리 — 배열 변수는 배열 객체의 "주소"를 담는다. int[] b = a 는 주소를 복사한 것이라 a 와 b 는 같은 배열이다 — b[0] 을 바꾸면 a[0] 도 바뀐다. a.clone() 은 배열을 새로 만들어 값을 복사한 것이라 c 는 다른 배열이다 — c[1] 을 바꿔도 a 는 그대로다. 출력은 a[0] + "" 로 문자열을 만든 뒤 붙이므로 9 · 2 · 3 이 이어진다. 참조 복사와 값 복사의 차이가 이 문제 전부다.
따라가기
헷갈리는 자리 — clone 도 같은 배열이라 보고 983 으로 적거나, = 도 복사라 보고 123 으로 적는 것. "= 는 같은 것을 가리키고, clone 은 새로 만든다". 2차원 배열의 clone 은 바깥 배열만 복사(얕은 복사)라 안쪽 행은 공유된다는 것이 다음 단계 함정이다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
왜 이걸 하나 — 이 장은 줄바꿈과 순서에서 깎인다.
| 자리 | 새는 꼴 | 적는 법 | 기출 |
|---|---|---|---|
| println | 4줄 출력을 한 줄로 | println 은 줄바꿈, print 는 이어짐. 문제가 「줄마다」라 하면 줄을 나눈다 | 2023-1회 1번 · 2023-2회 8번 |
| == 리터럴 | 리터럴 == 를 false 로 | 같은 리터럴은 같은 상수 → true. new 끼리만 false | 2023-2회 8번 · 2024-2회 1번 |
| catch 순서 | Exception catch 도 실행된다고 본다 | 맞는 첫 catch 하나만 | 2024-3회 16번 · 2025-1회 5번 |
| finally | 예외가 안 났으니 finally 를 뺀다 | finally 는 언제나 | 2025-1회 5번 |
| 연결 순서 | "2" 뒤의 3 을 더한다 | 문자열이 끼면 그 뒤는 전부 연결 | 2026-1회 17번 · 예상 1회 8번 |
| 종료 조건 | 음수 호출을 0 으로 | 코드가 돌려주는 값 그대로 | 2026-2회 14번 |
| 줄 번호 | 「7」만 적거나 다른 줄 | 문제가 「줄 번호」를 물으면 숫자, 정답표 표기가 「7번 줄」이면 그대로 | 2023-3회 12번 |
| 참조 교환 | 배열 칸을 바꾸면 a · b · c 변수도 바뀐다고 본다 | 변수는 그대로, 배열 칸의 쪽지만 바뀐다. 값을 바꾼 줄이 어느 객체인지 그림으로 | 2025-2회 15번 |
Java 출력 문제는 print 인지 println 인지가 줄 수를 정한다. 코드에서 println 을 세어 답의 줄 수와 맞춘다.
왜 이걸 하나 — 규칙 9개를 짧은 코드 20개로 돌린다. Java 훈련의 3분의 2가 여기 있다.
훈련 20문항은 static 카운터, == 와 equals, StringBuilder, 정수 나눗셈, 예외 흐름, 배열 clone, switch, 문자열 연결, charAt · substring · split, 중첩 루프, 증감, 비트, 최댓값 탐색, 재귀 피보나치 · 역순, 2차원 배열, char + int, catch 선택이다. 정답은 전부 JDK 17 로 실행해 확인했다.
답 — 3. static 변수 cnt 는 클래스에 하나라 객체를 셋 만들면 생성자가 세 번 돌아 3 이 된다.
원리 — 인스턴스 필드는 객체마다 따로지만 static 필드는 클래스에 단 하나다. 생성자 C() 가 불릴 때마다 그 하나의 cnt 를 1 올린다. new C() 세 번이면 cnt 는 3 이다. 객체를 변수에 담지 않아도 생성자는 실행된다. 읽을 때는 객체가 아니라 클래스 이름으로 C.cnt 라고 접근한다 — "만든 객체 수 세기"는 static 의 대표 용도다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — true false true. 리터럴 둘은 같은 객체를 공유하고, new 는 새 객체를 만들며, equals 는 내용을 비교한다.
원리 — == 는 "같은 객체인가(주소)", equals 는 "내용이 같은가"다. 문자열 리터럴 "Java" 는 문자열 풀(pool)에 하나만 만들어져 a 와 b 가 같은 객체를 가리키므로 a == b 는 true. new String("Java") 는 풀과 별개로 힙에 새 객체를 만들어 a == c 는 false. 하지만 글자는 같으니 a.equals(c) 는 true. 문자열 비교는 항상 equals 로 해야 한다는 교훈이 담긴 문제다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — edcba. "abc" 에 "de" 를 붙여 "abcde" 를 만든 뒤 뒤집었다.
원리 — StringBuilder 는 String 과 달리 자기 자신을 고치는(가변) 객체다. append 는 뒤에 붙이고 reverse 는 순서를 뒤집는데, 둘 다 자기 자신을 돌려주므로 점으로 이어 부를 수 있다(메서드 체이닝). sb.append("de") 로 sb 가 "abcde" 가 되고, 이어서 .reverse() 로 "edcba" 가 된다. print(sb) 는 sb.toString() 을 찍는다. String 이었다면 매번 새 객체가 생겨 원본은 안 바뀐다 — 그것이 StringBuilder 를 쓰는 이유다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — 3 1 5. 정수 나눗셈 몫 3, 나머지 1, 삼항 연산으로 7 − 2 = 5 다.
원리 — int 끼리의 / 는 소수점을 버린 몫이라 7 / 2 = 3 이고, % 는 나머지라 1 이다. 삼항 연산자는 a > b 가 참이면 a − b, 거짓이면 b − a 를 고르는데 7 > 2 참이라 5 다. 괄호가 없으면 + 가 삼항보다 먼저 묶여 엉뚱한 결과가 되므로 괄호로 감쌌다. 문자열 " " 와 번갈아 + 하므로 각 값은 문자열로 바뀌어 붙는다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — CFEND. x[2] 에서 예외가 나 T 는 안 찍히고 catch → finally → 뒤 문장 순서다.
원리 — new int[2] 는 0 · 1 두 칸이라 x[2] 는 범위 밖이고 ArrayIndexOutOfBoundsException 이 난다. 예외가 난 줄에서 try 는 중단되어 "T" 는 실행되지 않는다. 타입이 맞는 catch 가 잡아 C, finally 는 항상 실행되어 F. 예외가 처리됐으니 프로그램은 계속 진행해 END 를 찍는다. 예외가 없었다면 T F END 였을 것이다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — 923. b 는 a 와 같은 배열이라 b[0] = 9 가 a 를 바꾸고, c 는 clone 이라 c[2] = 7 은 a 를 안 바꾼다.
원리 — 배열 변수에는 배열의 주소가 들어 있다. int[] b = a 는 주소를 복사해 두 변수가 한 배열을 가리킨다 — 어느 쪽으로 고쳐도 같은 배열이다. a.clone() 은 값이 같은 새 배열을 만들어 돌려주므로 c 는 별개다. 그래서 a 는 [9 2 3] 이고 c 는 [9 2 7] 이다. a[0] + "" 로 먼저 문자열을 만들어 붙이므로 923 이다. P-2-05 와 같은 유형이고 바뀐 칸만 다르다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — CD. 75 / 10 = 7 이라 case 7 로 들어가 break 를 만날 때까지 C · D 가 찍힌다.
원리 — switch 는 값이 맞는 case 로 점프한 뒤 break 까지 아래로 흘러내린다(fall-through). score / 10 은 정수 나눗셈이라 7 이다. case 7 의 C 를 찍고, break 가 없어 case 6 의 D 까지 찍은 뒤 거기 break 로 나간다. case 9 · 8 은 위에 있어 안 거치고 default 는 break 뒤라 안 닿는다. 점수대별 등급 코드에서 break 를 빠뜨렸을 때의 전형이다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — 3a12. 문자열 "a" 앞은 덧셈, 뒤는 이어 붙이기다.
원리 — + 는 왼쪽부터 차례로 계산되고, 문자열이 끼어드는 순간부터 연결 연산이 된다. 1 + 2 는 둘 다 숫자라 3. 3 + "a" 는 "3a". "3a" + 1 은 "3a1", + 2 는 "3a12". 앞의 1 + 2 는 합쳐지고 뒤의 1 · 2 는 따로 붙는 비대칭이 답의 모양이다. 뒤도 더하고 싶으면 (1 + 2) 로 괄호를 쳐야 한다. 문자열이 맨 앞에 오면 "a" + 1 + 2 → "a12" 처럼 전부 붙는다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — Ol. 'o' − 32 = 'O', 'k' + 1 = 'l' 이다.
원리 — char 는 정수(유니코드 번호)로 계산된다. 'o' 는 111 이고 32 를 빼면 79 = 'O'(대소문자 차이 32). 'k' 는 107 이고 1 을 더하면 108 = 'l'. 그런데 char 끼리 산술을 하면 결과는 int 가 되므로 글자로 찍으려면 (char) 로 되돌려야 한다 — 캐스팅이 없으면 79 와 108 이 숫자로 찍힌다. 사이의 + "" 는 두 char 를 숫자로 더하지 않고 문자열로 붙이기 위한 것이다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — form 3 11. substring(2, 6) 은 첨자 2 부터 6 앞까지, indexOf('o') 는 첫 o 의 첨자, length 는 글자 수다.
원리 — substring(a, b) 는 a 번째부터 b 번째 "앞"까지, 곧 b − a 글자를 잘라 낸다. "information" 에 번호를 붙이면 i(0) n(1) f(2) o(3) r(4) m(5) a(6) … 이라 2~5 는 f o r m. indexOf('o') 는 처음 나오는 o 의 첨자 3 이다(뒤의 o 는 상관없다). length() 는 11 이다. 자바 문자열 첨자는 0 부터, 끝 번호는 미포함 — 이 둘만 지키면 된다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — 6. i = 1 일 때 3번, 2 일 때 2번, 3 일 때 1번 도는 삼각형 반복이다.
원리 — 안쪽 반복의 시작이 j = i 라 바깥이 진행될수록 안쪽 횟수가 줄어든다. i = 1 이면 j 는 1 · 2 · 3, i = 2 면 2 · 3, i = 3 이면 3 만. 합은 3 + 2 + 1 = 6 이다. 일반화하면 n(n+1)/2 로 3 × 4 / 2 = 6. 안쪽 시작이 j = 1 이었다면 3 × 3 = 9, j = i + 1 이었다면 2 + 1 + 0 = 3 이다 — 안쪽 시작값 하나로 답이 갈린다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — 12 7. i++ 는 5 를 내고 i 를 6 으로, ++i 는 i 를 7 로 만들고 7 을 낸다 — 5 + 7 = 12.
원리 — 식은 왼쪽부터 평가된다. i++ 는 "현재 값 5 를 쓰고 나서" i 를 6 으로 올린다. 다음 ++i 는 "먼저 7 로 올리고" 7 을 쓴다. 그래서 r = 5 + 7 = 12 이고 i 는 두 번 올라 7 이다. 후위 · 전위가 한 식에 섞이면 "값을 언제 읽나"를 순서대로 적어 가는 것이 유일한 방법이다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — 20 2 1 6. 5 = 101 을 왼쪽 2칸(×4), 오른쪽 1칸(÷2), 3 = 011 과 AND · XOR 한 값이다.
원리 — << k 는 2ᵏ 곱, >> k 는 2ᵏ 로 나눈 몫이다. 5 << 2 = 20, 5 >> 1 = 2. & 는 자리별 AND — 101 & 011 = 001 = 1. ^ 는 자리별 XOR(다르면 1) — 101 ^ 011 = 110 = 6. 2진수로 세로로 놓고 자리별로 보면 틀리지 않는다. n & 3 은 "4 로 나눈 나머지"와 같다는 것도 알아 두면 좋다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — 9 1. 최댓값 9 와 그 위치(첨자) 1 이다.
원리 — 최댓값을 찾을 때 값만 갱신하지 않고 "어디서 찾았나"도 함께 저장하는 형이다. max 와 idx 를 첫 원소로 시작하고, 더 큰 값을 만나면 둘을 함께 갱신한다. 4 → 9(갱신, idx 1) → 2 → 7 순으로 보면 9 가 최대이고 첨자 1 이다. 같은 최댓값이 두 번 나오면 > 라 첫 번째 위치가 남고, >= 였다면 마지막 위치가 남는다 — 부등호 하나가 답을 바꾸는 변형 포인트다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — 8. fib(0) = 0, fib(1) = 1 로 시작하는 피보나치의 6번째 값이다.
원리 — fib(n) = fib(n−1) + fib(n−2), 바닥은 n <= 1 일 때 n 자신(0 또는 1)이다. 앞에서부터 표로 채우면 fib(0) 0, fib(1) 1, fib(2) 1, fib(3) 2, fib(4) 3, fib(5) 5, fib(6) 8. C 버전(T-C-10)은 f(1) = f(2) = 1 로 시작해 f(7) = 13 이었다 — 바닥 정의가 다르면 같은 n 이라도 값이 한 칸 밀린다. 코드의 바닥 조건을 반드시 읽는다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — AVAJ. 첨자 3 부터 0 까지 글자를 하나씩 찍으며 재귀로 내려가 문자열이 뒤집힌다.
원리 — rev(s, i) 는 s 의 i 번 글자를 찍은 뒤 rev(s, i − 1) 을 부른다. 찍는 것이 재귀 호출 "앞"에 있으므로 호출 순서대로 찍힌다 — i = 3(A) → 2(V) → 1(A) → 0(J) → −1 에서 return. 만약 print 가 재귀 호출 "뒤"에 있었다면 되돌아오며 찍혀 JAVA 순서가 된다. 재귀에서 출력 위치(호출 앞 · 뒤)가 순서를 정한다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — 15. 대각선 원소 1 + 5 + 9 다.
원리 — a[i][i] 는 행 번호와 열 번호가 같은 칸, 곧 왼쪽 위에서 오른쪽 아래로 가는 주대각선이다. i = 0 → a[0][0] = 1, i = 1 → a[1][1] = 5, i = 2 → a[2][2] = 9. 합 15. 반대 대각선은 a[i][2 − i] 로 3 + 5 + 7 = 15 가 된다. 2차원 배열 문제는 표를 그리고 첨자가 가리키는 칸에 동그라미를 치면 끝난다. 반복 범위가 3 인 것은 행 · 열이 3 이기 때문이다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — 66 B. char + int 는 int 가 되어 66 이 찍히고, (char) 로 되돌리면 B 다.
원리 — 'A' 는 유니코드 65 다. c + 1 은 char 와 int 의 연산이라 결과가 int 66 이고, print 는 그것을 숫자로 찍는다. (char)(c + 1) 은 66 을 다시 문자로 해석해 'B' 다. "char 에 산술을 하면 int, 글자로 보려면 캐스팅" — 자바 문자 문제의 기본 규칙이다. 가운데 print(" ") 로 공백이 하나 들어간다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — NF. null 에 메서드를 부르면 NullPointerException 이고, 그것을 첫 catch 가 잡은 뒤 finally 가 돈다.
원리 — o 는 null 이라 가리키는 객체가 없다. o.toString() 은 없는 객체의 메서드를 부르는 것이라 NullPointerException 이 던져진다. catch 는 위에서부터 타입을 맞춰 보고 처음 맞는 하나만 실행한다 — NullPointerException 이 먼저 있어 N 이 찍히고, 아래의 Exception 은 부모 타입이라 잡을 수 있었지만 이미 잡혔으니 실행되지 않는다. finally 로 F. 순서를 바꿔 Exception 을 위에 두면 컴파일 오류가 난다(아래 catch 가 닿을 수 없어서).
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
답 — 3blueg. 쉼표로 쪼개 3 조각이고, 두 번째 조각 blue, 세 번째 조각의 첫 글자 g 다.
원리 — split(",") 은 쉼표를 경계로 잘라 문자열 배열을 돌려준다 — ["red", "blue", "green"], 길이 3. arr[1] 은 두 번째 "blue", arr[2].charAt(0) 은 "green" 의 첫 글자 'g' 다. 출력식은 int + String 이라 3 이 먼저 문자열 "3" 이 되고, 그 뒤에 "blue" 와 'g' 가 붙는다. 첫 항이 숫자 3 이고 뒤가 문자열이라 덧셈이 아니라 연결이다.
따라가기
이 노트에서 만든 변형 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
왜 이걸 하나 — 아래를 안 보고 적을 수 있어야 이 장이 끝난다.
9 + 2 + "2" + "3" 의 결과.