CodeGym /행동 /JAVA 25 SELF /클래스와 객체 선언 시 발생하는 오류

클래스와 객체 선언 시 발생하는 오류

JAVA 25 SELF
레벨 23 , 레슨 0
사용 가능

1. 클래스 선언 시 오류

접근 제한자를 생략함 (package-private가 기본)

Java에서 클래스에 접근 제한자를 명시하지 않으면 현재 패키지 내부에서만 접근할 수 있습니다. 이를 package-private 또는 '기본 접근'이라고 합니다. 예:

// 파일 Book.java
class Book {
    String title;
}

이런 클래스는 다른 패키지에서 사용할 수 없습니다. 클래스가 어디서든 접근 가능하도록 하려면(대부분의 핵심 모델은 그렇습니다) public 제한자를 사용하세요:

public class Book {
    String title;
}

왜 중요할까요?
public을 빼먹으면, 나중에 다른 패키지의 Library가 왜 당신의 클래스를 보지 못하는지 한참 헤매게 됩니다.

클래스 이름과 파일 이름 불일치

Java에서는 클래스가 들어 있는 파일 이름이 해당 파일의 public 클래스 이름과 동일해야 합니다(대소문자 구분!). 예:

// 파일 Book.java
public class Book {
    // ...
}

파일을 book.java(소문자)나, 더 나쁘게는 BooK.java로 저장하면 컴파일 오류가 발생합니다. 이는 IDE가 클래스를 이름만 바꾸고 파일 이름을 바꾸지 않았을 때 강하게 경고하는 이유 중 하나입니다.

선언 구문 오류: 중괄호 누락, 메서드와 필드의 잘못된 위치

Java는 엄격한 언어입니다. 어딘가에서 중괄호를 빼먹거나 실수로 메서드 안에 다른 메서드를 선언하면(이건 허용되지 않습니다!) 컴파일러가 즉시 오류를 알려줍니다.

잘못된 선언 예:

public class User
    String name; // 앗! 클래스의 중괄호가 빠졌습니다.

    public void printName() {
        System.out.println(name);
    }
}

올바른 예:

public class User {
    String name;

    public void printName() {
        System.out.println(name);
    }
}

기억하세요:

  • 모든 필드와 메서드는 클래스의 중괄호 안에서만 선언합니다.
  • 메서드는 서로 중첩될 수 없습니다(다른 언어에서는 허용되기도 하지만 Java에서는 안 됩니다!).

2. 객체 생성 시 오류

초기화 전에 객체를 사용하려는 시도 (NullPointerException)

가장 흔한 오류는 아직 생성되지 않은 객체에 접근하는 것입니다. Java에서 참조형 변수의 기본값은 null입니다.

예:

User user;
System.out.println(user.name); // NullPointerException!

왜 그럴까요?
변수 user는 선언만 되었고 초기화되지 않았습니다. 필드나 메서드에 접근하려 하면 NPE(NullPointerException)가 발생합니다.

올바른 방식:

User user = new User();
System.out.println(user.name); // 이제 괜찮습니다(필드가 null이 아니라면)

생성자 호출 오류(매개변수 불일치, 기본 생성자 없음)

클래스에 매개변수가 있는 생성자만 있는 경우, 매개변수 없이 객체를 생성하려고 하면 컴파일 오류가 납니다.

public class Book {
    String title;

    public Book(String title) {
        this.title = title;
    }
}

Book book = new Book(); // 오류! 매개변수 없는 생성자가 없습니다.

해결: 매개변수 없는 생성자를 추가하거나, 늘 필요한 값을 전달하세요:

Book book = new Book("자바 입문서");

재사용 대신 객체를 여러 번 생성함

가끔 초보자는 이미 만든 객체를 재사용하지 않고, 접근할 때마다 새로 생성하곤 합니다.

Book book = new Book("자바 입문서");
System.out.println(book.title);

book = new Book("자바 입문서"); // 왜 또 생성하나요? 이미 같은 객체가 있었습니다!
System.out.println(book.title);

이것은 컴파일 오류는 아니지만, 안 좋은 스타일의 신호입니다 — 기존 객체에 대한 참조를 잃고 불필요한 메모리를 사용하게 됩니다.

3. 베스트 프랙티스: 같은 실수를 피하는 법

항상 접근 제한자를 명시하세요

public, private, protected를 아끼지 말고 적어주세요 — 보안뿐 아니라 코드 가독성에 중요합니다. IDE가 물론 힌트를 주지만, 처음부터 습관을 들이는 편이 좋습니다.

