문제 1: 추상 클래스에서 static 메서드?
abstract class Parent {
static void show() {
System.out.println("Parent 클래스");
}
abstract void display();
}
class Child extends Parent {
void display() {
System.out.println("Child 클래스");
}
}
public class Test {
public static void main(String[] args) {
Parent.show();
}
}
Q1: 실행 결과는?
- "Parent 클래스"
- "Child 클래스"
- 컴파일 에러 발생
- 런타임 예외 발생
✅ 정답: 1) "Parent 클래스"
💡 설명:
static
메서드는 클래스 소속 → 인스턴스 없이Parent.show()
로 직접 호출 가능- 추상 클래스도
static
메서드를 가질 수 있음
※ 유사 문제: 이전 11번(추상 클래스 일반 메서드)와 유사하지만, 여기서는 static 메서드를 다룸
문제 2: super()의 호출 순서
class A {
A() {
System.out.println("A 생성자");
}
}
class B extends A {
B() {
System.out.println("B 생성자");
}
}
class C extends B {
C() {
System.out.println("C 생성자");
}
}
public class Test {
public static void main(String[] args) {
C obj = new C();
}
}
Q2: 실행 결과는?
- A 생성자 B 생성자 C 생성자
- C 생성자 B 생성자 A 생성자
- B 생성자 C 생성자 A 생성자
- A 생성자 C 생성자 B 생성자
✅ 정답: 1) A 생성자 B 생성자 C 생성자
💡 설명:
- 생성자 호출 시 항상 상위 클래스부터 차례대로 호출됨
C()
호출 → 내부적으로super()
→B()
→ 그 내부super()
→A()
순
문제 3: 인터페이스 다중 상속과 default 메서드
interface A {
default void show() {
System.out.println("A 인터페이스");
}
}
interface B {
default void show() {
System.out.println("B 인터페이스");
}
}
class C implements A, B {
public void show() {
System.out.println("C 클래스");
}
}
public class Test {
public static void main(String[] args) {
A obj = new C();
obj.show();
}
}
Q3: 실행 결과는?
- "A 인터페이스"
- "B 인터페이스"
- "C 클래스"
- 컴파일 에러 발생
✅ 정답: 3) "C 클래스"
💡 설명:
- 인터페이스 다중 상속 시, 같은 시그니처의 default 메서드가 충돌
- 클래스
C
에서show()
를 오버라이딩해 충돌 해결 → "C 클래스" 출력
※ 유사 문제: 이전 12번에서 오버라이딩하지 않아서 컴파일 에러가 났던 예시와 대조됨 (여긴 직접 오버라이딩)
문제 4: instanceof와 null
class Parent {}
public class Test {
public static void main(String[] args) {
Parent obj = null;
System.out.println(obj instanceof Parent);
}
}
Q4: 실행 결과는?
- true
- false
- 컴파일 에러 발생
- 런타임 예외 발생
✅ 정답: 2) false
💡 설명:
null instanceof Parent
는false
null
은 어떠한 객체도 아니기 때문
문제 5: try-with-resources와 AutoCloseable
class MyResource implements AutoCloseable {
public void use() {
System.out.println("리소스 사용");
}
@Override
public void close() {
System.out.println("리소스 해제");
}
}
public class Test {
public static void main(String[] args) {
try (MyResource res = new MyResource()) {
res.use();
}
}
}
Q5: 실행 결과는?
- "리소스 사용" "리소스 해제"
- "리소스 사용"
- "리소스 해제"
- 컴파일 에러 발생
✅ 정답: 1) "리소스 사용" "리소스 해제"
💡 설명:
try-with-resources
구문은AutoCloseable
구현체를 자동으로close()
호출함- 코드 내
res.use()
실행 후 블록을 벗어날 때close()
가 자동 수행
※ 유사 문제: 이전 16번(BufferedReader 예시)과 동일한 try-with-resources 개념, 여기서는 직접 만든 리소스 사용
문제 6: final 변수의 동작
public class Test {
public static void main(String[] args) {
final int x;
System.out.println(x);
}
}
Q6: 실행 결과는?
- 0
- 컴파일 에러 발생
- 런타임 예외 발생
- 아무것도 출력되지 않음
✅ 정답: 2) 컴파일 에러 발생
💡 설명:
final
변수는 선언과 동시에 혹은 생성자/블록 안에서 반드시 초기화해야 함- 초기화 없이
System.out.println(x)
로 사용하려 하면 컴파일 에러
문제 7: try-catch-finally와 return
public class Test {
public static int testMethod() {
try {
return 1;
} catch (Exception e) {
return 2;
} finally {
return 3;
}
}
public static void main(String[] args) {
System.out.println(testMethod());
}
}
Q7: 실행 결과는?
- 1
- 2
- 3
- 컴파일 에러 발생
✅ 정답: 3) 3
💡 설명:
finally
구문에서return
을 실행하면try
·catch
블록의return
은 무시- 최종적으로
3
이 반환됨
문제 8: throws와 throw의 차이
class MyException extends Exception {
MyException(String message) {
super(message);
}
}
public class Test {
public static void main(String[] args) throws MyException {
method();
}
static void method() throws MyException {
throw new MyException("예외 발생!");
}
}
Q8: 실행 결과는?
- "예외 발생!" 출력 후 프로그램 종료
- "예외 발생!" 출력 후 정상 종료
- 컴파일 에러 발생
- 아무것도 출력되지 않음
✅ 정답: 1) "예외 발생!" 출력 후 프로그램 종료
💡 설명:
throws
는 예외를 메서드 밖으로 던지겠다고 선언한 것일 뿐, 처리(catch)하지 않으면 프로그램 종료throw
는 실제 예외 객체 발생.catch
가 없으니 종료
※ 중복 개념: 15번(throws vs throw)과 유사 예제. 예외 처리가 없으면 그대로 종료
*문제 9: Integer 캐싱 범위
public class Test {
public static void main(String[] args) {
Integer a = 100;
Integer b = 100;
Integer c = 200;
Integer d = 200;
System.out.println(a == b);
System.out.println(c == d);
}
}
Q9: 실행 결과는?
- true true
- false false
- true false
- false true
✅ 정답: 3) true false
💡 설명:
Integer
는 -128 ~ 127 범위를 캐싱하므로 100은 동일 객체 →a == b
→ true- 200은 캐싱 범위 바깥이므로 다른 객체 →
c == d
→ false
문제 10: hashCode()와 equals()
import java.util.HashSet;
class Person {
String name;
Person(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Person) {
return this.name.equals(((Person) obj).name);
}
return false;
}
}
public class Test {
public static void main(String[] args) {
HashSet set = new HashSet<>();
set.add(new Person("Alice"));
set.add(new Person("Alice"));
System.out.println(set.size());
}
}
Q10: 실행 결과는?
- 1
- 2
- 컴파일 에러 발생
- 런타임 예외 발생
✅ 정답: 2) 2
💡 설명:
equals()
는 재정의했지만hashCode()
는 재정의하지 않아, 서로 다른 해시값으로 인식됨- HashSet은 내부적으로
hashCode()
비교 후equals()
를 확인하므로, 중복 판정 실패 → 원소 2개 - 중복을 제대로 제거하려면
hashCode()
도 함께 재정의 필요
문제 11: 추상 클래스 내 메서드 상속
abstract class Parent {
void show() { // 일반 메서드
System.out.println("Parent 클래스");
}
abstract void display(); // 추상 메서드
}
class Child extends Parent {
void display() {
System.out.println("Child 클래스");
}
}
public class Test {
public static void main(String[] args) {
Parent obj = new Child();
obj.show();
obj.display();
}
}
Q11: 실행 결과는 무엇인가?
- Parent 클래스 Child 클래스
- Child 클래스 Parent 클래스
- 컴파일 에러 발생
- 런타임 예외 발생
✅ 정답: 1) Parent 클래스 Child 클래스
💡 설명:
Parent
의 일반 메서드(show()
)는 자식이 재정의할 필요 없이 그대로 사용 가능display()
는 추상 메서드이므로Child
에서 구현- 실행 순서:
obj.show()
→ "Parent 클래스",obj.display()
→ "Child 클래스"
문제 12: 인터페이스 default 메서드 & 다중 상속
interface A {
default void show() {
System.out.println("A 인터페이스");
}
}
interface B {
default void show() {
System.out.println("B 인터페이스");
}
}
class C implements A, B {
// show() 오버라이딩 없이 비워둠
}
public class Test {
public static void main(String[] args) {
C obj = new C();
obj.show();
}
}
Q12: 실행 결과는?
- A 인터페이스
- B 인터페이스
- 컴파일 에러 발생
- 런타임 예외 발생
✅ 정답: 3) 컴파일 에러 발생
💡 설명:
A
와B
가 동일한 시그니처의default
메서드를 제공 → 충돌 발생- 클래스
C
에서 반드시show()
를 오버라이딩해 충돌 해결 필요
문제 13: 인터페이스의 static 메서드
interface A {
static void show() {
System.out.println("A 인터페이스");
}
}
class B implements A {}
public class Test {
public static void main(String[] args) {
B obj = new B();
obj.show();
}
}
Q13: 실행 결과는?
- A 인터페이스
- 컴파일 에러 발생
- 런타임 예외 발생
- 아무것도 출력되지 않음
✅ 정답: 2) 컴파일 에러 발생
💡 설명:
- 인터페이스의
static
메서드는 인스턴스로 호출할 수 없음 - 정확한 호출 방법:
A.show();
(인터페이스명으로 직접 호출)
문제 14: Checked vs Unchecked 예외
public class Test {
public static void main(String[] args) {
try {
method();
} catch (Exception e) {
System.out.println("예외 발생!");
}
}
static void method() throws RuntimeException {
throw new RuntimeException("런타임 예외 발생!");
}
}
Q14: 실행 결과는?
- "예외 발생!"
- "런타임 예외 발생!"
- 컴파일 에러 발생
- 예외 발생 후 프로그램 종료
✅ 정답: 1) "예외 발생!"
💡 설명:
RuntimeException
은 Unchecked Exception으로,catch (Exception e)
가 이를 잡음- catch 블록에서 "예외 발생!" 출력 후 정상 흐름으로 진행
문제 15: throws vs throw
class MyException extends Exception {
MyException(String message) {
super(message);
}
}
public class Test {
public static void main(String[] args) throws MyException {
System.out.println("프로그램 실행");
throw new MyException("커스텀 예외 발생!");
}
}
Q15: 실행 결과는?
- "프로그램 실행" 후 "커스텀 예외 발생!"
- "커스텀 예외 발생!" 후 프로그램 종료
- 컴파일 에러 발생
- "프로그램 실행" 후 정상 종료
✅ 정답: 1) "프로그램 실행" 후 "커스텀 예외 발생!"
💡 설명:
throws MyException
로 예외를 던질 수 있다고 선언했고, 실제로throw
로 예외 발생- "프로그램 실행"이 먼저 출력되고, 예외가 던져지면서 프로그램이 종료됨
문제 16: try-with-resources
import java.io.*;
public class Test {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("test.txt")))//파일이 없음 {
System.out.println(br.readLine());
} catch (IOException e) {
System.out.println("예외 발생!");
}
}
}
Q16: 실행 결과는?
- "test.txt" 파일의 첫 번째 줄 출력
- "예외 발생!"
- 컴파일 에러 발생
- 런타임 예외 발생 후 프로그램 종료
✅ 정답: 2) "예외 발생!"
💡 설명:
- 파일
test.txt
가 없거나 IO 에러가 발생 시IOException
을 잡아 "예외 발생!" 출력 - 만약 실제로 파일이 존재하고 정상 읽기가 가능하다면 1번 상황이 될 수도 있음 (문제 예시상 정답은 2번 가정)
문제 17: finally 블록과 System.exit()
public class Test {
public static void main(String[] args) {
try {
System.out.println("try 블록 실행");
System.exit(0);
} finally {
System.out.println("finally 블록 실행");
}
}
}
Q17: 실행 결과는?
- "try 블록 실행" 후 "finally 블록 실행"
- "try 블록 실행" 후 프로그램 종료
- "finally 블록 실행" 후 프로그램 종료
- 컴파일 에러 발생
✅ 정답: 2) "try 블록 실행" 후 프로그램 종료
💡 설명:
System.exit(0)
는 JVM을 종료하므로finally
블록이 실행되지 않음- 일반적으로
finally
는 항상 실행되지만,System.exit()
는 예외
문제 18: String Pool과 new String()
public class Test {
public static void main(String[] args) {
String s1 = "Java";
String s2 = "Java";
String s3 = new String("Java");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
}
}
Q: 위 코드 실행 결과는?
- true / true
- true / false
- false / true
- false / false
✅ 정답: 2) true / false
💡 설명:
s1
과s2
는 같은 String Pool 영역을 참조하므로s1 == s2
→true
new String("Java")
는 새로운 객체를 생성하므로s1 == s3
→false
- 문자열 내용을 비교하려면
equals()
메서드를 사용해야 함
문제 19: instanceof & 인터페이스
interface A {}
class B implements A {}
public class Test {
public static void main(String[] args) {
A obj = new B();
System.out.println(obj instanceof B);
System.out.println(obj instanceof A);
System.out.println(obj instanceof Object);
}
}
Q19: 실행 결과는?
- true true true
- true false true
- false true true
- true true false
✅ 정답: 1) true true true
💡 설명:
obj instanceof B
→obj
는B
객체이므로true
obj instanceof A
→B
가A
를 구현했으므로true
obj instanceof Object
→ 자바의 모든 클래스는Object
상속 →true
*문제 20: enum & 생성자
enum Color {
RED, GREEN, BLUE;
Color() {
System.out.println("Color 생성자 실행!");
}
}
public class Test {
public static void main(String[] args) {
Color c1 = Color.RED;
Color c2 = Color.GREEN;
}
}
Q20: 실행 결과는?
- "Color 생성자 실행!" 1번 출력
- "Color 생성자 실행!" 2번 출력
- "Color 생성자 실행!" 3번 출력
- 컴파일 에러 발생
✅ 정답: 3) "Color 생성자 실행!" 3번 출력
💡 설명:
- enum은 선언된 모든 상수가 처음 로드될 때 생성자를 실행
- 따라서
RED, GREEN, BLUE
세 상수 각각에 대해 한 번씩 호출 → 총 3번 출력
'Java' 카테고리의 다른 글
Java 문법 QUIZ [1] (0) | 2025.02.04 |
---|---|
Java 조각모음 [4] (1) | 2025.01.23 |
예제로 배우는 결국 알아야하는 JVM 메모리 구조(순한맛) (0) | 2025.01.22 |
예제로 배우는 제한자와 자바변수 설계 전략 (1) | 2025.01.22 |
예제로 배우는 자바가 배열을 생성하는 원리 이해하기 (0) | 2025.01.21 |