문서 읽는 데 56분 · 41강 · 4과목 · 프로그래밍 언어 활용

Java 첫걸음: 클래스·접근제어자·OOP 입문

목차 23
전체 59강 중 41강 · 4과목 · 프로그래밍 언어 활용

Java 첫걸음은 객체지향의 입구다. 클래스(설계도)와 객체(실체), 접근 제어자 4종 매트릭스, 생성자·static, 그리고 Java 타입 시스템(참조 vs 기본·Integer 캐시·String 불변·==/equals)을 한 바퀴 돈다. 매 회차 1~2문항 꾸준히 나오는 빈출 단원으로, 접근 제어 범위 · Integer 캐시 · String 비교가 단골 함정이다. 39·40강의 C(절차형·수동 메모리·포인터)와 달리 Java는 객체지향·자동 GC·참조로 메모리를 다룬다. 상속·다형성·추상 클래스/인터페이스는 42강에서 본격적으로 이어진다.

핵심 암기: 접근 제어자 4종 ★공보기사★(공개 public > 보호 protected > 기본 default > 사적 private) · 클래스 4대 구성 ★클필메생★(클래스·필드·메서드·생성자) · Integer 캐시 -128~127 · String 불변 + 리터럴 풀 · ==는 주소 / equals는 값


PART A — Java 진입

Java 정의 — 1995·고슬링·WORA·JVM ·Java 개요·

[정의] Java = 1995년 Sun Microsystems의 제임스 고슬링이 만든 객체지향 프로그래밍 언어. 2010년 Oracle이 인수했다. 슬로건은 WORA(Write Once, Run Anywhere) — 한 번 컴파일하면 어디서든 실행.

[흐름] 컴파일·실행 단계

텍스트
Java 소스 (.java)
    javac (컴파일)
바이트코드 (.class)       플랫폼 독립
    JVM (해석·실행)
실행 결과                 Windows / Mac / Linux 어디서든

[표] 절차형(C) vs Java

항목 절차형 언어(C) Java
패러다임 절차형 객체지향
메모리 관리 수동(직접 할당·해제) 자동 GC
포인터 직접 포인터 참조(자동)
플랫폼 OS 종속 JVM 독립(WORA)
실행 컴파일러 단일(.exe) 컴파일 + 인터프리트 하이브리드(.class + JVM)

💡 JVM = 통역사. 한 번 영어로 번역(.class)해두면 각 나라(OS)의 통역사(JVM)가 현지 기계어로 즉시 바꿔준다. JVM의 역할 셋 — 바이트코드 해석 · 메모리 자동 관리(GC) · 플랫폼 추상화(WORA).

🔑 암기 "Java = 1995 고슬링 / Sun→Oracle / WORA / JVM 하이브리드(컴파일+인터프리트) / 객체지향+자동 GC"

⚠️ 함정 Java는 순수 컴파일 언어가 아니다 — javac 컴파일 후 JVM이 바이트코드를 해석하는 하이브리드(38강 컴파일러 vs 인터프리터 회수).

🎯 빈출 Java 정의·WORA·JVM 역할이 정의 문제로 간헐 출제.

Hello World — main 시그니처 ·Java 개요·

[정의] 모든 Java 프로그램의 시작점은 main 메서드. 시그니처 public static void main(String[] args)는 토씨까지 고정이다.

[코드]

Java
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

[표] main 시그니처 5요소

키워드 의미
public 어디서든 접근 가능
static 객체 없이 호출(JVM이 객체 생성 없이 진입)
void 반환값 없음
main JVM이 자동으로 찾는 시작점
String[] args 명령행 인자 배열

💡 클래스명 = 파일명 일치 필수(public class HelloWorldHelloWorld.java). java.lang 패키지(String·Integer·Math·System)는 import 없이 자동 사용.

🔑 암기 "public static void main(String[] args) — 토씨까지. static 빠지면 진입 불가, String[]이 String이면 main 인식 안 됨"

🎯 빈출 main 시그니처 정확성·클래스명=파일명.


PART B — 클래스와 객체

클래스 vs 객체 — 붕어빵 틀과 붕어빵 ·클래스·시험 1순위·

[정의] 클래스(Class) = 설계도(붕어빵 틀). 객체(Object) = 클래스로 찍어낸 실체(붕어빵). new가 Heap에 객체를 할당한다.

[표] 셋의 분별

용어 한 줄
클래스 붕어빵 틀 — 설계도. 메모리에 1회 정의
객체 붕어빵 — 틀로 찍어낸 실체. 데이터 있음
new 붕어빵 찍는 동작 — Heap에 객체 할당

[코드]

Java
Student s1 = new Student();    // 붕어빵 하나 찍기 — Heap에 객체
Student s2 = new Student();    // 또 하나 — 별개 객체

💡 절차형 언어의 구조체는 데이터만 묶고 행동(함수)은 따로였다. Java 클래스는 데이터(필드)와 행동(메서드)을 한 덩어리로 묶는다 — 이게 객체지향의 시작.

🔑 암기 "클래스 = 붕어빵 틀(설계도) / 객체 = 붕어빵(실체) / new = Heap에 찍어내기"

🎯 빈출 클래스 vs 객체(인스턴스) 분별이 매 회차.

★클필메생★ — 클래스 4대 구성 ·클래스·시험 1순위·

[정의] 클래스를 이루는 4대 구성요소. 두음 ★클필메생★래스 정의 · 드 · 서드 · 성자.

[표] 4대 구성

두음 구성요소 한 줄
클래스 정의 class 키워드 + 클래스명(파일명 일치)
필드(Field) 멤버 변수 — 객체의 상태. 보통 private
메서드(Method) 멤버 함수 — 객체의 행동. 보통 public
생성자(Constructor) 객체 생성 시 자동 호출. 클래스명 동일, 반환타입 없음

[코드]

Java
public class Student {                          // 클 — 클래스 정의
    private String name;                        // 필 — 필드(private)
    private int age;

    public Student(String name, int age) {      // 생 — 생성자(클래스명 동일·반환타입 없음)
        this.name = name;
        this.age = age;
    }
    public String getName() { return name; }    // 메 — 메서드
}

💡 ★클필메생★ = 자동차 4대 부품. 차종(클) + 부품(필) + 움직임(메) + 공장 조립(생).

🔑 암기 "★클필메생★ — 클(class)·필(필드·상태)·메(메서드·행동)·생(생성자)"

⚠️ 함정 생성자 4대 특징 — ① 이름 = 클래스명 ② 반환타입 없음(void도 아님) ③ 기본 생성자 자동 생성(인자 생성자 만들면 사라짐) ④ new와 함께 자동 호출.

🎯 빈출 생성자 이름=클래스명 + 반환타입 없음이 단골.

★공보기사★ — 접근 제어자 4×4 매트릭스 ·접근 제어자·시험 1순위·

[정의] 접근 제어자 4종을 범위 넓음→좁음으로. 두음 ★공보기사★개 public > 호 protected > 본 default(생략) > 적 private.

[표] 접근 범위 4×4 (시험 1순위)

★공보기사★ 같은 클래스 같은 패키지 자식(다른 패키지) 외부
public O O O O
protected O O O X
default(생략) O O X X
private O X X X

[코드]

Java
public class Base {
    public    String pub  = "공";   // 공 — 어디서든
    protected String prot = "보";   // 보 — 같은 패키지 + 다른 패키지 자식
    String           def  = "기";   // 기 — 키워드 생략, 같은 패키지만
    private   String priv = "사";   // 사 — 이 클래스 안에서만
}

💡 백화점 출입 권한 4단계 — 공=1층 매장(누구나) · 보=VIP 라운지(VIP+자녀) · 기=직원 휴게실(같은 매장 직원) · 사=오너 집무실(본인만).

🔑 암기 "★공보기사★ 범위 넓음→좁음 · 매트릭스 4×4 · default=키워드 생략(같은 패키지) / protected=거기에 다른 패키지 자식 추가"

⚠️ 함정 default vs protected가 매년 1순위 — default는 같은 패키지까지(다른 패키지 자식 X), protected는 다른 패키지 자식까지 O. private은 같은 클래스 안에서만('같은 패키지' 붙으면 틀린 설명).

🎯 빈출 접근 제어 매트릭스가 매 회차 1문제 무조건.

캡슐화 — private + getter/setter + 검증 ·캡슐화·

[정의] 캡슐화(Encapsulation) = 필드를 private으로 숨기고, public getter/setter로만 접근시키는 것. ★공보기사★의 사(private)를 본격 활용한다.

[코드]

Java
public class Account {
    private long balance;                        // 필드는 private

    public long getBalance() { return balance; } // getter — 읽기

    public void setBalance(long amount) {        // setter + 검증
        if (amount < 0) throw new IllegalArgumentException("음수 불가");
        this.balance = amount;
    }
}

💡 약 캡슐 — 약 가루(private 필드)는 껍질(getter/setter) 안에 감싸지고, 외부는 캡슐을 통해서만 접근한다. 필드를 public으로 열면 a.balance = -1000처럼 음수도 그냥 들어간다. 위 코드는 음수 입력 시 실제로 예외가 던져져 차단되는 것을 확인했다.

🔑 암기 "캡슐화 = private 필드 + public getter/setter + 검증 1줄"

🎯 빈출 캡슐화 정의·이점(데이터 보호·검증·변경 자유)이 간헐. 캡슐화는 OOP 4대 특성 중 하나(42강 ★캡상다추★ 종합).


PART C — 생성자·this·static

생성자 오버로딩 — 기본 생성자 사라짐 함정 ·생성자·시험 1순위·

[정의] 오버로딩(Overloading) = 같은 이름 + 다른 매개변수로 쌓기. 생성자도 매개변수 개수·타입이 다르면 여러 개 만들 수 있다.

[코드]

Java
public class Student {
    private String name;
    private int age;

    public Student() { this("이름없음", 0); }        // 기본 → this()
    public Student(String name) { this(name, 0); }   // 인자 1개
    public Student(String name, int age) {           // 인자 2개 — 오버로딩
        this.name = name;
        this.age = age;
    }
}
Student s1 = new Student();           // 이름없음 / 0
Student s2 = new Student("민지");      // 민지 / 0
Student s3 = new Student("지훈", 22);  // 지훈 / 22

💡 위 세 생성자는 실제로 각각 이름없음/0, 민지/0, 지훈/22를 만들어낸다 — 같은 이름이지만 매개변수가 달라 별개로 인식된다.

🔑 암기 "오버로딩 = 같은 이름·다른 매개변수 · 인자 생성자만 만들면 기본 생성자 자동 생성이 사라짐"

⚠️ 함정 public B(String s) {}만 정의하면 new B()컴파일 오류(기본 생성자가 사라짐). 매년 단골.

🎯 빈출 기본 생성자 사라짐·오버로딩 성립 여부.

this 키워드 — 3대 용도 ·생성자·

[정의] this = 현재 객체 자신을 가리키는 참조. 3대 용도 = this.필드(매개변수와 이름 충돌 해소) · this()(다른 생성자 호출, 첫 줄만) · return this(메서드 체이닝).

[표] this 3대 용도

용도 의미
this.필드 매개변수와 같은 이름의 멤버 필드 구분
this(인자) 같은 클래스의 다른 생성자 호출(생성자 첫 줄만)
return this 자기 자신 반환(메서드 체이닝)

💡 this()super()(부모 생성자 호출)는 둘 다 생성자 첫 줄에 와야 해서 동시 사용이 불가능하다 — 시험 단골 함정. super로 부모를 호출하는 상속은 42강에서 본격적으로 다룬다.

🔑 암기 "this = 현재 객체 · this.필드(충돌 해소) / this()(다른 생성자·첫 줄) / return this(체이닝)"

⚠️ 함정 this()super() 동시 사용 불가(둘 다 첫 줄).

🎯 빈출 this.필드로 매개변수 충돌 해소·this() 첫 줄 제약.

static — 칠판(공유) vs 인스턴스(개인 노트) ·static·시험 1순위·

[정의] static = 클래스 변수/메서드. 모든 객체가 공유(칠판)하며 객체 없이 클래스명으로 호출. 인스턴스 멤버는 객체마다 따로(개인 노트).

[코드]

Java
public class Counter {
    private static int totalCount = 0;     // static — 모든 객체 공유(칠판)
    private int myCount = 0;                // 인스턴스 — 객체마다 따로(개인 노트)

    public void increment() {
        totalCount++;                      // 칠판 +1 — 모든 객체에 영향
        myCount++;                         // 내 노트 +1 — 이 객체만
    }
    public static int getTotal() { return totalCount; } // 객체 없이 호출
}
// c1 두 번·c2 한 번 increment → totalCount=3(공유) / c1.my=2 · c2.my=1

[표] static vs 인스턴스

구분 static(클래스 변수) 인스턴스 변수
저장 Method Area, 1개만 Heap, 객체마다
공유 모든 객체 공유(칠판) 객체마다 따로(개인 노트)
호출 클래스명.멤버 객체참조.멤버

💡 두 객체가 increment를 합쳐 3번 부르면 공유 칠판 totalCount는 3, 개인 노트 myCount는 각각 2와 1로 갈린다 — 실행으로 확인했다.