예:

public class User {
    private String name;
    // ...
}

클래스 명명 규칙을 지키세요

  • 클래스 이름은 대문자로 시작하고 CamelCase를 사용합니다: Book, LibraryUser, BookManager.
  • 파일 이름은 클래스 이름과 정확히 같아야 합니다.

필수 필드 초기화에는 생성자를 사용하세요

객체에 생성 시 반드시 채워야 하는 필드가 있다면, 매개변수가 있는 생성자를 추가하세요. 사용 단계에서의 오류를 방지할 수 있습니다.

예:

public class User {
    private String name;

    public User(String name) {
        this.name = name;
    }
}

이제 이름 없이 User를 생성할 수 없습니다 — 컴파일러가 허용하지 않습니다.

4. 지식 적용: 미니‑애플리케이션 "라이브러리" 만들기

우리의 학습용 애플리케이션을 계속 확장해 봅시다. Book 클래스와 책들을 관리하는 Library 클래스가 있다고 가정합시다.

올바른 클래스 선언 예

// 파일 Book.java
public class Book {
    private String title;
    private String author;

    // 매개변수가 있는 생성자
    public Book(String title, String author) {
        this.title = title;
        this.author = author;
    }

    // 게터
    public String getTitle() {
        return title;
    }

    public String getAuthor() {
        return author;
    }
}

올바른 객체 생성 예

Book book = new Book("자바 입문서", "John Doe");
System.out.println(book.getTitle() + " - " + book.getAuthor());

매니저 클래스 예

// 파일 Library.java
import java.util.ArrayList;

public class Library {
    private ArrayList<Book> books = new ArrayList<>();

    public void addBook(Book book) {
        books.add(book);
    }

    public void printAllBooks() {
        for (Book book : books) {
            System.out.println(book.getTitle() + " - " + book.getAuthor());
        }
    }
}

main에서의 사용

public class Main {
    public static void main(String[] args) {
        Library library = new Library();
        Book book1 = new Book("자바 입문서", "John Doe");
        Book book2 = new Book("쉽게 배우는 OOP", "Ivan Ivanov");

        library.addBook(book1);
        library.addBook(book2);

        library.printAllBooks();
    }
}

5. 그림과 도식

도식: 무엇을 어디에 선언하나요?

+-----------------------------+
|         Book.java           |
|-----------------------------|
| public class Book {         |
|     private String title;   |  <--- 필드(클래스 내부에서만)
|     ...                     |
|     public Book(...) {...}  |  <--- 생성자(클래스 내부)
|     public String getTitle()|  <--- 메서드(클래스 내부)
| }                           |
+-----------------------------+

+-----------------------------+
|        Main.java            |
|-----------------------------|
| public class Main {         |
|     public static void main |
|         // 객체 생성         |
|         Book book = new Book|
| }                           |
+-----------------------------+

6. 흔한 오류 살펴보기

오류 1: 클래스 이름과 파일 이름 불일치

// 파일: Libraryuser.java
public class LibraryUser { // 클래스 이름은 대문자 U, 파일은 소문자!
    // ...
}

class LibraryUser is public, should be declared in a file named LibraryUser.java

오류 2: 초기화되지 않은 객체 사용 시도

Book book;
System.out.println(book.getTitle()); // NullPointerException!

오류 3: 중괄호를 잊음

public class Book
    private String title; // 캡슐화를 위해 필드는 보통 private로 만듭니다
    // ...
}

';' expected

오류 4: 메서드 안에 메서드 선언

public class User {
    public void printName() {
        void sayHello() {
            System.out.println("Hello!"); // 메서드 안에 메서드를 선언할 수 없습니다!
        }
    }
}

illegal start of type

1
과제
JAVA 25 SELF, 레벨 23, 레슨 0
잠금
학생 데이터베이스 설계 📚
학생 데이터베이스 설계 📚
1
과제
JAVA 25 SELF, 레벨 23, 레슨 0
잠금
도서관 카탈로그의 "빈" 책의 위험성 👻
도서관 카탈로그의 "빈" 책의 위험성 👻
1
과제
JAVA 25 SELF, 레벨 23, 레슨 0
잠금
메서드 안의 메서드: 아키텍처적 금지 🏗️
메서드 안의 메서드: 아키텍처적 금지 🏗️
1
과제
JAVA 25 SELF, 레벨 23, 레슨 0
잠금
새 상품의 필수 명명 🏷️
새 상품의 필수 명명 🏷️
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION