Java 객체지향의 정석
목차 23
Java 클래스 뼈대 위에 객체지향(OOP) 4대 기둥을 세우는 단원이다. 상속·오버라이딩·다형성·추상 클래스·인터페이스까지 매 회차 1~3문항 고정 출제되는 빈출 핵심이다. 41강의 클래스·캡슐화·접근 제어자 위에 ★캡상다추★(OOP 4대), ★로딩=쌓기/라이딩=덮어쓰기★(오버로딩 vs 오버라이딩), ★업=자동/다운=강제★(캐스팅) 세 두음을 본격으로 다룬다. 시험 1순위는 동적/정적 바인딩(메서드만 동적), 생성자 호출 순서(부모 먼저), abstract+final 모순이다.
대단원 1 — 상속 (Inheritance)
상속의 정의와 extends ·상속·
[정의] 상속 = 부모 클래스의 필드·메서드를 자식 클래스가 물려받는 것. class 자식 extends 부모 한 줄로 성립.
[표] 상속 4대 규칙
| 규칙 | 내용 |
|---|---|
| 단일 상속 | extends 부모 하나만 — 다중 상속 불가 (C++과 다름) |
| Object 자동 부모 | 모든 클래스의 최상위 부모는 Object — toString·equals·hashCode 자동 보유 |
| private 직접 접근 불가 | 상속은 되지만 자식이 직접 접근 불가 — getter/setter 경유 |
| 생성자는 상속 X | 자식은 super()로 부모 생성자를 호출만 가능 |
public class Animal {
String name;
public Animal(String name) { this.name = name; }
public void eat() { System.out.println(name + " 먹는다"); }
}
public class Dog extends Animal {
String breed;
public Dog(String name, String breed) {
super(name); // 부모 생성자 호출
this.breed = breed;
}
public void bark() { System.out.println(name + " 멍멍!"); }
}
// Dog d = new Dog("바둑이", "진돗개");
// d.eat(); → "바둑이 먹는다" (부모에게서 물려받음)
// d.bark(); → "바둑이 멍멍!" (자식 고유 메서드)
🔑 암기 extends 한 줄 = 부모 필드·메서드 전부 자동 + 자식 멤버 추가. Object까지 합쳐 toString·equals·hashCode도 기본.
⚠️ 함정 "Java는 다중 상속 가능" → 오답. 클래스는 단일 상속, 다중은 인터페이스 implements만.
🎯 빈출 단일 상속·다중 상속 불가가 매 회차. 인터페이스 다중 구현과 짝으로 출제.
💡 공통 로직(로그·인증·예외)을 부모 한 곳에 정의하고 자식 여럿이 물려받아 코드 중복을 막는 것이 상속의 실무 본질.
super 키워드 — 부모 메서드·생성자 호출 ·상속·시험 1순위·
[정의] super = 부모를 가리키는 참조. 두 용도 — super.메서드()(부모 메서드 호출)와 super()(부모 생성자 호출).
① super.메서드() — 부모 메서드 호출:
@Override
public void eat() {
super.eat(); // 부모 원본 먼저
System.out.println("간식도 먹는다!");
}
// 출력: 밥 먹는다 → 간식도 먹는다!
② super() — 부모 생성자 호출:
| 규칙 | 내용 |
|---|---|
| 위치 | 자식 생성자 첫 줄이어야 함 |
| 생략 시 | super() 자동 삽입 (부모 기본 생성자 호출) |
| 부모 기본 생성자 없으면 | 명시 안 하면 컴파일 오류 |
🔑 암기 this = 나를 가리키는 참조, super = 부모를 가리키는 참조. super()는 자식 생성자 첫 줄에 자동 삽입. ⚠️ 함정 super()와 this()는 둘 다 첫 줄이어야 해 동시 호출 불가. "동시 가능" → 오답. 🎯 빈출 super() 첫 줄·자동 삽입이 생성자 호출 순서와 짝으로 출제.
생성자 호출 순서 — 무조건 부모 먼저 ·상속·시험 1순위·
[정의] 객체 생성 시 생성자는 최상위 조상부터 자식 방향으로 실행된다. 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"); } }
new C(); // 출력: A → B → C (부모부터!)
┌─────────┐
│ C │ ← 3층 (마지막 실행)
├─────────┤
│ B │ ← 2층 (다음)
├─────────┤
│ A │ ← 1층 (먼저 실행!)
└─────────┘
🔑 암기 super() 첫 줄 자동 삽입 → 부모 생성자가 자식 본문보다 먼저. 다단계도 최상위 조상부터. ⚠️ 함정 "자식 먼저 실행" → 오답. 무조건 부모 먼저. 🎯 빈출 다단계 상속 출력 순서 추적이 매 회차 단골. 기출 ①에서 코드로 확인.
대단원 2 — 오버로딩과 오버라이딩
★로딩=쌓기 / 라이딩=덮어쓰기★ — 6항목 분별 ·오버라이딩·시험 1순위·
[정의] 오버로딩(Overloading) = 같은 이름·다른 매개변수로 메서드를 여러 개 쌓기. 오버라이딩(Overriding) = 부모 메서드를 자식이 같은 시그니처로 덮어쓰기.
[표] 6항목 분별
| 항목 | ★로딩=쌓기★ (오버로딩) | ★라이딩=덮어쓰기★ (오버라이딩) |
|---|---|---|
| 위치 | 같은 클래스 안 | 부모-자식 (extends) |
| 이름 | 같아야 함 | 같아야 함 |
| 매개변수 | 달라야 함 | 같아야 함 |
| 반환타입 | 무관 | 같거나 자식 타입 |
| 접근 제어자 | 무관 | 같거나 더 넓게 |
| 바인딩 | 컴파일 시점 (정적) | 실행 시점 (동적) |
🔑 암기 매개변수가 결정 — 같으면 ★라이딩=덮어쓰기★, 다르면 ★로딩=쌓기★. ⚠️ 함정 부모-자식 관계인데 매개변수가 다르면 오버라이딩이 아니라 자식에 새로 쌓은 오버로딩. 🎯 빈출 두 개념 분별·매개변수 조건이 매 회차. 41강 생성자 오버로딩(쌓기)에서 이어짐. 💡 같은 이름 메서드를 사이즈별로 여러 개 쌓는 것이 오버로딩, 부모 레시피를 자식이 다른 맛으로 덮어쓰는 것이 오버라이딩.
오버라이딩 시그니처 4조건 ·오버라이딩·
[정의] 오버라이딩이 성립하려면 네 조건을 만족해야 한다. 하나라도 어긋나면 오버라이딩이 아니다.
| # | 조건 | 규칙 | 어기면 |
|---|---|---|---|
| ① | 메서드 이름 | 부모와 완전 동일 | 새 메서드 |
| ② | 매개변수 | 개수·타입·순서 완전 동일 | 오버로딩 됨 |
| ③ | 반환타입 | 동일 또는 자식 타입(공변 반환) | 컴파일 오류 |
| ④ | 접근 제어자 | 부모와 같거나 더 넓게 | 컴파일 오류 |
🔑 암기 이름·매개변수·반환은 "같아야", 접근자만 "같거나 더 넓게". public > protected > default > private. ⚠️ 함정 접근 제어자를 부모보다 좁히면 컴파일 오류 — 자식은 부모보다 좁힐 수 없다. 🎯 빈출 "옳지 않은 것" 형태로 접근자 "좁게"가 단골 오답 보기. 기출 ②. 💡 @Override는 안 써도 동작하지만, 오타 시 컴파일러가 잡아주는 실무 필수 관행.
동적 바인딩 vs 정적 바인딩 — 메서드만 동적 ·오버라이딩·시험 1순위·
[정의] 부모 타입 변수에 자식 객체를 담았을 때 어느 멤버를 호출할지 결정하는 기준. 일반 메서드만 실제 객체(동적), 나머지는 컴파일 타입(정적).
| 멤버 | 바인딩 | 결과 |
|---|---|---|
| 일반 메서드 | 동적 | 실제 객체(자식)의 오버라이딩 메서드 |
| 필드 | 정적 | 컴파일 타입(부모)의 필드 |
| static 메서드 | 정적 | 컴파일 타입(부모) |
| final·private | 정적 | 부모 메서드 |
class A {
String name = "A";
public void show() { System.out.println("A의 show"); }
public static void describe() { System.out.println("A의 static"); }
public final void info() { System.out.println("A의 final"); }
}
class B extends A {
String name = "B";
@Override public void show() { System.out.println("B의 show"); }
public static void describe() { System.out.println("B의 static"); }
}
A a = new B();
a.name; // → "A" (필드 = 정적)
a.show(); // → "B의 show" (메서드 = 동적)
a.describe(); // → "A의 static" (static = 정적)
a.info(); // → "A의 final" (final = 정적)
🔑 암기 "메서드만 동적, 나머지는 정적" 한 줄이면 동적/정적 바인딩 문제 정답. ⚠️ 함정 "필드도 자식 값 호출" → 오답. 필드는 정적(부모 값) — 오버라이딩이 아니라 가리기(hiding). 🎯 빈출 매 회차 1~2문제. 기출 ③에서 필드·메서드 출력 추적으로 확인.
대단원 3 — OOP 4대 특성 (★캡상다추★)
★캡상다추★ — OOP 4대 특성 ·객체지향·시험 1순위·
[정의] 객체지향(OOP)의 4대 특성 = 캡슐화·상속·다형성·추상화. 두음 ★캡상다추★.
| ★캡상다추★ | OOP 특성 | Java 키워드 |
|---|---|---|
| 캡 | 캡슐화 (Encapsulation) | private 필드 + public getter/setter |
| 상 | 상속 (Inheritance) | extends + super() |
| 다 | 다형성 (Polymorphism) | Parent p = new Child(); + 동적 바인딩 |
| 추 | 추상화 (Abstraction) | abstract class + interface |
🔑 암기 ★캡상다추★ 4글자 = OOP 4대. 직렬화·동기화·은닉화·모듈화는 포함 X. ⚠️ 함정 "4대 특성이 아닌 것?"에서 직렬화(데이터 처리)·동기화(스레드 보호)·은닉화(캡슐화의 효과)·모듈화(SW 설계 원칙)가 정답 보기. 🎯 빈출 "4대 특성에 포함되지 않는 것" 매 회차 단골. 기출 ⑦. 💡 SOLID(설계 5원칙)와 ★캡상다추★(4대 특성)는 다른 영역 — 보기에서 섞이면 함정 (7강 참조).
★캡상다추★ 한 코드 종합 ·객체지향·
[정의] 클래스 구성 위에 4대 특성을 한 코드에 쌓은 예 — 캡(private)·상(extends)·다(부모타입+자식객체)·추(abstract/interface).
interface Payable { void pay(long amount); } // 추(추상화)
abstract class Account implements Payable {
private long balance = 0; // 캡(캡슐화)
public long getBalance() { return balance; }
protected void deposit(long a) { balance += a; }
abstract String accountType(); // 추(추상 메서드)
}
class SavingAccount extends Account { // 상(상속)
@Override public void pay(long amount) { // 다(다형성·오버라이딩)
deposit(amount);
System.out.println(accountType() + " 입금: " + amount + " / 잔액: " + getBalance());
}
@Override String accountType() { return "저축"; }
}
Payable p = new SavingAccount(); // 다(부모 타입 + 자식 객체)
p.pay(10000); // 동적 바인딩 → "저축 입금: 10000 / 잔액: 10000"
🔑 암기 한 컷에 캡(private)·상(extends)·다(부모타입+자식객체+동적바인딩)·추(abstract/interface)가 전부. 🎯 빈출 4대 특성과 Java 키워드 매칭이 빈출. 코드에서 어느 줄이 어느 특성인지 식별. 💡 인터페이스(추상화) + 자식 구현체(다형성) 구조 — 새 기능 추가 시 자식 클래스 1개만 만들면 되는 것이 OOP 4대의 실무 가치.
대단원 4 — 다형성과 캐스팅
다형성 — 부모 타입 하나로 자식 여럿 + 3요소 ·다형성·시험 1순위·
[정의] 다형성(Polymorphism) = 하나의 부모 타입이 여러 자식 형태로 동작하는 것. 부모 타입 변수에 자식 객체를 담고 동적 바인딩으로 자식 메서드가 호출된다.
Animal[] animals = { new Dog(), new Cat(), new Cow() };
for (Animal a : animals) {
a.cry(); // 같은 a.cry() — 실제 객체에 따라 다른 동작
}
// 출력: 멍멍! / 야옹! / 음매!
[표] 다형성 3요소 (셋 다 갖춰야 동적 바인딩 작동)
| # | 요소 | 내용 |
|---|---|---|
| ① | 상속/구현 | 부모-자식 또는 인터페이스 구현 관계 |
| ② | 오버라이딩 | 자식이 부모 메서드를 덮어씀 |
| ③ | 부모 타입 변수 | 부모 타입에 자식 객체 대입 |
🔑 암기 다형성 = 부모 타입 변수 + 자식 객체 + 동적 바인딩.
🎯 빈출 다형성 정의·3요소가 빈출. 자식 100종도 부모 타입 메서드 하나로 처리.
💡 void makeCry(Animal a){ a.cry(); } 하나로 자식 전부 처리되고, 새 자식이 추가돼도 기존 코드를 안 건드리는 것이 다형성의 확장성.
★업=자동 / 다운=강제★ — 캐스팅 방향 ·다형성·
[정의] 업캐스팅(Upcasting) = 자식 객체를 부모 타입으로 변환(자동·안전). 다운캐스팅(Downcasting) = 부모 타입을 자식 타입으로 변환(강제·위험).
| 항목 | ★업=자동(안전)★ | ★다운=강제(위험)★ |
|---|---|---|
| 방향 | 자식 → 부모 | 부모 → 자식 |
| 캐스트 | 자동 (생략 가능) | 강제 (명시 필수) |
| 안전성 | 항상 안전 | ClassCastException 위험 |
| 사전 검사 | 불필요 | instanceof 필수 |
Animal a = new Dog(); // 업캐스팅 — 자동, 안전
Dog d = (Dog) a; // 다운캐스팅 — 강제, 실제 객체가 Dog 아니면 런타임 예외
🔑 암기 업 = 자동·안전(자식은 항상 부모), 다운 = 강제·위험(부모가 다 자식은 아님).
⚠️ 함정 다운캐스팅을 자동으로 안다고 하면 오답 — 명시 캐스트 + instanceof 필요.
🎯 빈출 업/다운 방향·안전성 분별. 기출 ④에서 instanceof 없는 다운캐스팅 결과.
💡 Java 16+ 패턴 매칭(if (a instanceof Dog d))은 필기 범위 밖 — 실기·실무 영역.
instanceof — 안전 다운캐스팅 3단 ·다형성·시험 1순위·
[정의] instanceof = 객체가 특정 타입인지 검사하는 연산자. 다운캐스팅 전에 검사해 ClassCastException을 막는다.
public void care(Animal a) {
a.cry(); // 다형성 — 모든 동물 공통
if (a instanceof Dog) { // ① 검사
Dog d = (Dog) a; // ② 안전 다운캐스팅
d.bark(); // ③ 자식 고유 메서드
}
}
🔑 암기 안전 다운캐스팅 3단 — instanceof 검사 → (Dog) 캐스트 → 자식 고유 메서드. ⚠️ 함정 instanceof 없이 다운캐스팅하면 실제 타입 불일치 시 ClassCastException(런타임). 🎯 빈출 instanceof + 다운캐스팅 결합 패턴이 빈출. 기출 ④와 짝.
대단원 5 — 추상 클래스와 인터페이스
추상 클래스 — 미완성 설계도·new 불가 ·추상화·시험 1순위·
[정의] 추상 클래스(abstract class) = 추상 메서드를 1개 이상 가진 미완성 클래스. 직접 new 불가, 자식이 추상 메서드를 구현해야 인스턴스화된다.
abstract class Shape {
protected String color;
public Shape(String c) { this.color = c; } // 생성자 가능
public String getColor() { return color; } // 일반 메서드 가능
public abstract double area(); // 추상 메서드 — 자식 구현 강제
}
class Circle extends Shape {
private double r;
public Circle(String c, double r) { super(c); this.r = r; }
@Override public double area() { return Math.PI * r * r; }
}
// Shape s = new Shape("red"); ← 컴파일 오류! (추상 클래스 new 불가)
Shape s = new Circle("red", 5); // OK — 다형성 (area = 78.53...)
🔑 암기 추상 클래스 = abstract + 추상 메서드 1개 이상 + new 불가 + 일반 메서드·필드·생성자도 보유. ⚠️ 함정 "추상 클래스 new 가능" → 오답. 자식을 통해서만 인스턴스화. 🎯 빈출 추상 클래스 특성 "옳지 않은 것"에서 new 가능이 단골 오답. 기출 ⑤.
인터페이스 — 다중 구현·자동 public abstract ·추상화·시험 1순위·
[정의] 인터페이스(interface) = 메서드 명세만 정의한 계약서. 클래스가 implements로 구현하며 다중 구현이 가능하다.
interface Drawable { void draw(); } // 자동 public abstract
interface Movable { void move(int x, int y); }
class Player implements Drawable, Movable { // 다중 implements!
@Override public void draw() { /* 구현 */ }
@Override public void move(int x, int y) { /* 구현 */ }
}
| 특징 | 내용 |
|---|---|
| 모든 메서드 | 자동 public abstract (명시 불필요) |
| 다중 implements | 가능 — 클래스 단일 상속과 핵심 차이 |
| 변수 | 자동 public static final (상수만) |
| new | 불가 (추상 클래스와 동일) |
🔑 암기 클래스는 단일 상속, 인터페이스는 다중 구현. 메서드 자동 public abstract, 변수 자동 상수. ⚠️ 함정 "인터페이스 단일 implements만 가능" → 오답. 다중 구현이 핵심 차이. 🎯 빈출 단일/다중 분별이 매 회차 단골 결정 문항. 기출 ⑥.
Java 8+ default 메서드 ·추상화·
[정의] Java 8부터 인터페이스가 default 메서드(본문 있는 메서드)와 static 메서드를 가질 수 있다.
interface Drawable {
void draw(); // 추상 메서드
default void describe() { // Java 8+ default — 본문 가짐
System.out.println("그릴 수 있는 객체");
}
}
| Java 버전 | 인터페이스 능력 |
|---|---|
| 1.0~7 | 추상 메서드 + 상수만 |
| 8+ | + default 메서드 + static 메서드 |
| 17+ | + sealed 인터페이스 |
🔑 암기 Java 8+ 인터페이스는 default·static 메서드 보유 가능 (본문 있음). ⚠️ 함정 "인터페이스는 모든 메서드가 반드시 추상" → Java 8+ 기준 오답. 🎯 빈출 Java 8 default 메서드 등장이 "옳은 것" 보기로 출제. 기출 ⑥. 💡 필기는 Java 8 default까지가 본격. sealed·record·패턴 매칭은 실기·실무 영역.
추상 클래스 vs 인터페이스 5항목 ·추상화·시험 1순위·
[정의] 둘 다 new 불가·미완성 설계지만, 다중 여부·생성자·필드에서 갈린다.
| 항목 | 추상 클래스 | 인터페이스 |
|---|---|---|
| 키워드 | abstract class / extends |
interface / implements |
| 다중 | 단일만 (1개) | 다중 가능 |
| 생성자 | 있음 (super()용) | 없음 |
| 메서드 본문 | 일반 + 추상 둘 다 | 추상 (+ Java 8+ default) |
| 필드 | 일반 필드 가능 | 상수만 (public static final) |
🔑 암기 추상 클래스 = 공통 로직 + 일부 추상(단일·생성자 O), 인터페이스 = 계약 + 다중 구현(생성자 X). ⚠️ 함정 "추상 클래스는 일반 메서드 불가" → 오답. "인터페이스는 단일만" → 오답. 둘 다 new 불가는 동일. 🎯 빈출 5항목 짝짓기가 매년 단골. 다중·생성자·필드가 결정 포인트.
abstract + final = 컴파일 오류 ·추상화·시험 1순위·
[정의] abstract(자식이 반드시 구현)와 final(자식이 손댈 수 없음)은 정반대 명령이라 동시 적용 시 컴파일 오류.
abstract final class A { } // 컴파일 오류! (modifiers 충돌)
abstract class B {
public abstract final void m(); // 컴파일 오류!
}
final class Sealed { }
class Sub extends Sealed { } // 컴파일 오류! (final 클래스 상속 불가)
| 키워드 | 의미 |
|---|---|
| abstract | 자식이 구현하라 (상속 강제) |
| final | 자식이 손대지 마라 (상속·오버라이딩 금지) |
🔑 암기 abstract + final = 모순 → 컴파일 오류. final 클래스는 상속 불가. ⚠️ 함정 "abstract + final 동시 가능" → 오답. 컴파일러가 거부. 🎯 빈출 abstract+final 모순이 매년 단골. final 클래스 상속 불가와 짝. 기출 ⑧. 💡 String·Integer·Math는 final 클래스라 상속 불가 — Java 보안·일관성의 본질.
기출 다지기
[기출 1 출제] 다음 Java 코드의 출력 결과는? (다단계 상속 생성자 호출 순서)
class A { public A() { System.out.print("A"); } }
class B extends A { public B() { System.out.print("B"); } }
class C extends B { public C() { System.out.print("C"); } }
public class Main {
public static void main(String[] args) { C c = new C(); }
}
- ① C
- ② CBA
- ③ ABC
- ④ CB
정답 및 해설 보기
정답: ③ ABC
super()가 자식 생성자 첫 줄에 자동 삽입되니 Object → A → B → C 순서로 실행된다. 출력은 A, B, C가 붙어 ABC.
| 보기 | 판정 | 함정 |
|---|---|---|
| ② CBA | 오답 | 호출 순서 거꾸로 — 매년 단골 함정 |
| ③ ABC | 정답 | 부모 먼저(A) → B → C |
🔑 암기 다단계 상속도 최상위 조상부터 위에서 아래로. "자식 먼저 실행" 보이면 오답.
[기출 2 출제] 오버라이딩(Overriding)의 조건으로 옳지 않은 것은? (옳지 않은 것 고르기)
- ① 부모 메서드와 이름이 같아야 한다
- ② 부모 메서드와 매개변수 개수·타입이 같아야 한다
- ③ 부모 메서드보다 접근 제어자를 더 좁게 설정해야 한다
- ④ 부모 메서드와 반환타입이 같거나 자식 타입이어야 한다
정답 및 해설 보기
정답: ③
접근 제어자는 부모와 같거나 더 넓게여야 한다. "더 좁게"라 했으니 오답. public > protected > default > private 순서에서 자식이 부모보다 좁히면, 부모 타입으로 받아 쓸 때 호출이 막히므로 컴파일러가 차단한다.
🔑 암기 이름·매개변수·반환은 "같아야", 접근자만 "같거나 더 넓게". "좁게" 보이면 오답.
[기출 3 출제] 다음 Java 코드의 출력 결과는? (필드·메서드 바인딩)
class Animal {
String type = "동물";
public void cry() { System.out.println("동물의 울음"); }
}
class Dog extends Animal {
String type = "강아지";
@Override public void cry() { System.out.println("멍멍!"); }
}
public class Main {
public static void main(String[] args) {
Animal a = new Dog();
System.out.println(a.type);
a.cry();
}
}
- ① 동물 / 동물의 울음
- ② 동물 / 멍멍!
- ③ 강아지 / 동물의 울음
- ④ 강아지 / 멍멍!
정답 및 해설 보기
정답: ② 동물 / 멍멍!
a.type — 필드는 정적 바인딩이라 컴파일 타입(Animal)의 값 동물. a.cry() — 일반 메서드는 동적 바인딩이라 실제 객체(Dog)의 멍멍!.
| 보기 | 판정 | 함정 |
|---|---|---|
| ④ 강아지 / 멍멍! | 오답 | 필드를 동적으로 잘못 이해 |
| ② 동물 / 멍멍! | 정답 | 필드=정적, 메서드=동적 |
🔑 암기 필드는 오버라이딩이 아니라 가리기(hiding) — 컴파일 타입의 필드가 그대로. "필드도 자식 값" 보이면 오답.
[기출 4 출제] 다음 Java 코드의 실행 결과는? (instanceof 없는 다운캐스팅)
class Animal { }
class Dog extends Animal { public void bark() { System.out.println("멍멍!"); } }
class Cat extends Animal { }
public class Main {
public static void main(String[] args) {
Animal a = new Cat();
Dog d = (Dog) a;
d.bark();
}
}
- ① "멍멍!" 출력
- ② 컴파일 오류
- ③ null 출력
- ④ 런타임에 ClassCastException 발생
정답 및 해설 보기
정답: ④ 런타임에 ClassCastException 발생
Animal a = new Cat()는 업캐스팅(자동·안전), 실제 객체는 Cat. (Dog) a는 다운캐스팅(강제) — 컴파일은 통과하지만 런타임에 Cat을 Dog로 바꾸려 하니 ClassCastException.
| 보기 | 판정 | 함정 |
|---|---|---|
| ② 컴파일 오류 | 오답 | 컴파일은 통과 (부모-자식 관계라 캐스트 허용) |
| ④ ClassCastException | 정답 | 런타임에 실제 타입 불일치 |
🔑 암기 컴파일 통과·런타임 실패가 핵심. 안전 패턴은 if (a instanceof Dog) 검사 후 캐스트.
[기출 5 출제] 추상 클래스에 대한 설명으로 옳지 않은 것은? (옳지 않은 것 고르기)
- ① abstract 키워드를 사용하여 선언한다
- ② 추상 메서드를 1개 이상 포함할 수 있다
- ③ 일반 메서드와 필드도 포함할 수 있다
- ④ 추상 클래스로 직접 인스턴스를 생성할 수 있다
정답 및 해설 보기
정답: ④
추상 클래스는 직접 new가 불가능하다. 자식 클래스를 통해서만 인스턴스를 만든다. ①·②·③은 모두 옳은 설명 — abstract 선언, 추상 메서드 1개 이상, 일반 메서드·필드도 보유. 100% 추상이 아닌 것이 인터페이스와의 차이다.
🔑 암기 추상 클래스·인터페이스 둘 다 new 불가. "추상 클래스 new 가능" 보이면 오답.
[기출 6 출제] Java 인터페이스에 대한 설명으로 옳은 것은? (옳은 것 고르기)
- ① 인터페이스는 단일 implements만 가능하다
- ② 모든 메서드는 반드시 본문 없이 추상 메서드여야 한다
- ③ Java 8부터 default 메서드와 static 메서드를 정의할 수 있다
- ④ new로 직접 인스턴스를 생성할 수 있다
정답 및 해설 보기
정답: ③
| 보기 | 판정 | 이유 |
|---|---|---|
| ① 단일만 | 오답 | 다중 implements 가능 |
| ② 전부 추상 | 오답 | Java 8+ default·static은 본문 가짐 |
| ③ Java 8+ default/static | 정답 | 인터페이스 진화 핵심 |
| ④ new 가능 | 오답 | new 불가 |
🔑 암기 클래스 단일 상속 / 인터페이스 다중 구현. Java 8+ default 메서드로 본문 보유 가능.
[기출 7 출제] 객체지향(OOP) 4대 특성에 포함되지 않는 것은? (포함되지 않는 것 고르기)
- ① 캡슐화 (Encapsulation)
- ② 상속 (Inheritance)
- ③ 직렬화 (Serialization)
- ④ 다형성 (Polymorphism)
정답 및 해설 보기
정답: ③ 직렬화
★캡상다추★ 4글자(캡슐화·상속·다형성·추상화)만 OOP 4대다.
| 함정 단어 | 정체 |
|---|---|
| 직렬화 (Serialization) | 객체→바이트 변환, 데이터 처리 기법 |
| 동기화 (Synchronization) | 멀티스레드 자원 보호 기법 |
| 은닉화 (Information Hiding) | 캡슐화의 효과 (별도 항목 X) |
| 모듈화 (Modularization) | 일반 SW 설계 원칙 |
🔑 암기 OOP 4대 = ★캡상다추★. 직렬화·동기화·은닉화·모듈화는 포함 X.
[기출 8 출제] abstract와 final 키워드에 대한 설명으로 옳지 않은 것은? (옳지 않은 것 고르기)
- ① abstract 클래스는 직접 인스턴스화할 수 없다
- ② final 클래스는 상속할 수 없다
- ③ final 메서드는 오버라이딩할 수 없다
- ④ 하나의 클래스에 abstract와 final을 함께 선언할 수 있다
정답 및 해설 보기
정답: ④
abstract(자식이 반드시 구현)와 final(자식이 손댈 수 없음)은 정반대 명령이라 함께 선언하면 컴파일 오류. ①·②·③은 모두 옳다.
| 보기 | 판정 | 이유 |
|---|---|---|
| ② final 클래스 상속 X | 옳음 | String·Integer·Math가 final |
| ④ abstract + final 함께 | 정답(옳지 않음) | modifiers 충돌 → 컴파일 오류 |
🔑 암기 abstract + final = 모순. final 클래스는 상속 불가, final 메서드는 오버라이딩 불가.
한 장 요약
| 주제 | 암기·핵심 | 결정 카드 |
|---|---|---|
| OOP 4대 | ★캡상다추★ | 직렬화·동기화·은닉화·모듈화는 포함 X |
| 상속 | extends·단일 | 다중은 인터페이스만 · Object 자동 부모 |
| super | 부모 참조 | super() 첫 줄 자동 삽입 · this()와 동시 불가 |
| 생성자 순서 | 부모 → 자식 | 다단계도 최상위 조상부터 (ABC) |
| 오버로딩 vs 오버라이딩 | ★로딩=쌓기/라이딩=덮어쓰기★ | 매개변수 같으면 라이딩, 다르면 로딩 |
| 오버라이딩 4조건 | 이름·매개변수·반환 동일 | 접근자만 같거나 더 넓게 (좁게 = 오류) |
| 바인딩 | 메서드=동적 / 필드·static·final=정적 | "필드도 자식 값" = 오답 |
| 다형성 | 부모 타입 + 자식 객체 | 3요소: 상속·오버라이딩·부모 타입 변수 |
| 캐스팅 | ★업=자동/다운=강제★ | 다운 = instanceof 검사 후 (CCE 위험) |
| 추상 클래스 | abstract·new 불가 | 단일·생성자 O·일반 메서드 O |
| 인터페이스 | 다중 implements | 자동 public abstract·상수만·Java 8+ default |
| abstract + final | 모순 = 컴파일 오류 | final 클래스 상속 불가 (String·Integer) |
시험 직전 함정 즉답:
| 함정 보기 | 즉답 |
|---|---|
| 자식 생성자 먼저 실행 | 오답 — 부모 먼저 |
| 필드도 자식 값 호출 | 오답 — 필드는 정적(부모) |
| 매개변수 다른데 오버라이딩 | 오답 — 오버로딩 |
| 추상 클래스 new 가능 | 오답 — new 불가 |
| Java 다중 상속 가능 | 오답 — 인터페이스만 다중 |
| abstract + final 동시 가능 | 오답 — 컴파일 오류 |