🔑 암기 "static = 칠판(공유·Method Area) / 인스턴스 = 개인 노트(Heap) · 클래스명.메서드() 호출"

⚠️ 함정 static 메서드에서 this 사용 불가(객체와 무관 → this 없음). 인스턴스 필드 직접 접근도 불가 — 시도하면 컴파일 오류.

🎯 빈출 static에서 this·인스턴스 필드 접근이 컴파일 오류로 매 회차.


PART D — Java 메모리와 타입

Java 메모리 3영역 — Stack·Heap·Method Area ·메모리·

[정의] Java 메모리는 3영역. Stack(지역 변수·매개변수·참조 변수) · Heap(객체·인스턴스 필드·배열) · Method Area(클래스 메타정보·static 필드).

[흐름] 영역별 저장 대상

텍스트
┌──────────────┐
│  Stack       │  지역 변수 · 매개변수 · 참조 변수(주소)   함수 끝나면 자동 반납
├──────────────┤
│  Heap        │  객체(new) · 인스턴스 필드 · 배열   자동 GC가 회수
├──────────────┤
│  Method Area │  클래스 메타정보 · static 필드   클래스 로드 시 1회
└──────────────┘

💡 Stack은 도서관 사물함(자동 반납), Heap은 창고(GC 청소부가 자동 정리). 절차형 언어는 할당·해제를 직접 했지만, Java는 new 한 줄로 Heap에 올리고 GC가 알아서 치운다.

🔑 암기 "객체는 Heap / 참조 변수는 Stack / static은 Method Area · free 없이 GC가 회수"

⚠️ 함정 객체는 Heap(Stack 아님) · static은 Method Area(Heap 아님) · Java에 free 키워드 없음(GC가 처리).

🎯 빈출 영역별 저장 대상 매칭(객체·static 위치).

참조 타입 vs 기본 타입 — 포스트잇 vs 같은 방 열쇠 ·타입·시험 1순위·

[정의] 기본 타입(8종) = 값 자체를 저장(복사하면 독립). 참조 타입(그 외 전부) = 주소를 저장(복사하면 같은 객체 공유).

[표] 두 타입 분별

구분 기본 타입(8종) 참조 타입(그 외)
종류 byte·short·int·long·float·double·char·boolean 클래스·배열·String·Integer
저장 Stack에 값 자체 Stack에 주소, Heap에 실체
전달 값 복사(독립) 주소 복사(공유)
비유 포스트잇 복사(각자 독립) 같은 방 열쇠 복사(같은 객체)

[코드]

Java
int a = 10; int b = a; b = 99;   // 포스트잇 복사 — a는 그대로 10
Student s2 = s1;                  // 같은 방 열쇠 — s2 통해 바꾸면 s1도 바뀜

💡 b = a로 복사한 뒤 b를 99로 바꿔도 a는 10 그대로다(실행 확인). 배열도 참조 타입 — int[] arr은 Stack에 주소만, 실제 데이터는 Heap에. 포인터가 명시적으로 다루던 주소·역참조를 Java는 명시 없이 자동 처리한다.

🔑 암기 "기본 타입(8종) = 값 복사·독립 / 참조 타입 = 주소 복사·공유 · 배열도 참조 타입"

⚠️ 함정 참조 타입 대입은 객체 복제가 아니라 주소 공유 — 한쪽을 바꾸면 다른 쪽도 바뀐다.

🎯 빈출 기본 타입 8종·값 vs 주소 복사 분별.

final 3종 — 변수·메서드·클래스 ·final·

[정의] final = 잠금. 위치에 따라 잠그는 대상이 다르다 — 변수(재할당 잠금) · 메서드(오버라이딩 잠금) · 클래스(상속 잠금).

[표] final 3종

final 위치 의미
① 변수 재할당 잠금(상수화) final int MAX = 100;
② 메서드 오버라이딩 잠금 final void run() {}
③ 클래스 상속 잠금 final class String {}

💡 콘크리트 굳히기 — 변수에 부으면 값이 굳고, 메서드에 부으면 덮어쓰기가 굳고, 클래스에 부으면 상속이 굳는다. String이 final 클래스인 이유 = 보안 + 불변 최적화 + 멀티스레드 안전.

🔑 암기 "final = 변수(재할당 X) / 메서드(오버라이딩 X) / 클래스(상속 X·대표 String)"

⚠️ 함정 final int MAX = 100;MAX = 200;컴파일 오류(cannot assign a value to final variable). 단 final 변수는 생성자에서 1회 초기화 OK, final 메서드도 호출은 가능(오버라이딩만 차단), final 클래스도 인스턴스 생성 OK(상속만 차단). static final = 상수 패턴(가장 흔한 조합).

🎯 빈출 final 변수 재할당 오류·static final 상수.


PART E — 객체 비교와 핵심 타입

Wrapper와 Integer 캐시 -128~127 ·Wrapper·시험 1순위·

[정의] Wrapper = 기본 타입을 객체로 포장한 클래스(int→Integer, double→Double, char→Character, boolean→Boolean). int↔Integer 자동 변환을 박싱/언박싱이라 한다.

[코드]

Java
Integer a = 100, b = 100;
System.out.println(a == b);       // true  — Integer 캐시(-128~127), 같은 박스 재활용
Integer c = 200, d = 200;
System.out.println(c == d);       // false — 캐시 밖, 매번 새 객체
System.out.println(c.equals(d));  // true  — 값 비교

💡 JVM이 -128~127까지 256개의 Integer 박스를 미리 만들어 캐시한다. 이 범위 안이면 같은 박스를 재활용해서 ==도 true, 128부터는 매번 새 박스라 ==는 false. 위 결과(true/false/true)를 실행으로 확인했다 — 항상 equals로 비교하면 함정이 사라진다.

🔑 암기 "Integer 캐시 -128~127만 ==도 true · 그 밖은 false · 비교는 항상 equals"

⚠️ 함정 Integer 200 == 200은 false(캐시 밖). ==로 값이 같을 거라 단정하면 틀린다.

🎯 빈출 Integer 캐시 경계(-128~127)가 매년 1점.

String 불변 + 리터럴 풀 ·String·시험 1순위·

[정의] String은 불변(Immutable) — 한 번 만든 문자열은 못 바꾼다. 리터럴 "hello"String Pool에 한 번만 저장돼 공유되고, new String("hello")는 Heap에 별도 객체를 만든다.

[코드]

Java
String s1 = "hello", s2 = "hello";
System.out.println(s1 == s2);      // true  — 리터럴 풀, 같은 객체
String s3 = new String("hello");
System.out.println(s1 == s3);      // false — new는 Heap에 별도 객체
System.out.println(s1.equals(s3)); // true  — 값 비교

[표] String vs StringBuilder

항목 String StringBuilder
변경 불변(Immutable) 가변(Mutable)
+ 연산 매번 새 객체(비효율) append로 같은 객체에 추가
스레드 안전 O(불변이라 자동) X(StringBuffer는 O)

💡 String = 돌에 새긴 글자(불변), StringBuilder = 공책(가변). String으로 +를 1000번 하면 임시 객체 1000개가 생기니, 반복 추가는 StringBuilder가 압도적으로 빠르다. 위 비교 결과(true/false/true)는 실행으로 확인했다.

🔑 암기 "리터럴은 ==도 true / new String()은 == false · 둘 다 equals면 true · 반복 추가는 StringBuilder"

⚠️ 함정 new String("hello")는 같은 글자라도 ==가 false(Heap 별도 객체).

🎯 빈출 리터럴 vs new String 비교가 매 회차(Integer 캐시와 짝).

== vs equals — 주소 비교 vs 값 비교 ·비교·시험 1순위·

[정의] ==는 주소(참조) 비교, equals는 값 비교. 기본 타입은 ==가 값 비교지만, 참조 타입은 ==가 주소를 본다.

[표] == / equals 결과 (실행 확인)

비교 == equals
int 100, 100 true(기본 타입은 값)
Integer 100, 100 true(캐시) true
Integer 200, 200 false(캐시 밖) true
"hello", "hello"(리터럴) true(풀) true
"hello", new String("hello") false(Heap) true
사용자 객체 a, b false(다른 객체) 오버라이딩 안 했으면 false

💡 ==도 true가 되는 건 Integer 캐시(-128~127)와 String 리터럴 풀, 두 경우뿐. 나머지는 다 false. 그래서 객체 비교는 항상 equals를 우선하고, null 안전을 위해 리터럴을 앞에 둔다 — "hello".equals(s).

🔑 암기 "==는 주소 / equals는 값 · Integer 캐시 + String 리터럴 풀만 ==도 true"

⚠️ 함정 참조 타입을 ==로 내용 비교하면 대부분 false. 사용자 클래스는 equals를 오버라이딩해야 값 비교가 된다.

🎯 빈출 == vs equals가 매년 단골(Integer·String과 묶여 출제).

배열과 ArrayList — length 속성 vs size() 메서드 ·배열·

[정의] 배열 = 크기 고정 참조 타입. 길이는 arr.length(속성, 괄호 X). 크기 한계를 푸는 게 ArrayList(동적 확장), 길이는 list.size()(메서드, 괄호 O).

[코드]

Java
int[] arr = {10, 20, 30, 40, 50};   // Heap에 할당, 인덱스 0부터
arr[0] = 99;
int len = arr.length;               // 속성 — 괄호 없음, len=5

ArrayList<String> list = new ArrayList<>();
list.add("민지"); list.add("지훈");  // 끝에 추가
String first = list.get(0);          // 조회 — "민지"
int size = list.size();              // 메서드 — 괄호 있음, size=2

[표] 배열 vs ArrayList

항목 배열 ArrayList
크기 고정 동적(자동 확장)
크기 조회 arr.length(속성) list.size()(메서드)
타입 기본 타입 OK 참조 타입만(Wrapper 자동 박싱)

💡 arr.length는 괄호가 없는 속성, list.size()는 괄호가 있는 메서드 — 이 차이가 단골 함정이다. 위 코드는 arr.length=5, list.size()=2, list.get(0)="민지"를 실행으로 확인했다. 배열 비교 ==는 주소 비교라 내용 비교는 Arrays.equals()를 쓴다.

🔑 암기 "배열 = 고정 + arr.length(속성·괄호 X) / ArrayList = 동적 + list.size()(메서드·괄호 O) · 인덱스 0부터"

⚠️ 함정 arr.length()(배열에 괄호) ❌ · list.length ❌ — 배열은 속성, 리스트·String은 메서드.

🎯 빈출 length 속성 vs size() 메서드 분별.


기출 다지기

[기출 1 출제] Java 접근 제어자에 대한 설명으로 옳지 않은 것은? (옳지 않은 것 고르기)

  • ① public — 어떤 클래스에서든 접근 가능
  • ② protected — 같은 패키지 + 다른 패키지 자식에서 접근 가능
  • ③ default — 같은 패키지에서만 접근 가능
  • ④ private — 같은 클래스 + 같은 패키지에서 접근 가능
정답 및 해설 보기

정답: ④

private은 해당 클래스 안에서만 접근 가능하다. 같은 패키지여도 다른 클래스면 접근 불가다.

보기 판정 근거
③ default 옳음 같은 패키지까지만
④ private 정답(틀린 설명) '같은 패키지' 추가가 함정 — 같은 클래스만 O

★공보기사★ 매트릭스에서 private은 '같은 클래스' 열만 O이고 나머지 전부 X. ④는 '같은 패키지'를 넣어 범위를 넓혀놓은 함정이다.

🔑 암기 private에 '같은 패키지'가 붙으면 틀린 설명 — ★공보기사★ 범위 순서로 즉결.

[기출 2 출제] 다음 코드에서 컴파일 결과로 옳은 것은? (컴파일 성공/실패 판정)

Java
class B {
    public B(String s) { }     // 인자 생성자만 정의
}
// 호출부
B b = new B();                 // ?
  • ① 정상 컴파일된다
  • new B()에서 컴파일 오류가 난다
  • ③ 런타임에 예외가 발생한다
  • ④ 경고만 뜨고 실행된다
정답 및 해설 보기

정답: ②

기본 생성자는 생성자를 하나도 정의하지 않았을 때만 컴파일러가 자동으로 넣어준다. 인자 있는 생성자 B(String s)를 정의하는 순간 기본 생성자 자동 생성이 사라지므로, new B()(인자 없는 호출)는 컴파일 오류(constructor B cannot be applied to given types)다.

new B("hello")처럼 인자를 주거나, public B() {}를 따로 추가해야 한다.

🔑 암기 인자 생성자만 만들면 기본 생성자 자동 생성이 사라짐 — new 클래스() 컴파일 오류.

[기출 3 출제] 다음 중 컴파일 오류가 발생하는 줄은? (오류 줄 고르기)

Java
class Calc {
    private int x = 10;                                            // ⓐ
    public static int add(int a, int b) { return a + b; }          // ⓑ
    public static int add(int a, double b) { return (int)(a + b); } // ⓒ
    public static int multiply() { return this.x * 2; }           // ⓓ
}
  • ① ⓐ
  • ② ⓑ
  • ③ ⓒ
  • ④ ⓓ
정답 및 해설 보기

정답: ④

static 메서드에서는 this를 쓸 수 없다. static은 객체 없이 호출되니 this(현재 객체)가 존재하지 않는다. ⓓ의 this.x는 컴파일 오류(non-static variable this cannot be referenced from a static context)다.

보기 판정 근거
ⓑ·ⓒ 정상 매개변수가 (int,int)와 (int,double)로 달라 오버로딩 성립
④ ⓓ 정답(오류) static 메서드 안에서 this·인스턴스 필드 접근 불가

🔑 암기 static 메서드 안에 this·인스턴스 필드 직접 접근 보이면 컴파일 오류.

[기출 4 출제] 다음 코드의 출력 결과는? (코드 실행 결과 예측)

Java
Integer a = 100, b = 100;
Integer c = 200, d = 200;
System.out.println(a == b);
System.out.println(c == d);
System.out.println(a.equals(b));
System.out.println(c.equals(d));
  • ① true / true / true / true
  • ② true / false / true / true
  • ③ false / false / true / true
  • ④ true / true / false / false
정답 및 해설 보기

정답: ② true / false / true / true

비교 결과 근거
a == b (100) true Integer 캐시 -128~127, 같은 박스 재활용
c == d (200) false 캐시 밖, 매번 새 객체
equals(둘 다) true 값 비교

100은 캐시 범위 안이라 ==도 true, 200은 캐시 밖이라 새 객체라서 ==는 false. equals는 값을 보니 둘 다 true. 항상 equals를 쓰면 함정이 없다.

🔑 암기 Integer는 -128~127만 ==도 true. 그 밖은 false. 비교는 무조건 equals.

[기출 5 출제] 다음 코드의 출력 결과는? (코드 실행 결과 예측)

Java
String s1 = "hello", s2 = "hello";
String s3 = new String("hello");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1.equals(s3));
  • ① true / true / true
  • ② true / false / false
  • ③ true / false / true
  • ④ false / false / true
정답 및 해설 보기

정답: ③ true / false / true

비교 결과 근거
s1 == s2 true 리터럴 풀 같은 객체
s1 == s3 false new String은 Heap에 별도 객체
s1.equals(s3) true 값 비교

리터럴 "hello"는 풀에서 공유되니 ==도 true, new String("hello")는 Heap에 새 객체라 ==는 false. equals는 값을 보니 true. Integer 캐시 문제와 짝으로 자주 출제된다.

🔑 암기 리터럴은 ==도 true, new String()은 == false — 둘 다 equals면 true.

[기출 6 출제] 다음 중 == 비교 결과가 true인 것은? (옳은 것 고르기)

  • Integer x = 200, y = 200; 에서 x == y
  • String a = new String("hi"), b = new String("hi"); 에서 a == b
  • int p = 100, q = 100; 에서 p == q
  • String s = "hi";String t = new String("hi"); 에서 s == t
정답 및 해설 보기

정답: ③

==도 true가 되는 건 기본 타입의 값 비교, Integer 캐시(-128~127), String 리터럴 풀, 세 경우뿐이다.

보기 결과 근거
① Integer 200 false 캐시 밖, 새 객체
② new String 둘 false Heap 별도 객체 둘
③ int 100 true 기본 타입은 ==가 값 비교
④ 리터럴 vs new false new String은 Heap 별도

🔑 암기 ==가 true = 기본 타입 값 / Integer 캐시 / String 리터럴 풀. 나머지는 equals.

[기출 7 출제] Java의 메모리 영역과 저장 대상의 연결로 옳지 않은 것은? (옳지 않은 것 고르기)

  • ① Stack — 지역 변수와 참조 변수(주소)
  • ② Heap — new로 생성한 객체와 인스턴스 필드
  • ③ Method Area — 클래스 메타정보와 static 필드
  • ④ Heap — static 필드와 클래스 메타정보
정답 및 해설 보기

정답: ④

static 필드와 클래스 메타정보는 Method Area에 저장된다(Heap 아님). ④는 static을 Heap에 놓아 ③과 충돌시킨 함정이다.

영역 저장 대상
Stack 지역 변수·매개변수·참조 변수(주소)
Heap 객체(new)·인스턴스 필드·배열
Method Area 클래스 메타정보·static 필드

객체는 Heap, static은 Method Area, Java에는 free가 없고 GC가 회수한다 — 이 세 줄이 시험장 1점이다.

🔑 암기 객체=Heap / static=Method Area / 참조 변수=Stack · free 없이 GC 회수.

[기출 8 출제] 다음 코드에서 컴파일 오류가 나는 줄은? (오류 줄 고르기)

Java
final int MAX = 100;      // ⓐ
int total = MAX + 50;     // ⓑ
MAX = 200;                // ⓒ
System.out.println(MAX);  // ⓓ
  • ① ⓐ
  • ② ⓑ
  • ③ ⓒ
  • ④ ⓓ
정답 및 해설 보기

정답: ③

final 변수는 한 번 초기화하면 재할당이 잠긴다. ⓒ의 MAX = 200;은 컴파일 오류(cannot assign a value to final variable MAX)다.

판정 근거
정상 final 변수 선언 + 초기화
정상 final 값 읽기는 자유
정답(오류) final 변수 재할당 금지
정상 값 출력

final 변수는 읽기는 자유지만 다시 대입은 불가. static final로 쓰면 클래스 상수 패턴이 된다.

🔑 암기 final 변수는 재할당 금지(읽기는 자유) · static final = 상수.


한 장 요약

주제 암기·핵심 결정 카드
Java 정의 1995·고슬링·WORA Sun→Oracle · JVM 하이브리드 · 객체지향+자동 GC
main public static void main(String[] args) 토씨 고정 · 클래스명=파일명
클래스 vs 객체 붕어빵 틀 / 붕어빵 new = Heap에 객체 할당
클래스 구성 ★클필메생★ 클·필(상태)·메(행동)·생(클래스명 동일·반환타입 없음)
접근 제어자 ★공보기사★ 공>보>기>사 · default vs protected(자식) 매트릭스
캡슐화 private + getter/setter 검증 1줄 · OOP 4대 중 하나(42강)
생성자 오버로딩 인자 생성자만 만들면 기본 생성자 사라짐
this 현재 객체 this.필드 / this()(첫 줄) / return this · super와 동시 불가
static 칠판(공유) Method Area · 클래스명 호출 · this 사용 불가
메모리 Stack/Heap/Method Area 객체=Heap · static=Method Area · free 없음(GC)
타입 기본 8종 vs 참조 값 복사(독립) vs 주소 복사(공유) · 배열도 참조
final 변수·메서드·클래스 재할당 X / 오버라이딩 X / 상속 X(String)
Wrapper Integer 캐시 -128~127==도 true
String 불변 + 리터럴 풀 리터럴 == true / new String == false
== / equals 주소 / 값 기본 타입·Integer 캐시·String 리터럴만 == true
배열 / ArrayList length / size() 속성(괄호 X) / 메서드(괄호 O) · 인덱스 0부터
함정 (매년 2~3쌍 출제) 정답
default vs protected default=같은 패키지 / protected=+다른 패키지 자식
private '같은 패키지' 틀린 설명 — 같은 클래스만
인자 생성자만 정의 기본 생성자 사라짐(new 클래스() 오류)
static에서 this 컴파일 오류
Integer 200 == 200 false(캐시 밖)
"hi" == new String("hi") false(Heap 별도)
final 변수 재할당 컴파일 오류
arr.length() / list.length 배열=속성·리스트=메서드

🎯 합격 한 끗: 41강은 ★공보기사★(접근 제어 4×4 매트릭스) · ★클필메생★(클래스 4대 구성) 두 묶음이 기둥이다. 여기에 Integer 캐시 -128~127 · String 리터럴 풀 · ==는 주소·equals는 값 세 줄을 더하면 4과목 Java 빈출의 절반을 가져온다. 깊이 파기보다 추적 한 글자가 정답을 가르는 영역 — private에 '같은 패키지'가 붙으면 틀린 설명이고, 인자 생성자만 만들면 기본 생성자가 사라지며, static에서 this는 컴파일 오류, Integer는 캐시 안(-128~127)만 ==도 true다. 39·40강의 C(절차형·포인터·수동 메모리)가 여기서 Java(객체지향·참조·자동 GC)로 갈아탔다. 캡슐화는 OOP 4대 특성의 하나로 맛만 봤고, 상속·다형성·추상 클래스/인터페이스는 42강에서 ★캡상다추★로 본격적으로 묶인다.

전체 목록 필기 이론

합격까지

정처기, 혼자 막막하다면

초개인화 학습앱 Klue와 에듀윌 온라인강의로 합격까지 이어가세요.