06. 클래스와 객체
Java 는 객체지향(OOP) 언어입니다. 데이터를 **클래스(class)** 로 정의하고, 그 청사진에서 **객체(object, 인스턴스)** 를 찍어 사용합니다. 이 단원에서는 클래스를 정의하고, 객체를 만들어 필드와 메서드를 다루는 가장 기본적인 흐름을 봅니다.
이 강의에서 배우는 것
- 1`class` 키워드로 클래스를 정의한다
- 2필드·메서드·생성자의 역할을 구분한다
- 3`this` 가 가리키는 것이 무엇인지 안다
- 4접근 제한자(`public` / `private`) 의 효과를 간단히 본다
소개
Java 는 객체지향(OOP) 언어입니다. 데이터를 **클래스(class)** 로 정의하고, 그 청사진에서 **객체(object, 인스턴스)** 를 찍어 사용합니다. 이 단원에서는 클래스를 정의하고, 객체를 만들어 필드와 메서드를 다루는 가장 기본적인 흐름을 봅니다.
핵심 개념
1) 클래스 정의
public class Person {
String name;
int age;
void hello() {
System.out.println("Hi, I'm " + name);
}
}클래스는 **상태(필드)** 와 **행동(메서드)** 의 묶음입니다.
2) 객체 생성
Person p = new Person();
p.name = "지수";
p.age = 21;
p.hello();`new` 가 객체를 메모리에 만들고, 그 참조를 변수 `p` 에 저장합니다.
3) 생성자
public class Person {
String name;
int age;
Person(String name, int age) { // 생성자
this.name = name;
this.age = age;
}
}생성자는 **반환형이 없는** 특별한 메서드입니다. 객체를 만들면서 초기값을 받습니다. 별도 정의 안 하면 컴파일러가 매개변수 없는 **기본 생성자** 를 자동 추가합니다.
4) `this` 키워드
`this` 는 **현재 객체 자신** 을 가리킵니다. 매개변수와 필드 이름이 같을 때 명확하게 구분하는 용도로 자주 씁니다.
this.name = name; // 왼쪽=필드, 오른쪽=매개변수핵심 예제
예제 1 — `Person.java` : 클래스 정의와 객체 생성
public class Person {
String name;
int age;
void hello() {
System.out.println("Hi, I'm " + name + " (" + age + ")");
}
public static void main(String[] args) {
Person p = new Person();
p.name = "지수";
p.age = 21;
p.hello();
}
}**실행 결과**
Hi, I'm 지수 (21)**메모:** 필드를 따로 초기화하지 않으면 기본값(0, null, false) 이 자동 부여됩니다.
예제 2 — `PersonWithCtor.java` : 생성자와 `this`
public class PersonWithCtor {
String name;
int age;
PersonWithCtor(String name, int age) {
this.name = name;
this.age = age;
}
public static void main(String[] args) {
PersonWithCtor a = new PersonWithCtor("지수", 21);
PersonWithCtor b = new PersonWithCtor("민수", 25);
System.out.println(a.name + ", " + a.age);
System.out.println(b.name + ", " + b.age);
}
}**실행 결과**
지수, 21
민수, 25**메모:** 생성자는 `new` 와 함께만 호출됩니다.
예제 3 — `Counter.java` : 객체별 상태
public class Counter {
int count;
void increment() {
count++;
}
public static void main(String[] args) {
Counter c1 = new Counter();
Counter c2 = new Counter();
c1.increment();
c1.increment();
c2.increment();
System.out.println("c1=" + c1.count + ", c2=" + c2.count);
}
}**실행 결과**
c1=2, c2=1**메모:** 인스턴스가 다르면 필드도 **각자 따로** 관리됩니다.
예제 4 — `Rectangle.java` : 메서드로 동작 추가
public class Rectangle {
int width;
int height;
Rectangle(int w, int h) {
this.width = w;
this.height = h;
}
int area() {
return width * height;
}
int perimeter() {
return 2 * (width + height);
}
public static void main(String[] args) {
Rectangle r = new Rectangle(3, 4);
System.out.println("면적=" + r.area());
System.out.println("둘레=" + r.perimeter());
}
}**실행 결과**
면적=12
둘레=14**메모:** "데이터 + 그 데이터를 다루는 메서드" 를 한 클래스로 묶는 것이 OOP 의 첫 단계입니다.
전체 예제 코드 (src/)
src/Counter.java
public class Counter {
int count;
void increment() {
count++;
}
public static void main(String[] args) {
Counter c1 = new Counter();
Counter c2 = new Counter();
c1.increment();
c1.increment();
c2.increment();
System.out.println("c1=" + c1.count + ", c2=" + c2.count);
}
}
src/Person.java
public class Person {
String name;
int age;
void hello() {
System.out.println("Hi, I'm " + name + " (" + age + ")");
}
public static void main(String[] args) {
Person p = new Person();
p.name = "지수";
p.age = 21;
p.hello();
}
}
src/PersonWithCtor.java
public class PersonWithCtor {
String name;
int age;
PersonWithCtor(String name, int age) {
this.name = name;
this.age = age;
}
public static void main(String[] args) {
PersonWithCtor a = new PersonWithCtor("지수", 21);
PersonWithCtor b = new PersonWithCtor("민수", 25);
System.out.println(a.name + ", " + a.age);
System.out.println(b.name + ", " + b.age);
}
}
src/Rectangle.java
public class Rectangle {
int width;
int height;
Rectangle(int w, int h) {
this.width = w;
this.height = h;
}
int area() {
return width * height;
}
int perimeter() {
return 2 * (width + height);
}
public static void main(String[] args) {
Rectangle r = new Rectangle(3, 4);
System.out.println("면적=" + r.area());
System.out.println("둘레=" + r.perimeter());
}
}
자주 하는 실수
- 객체를 만들지 않고 `Person.hello()` 처럼 호출 (인스턴스 메서드는 객체가 있어야)
- 필드명과 매개변수 충돌인데 `this.` 빠뜨림 → 자기 할당
- 생성자 이름을 잘못 쓰면 메서드로 간주됨 (반환형 없음 + 클래스명 동일이어야)
- `new` 없이 변수만 선언하고 사용 → `NullPointerException`
- 객체 참조 변수 비교에 `==` 사용 (객체는 일반적으로 `.equals()`)
정리
- 클래스는 **상태 + 행동** 의 청사진
- 객체는 클래스로부터 `new` 로 찍어낸 인스턴스
- 생성자는 객체 초기화 전용 메서드
- `this` 는 현재 객체 자신
과제
# 과제 - 06. 클래스와 객체
## 문제 1 — `Book` 클래스
- 파일명: `Homework01.java`
- 핵심 개념: 클래스, 생성자, 메서드
요구사항
- 클래스 `Book` 을 `Homework01` 내부 또는 같은 파일에 만들고 `title`, `author`, `pages` 필드를 가집니다.
- 생성자에서 세 값을 받아 초기화합니다.
- `info()` 메서드는 `[제목] 저자(쪽수쪽)` 형식의 문자열을 반환합니다.
- main 에서 책 2 권을 만들고 `info()` 결과를 출력합니다.
예상 출력
[Effective Java] Joshua Bloch(384쪽)
[Clean Code] Robert C. Martin(464쪽)## 문제 2 — `Circle` 면적
- 파일명: `Homework02.java`
- 핵심 개념: 인스턴스 메서드, `Math.PI`
요구사항
- 클래스 `Circle` 에 `double radius` 필드와 생성자, `area()` 메서드를 정의합니다.
- 반지름 1, 2.5, 3 인 원의 면적을 소수 셋째 자리까지 출력합니다.
예상 출력
r=1.000 area=3.142
r=2.500 area=19.635
r=3.000 area=28.274## 정답 확인 직접 풀어 본 후 [`answer/`](./answer/) 폴더의 정답과 비교해 보세요.
정답 코드 (homework/answer/)
answer/Homework01.java
/** Book 클래스를 정의하고 info() 출력. */
public class Homework01 {
public static void main(String[] args) {
Book a = new Book("Effective Java", "Joshua Bloch", 384);
Book b = new Book("Clean Code", "Robert C. Martin", 464);
System.out.println(a.info());
System.out.println(b.info());
}
}
class Book {
String title;
String author;
int pages;
Book(String title, String author, int pages) {
this.title = title;
this.author = author;
this.pages = pages;
}
String info() {
return "[" + title + "] " + author + "(" + pages + "쪽)";
}
}
answer/Homework02.java
/** Circle 면적 계산. */
public class Homework02 {
public static void main(String[] args) {
double[] radii = {1.0, 2.5, 3.0};
for (double r : radii) {
Circle c = new Circle(r);
System.out.printf("r=%.3f area=%.3f%n", r, c.area());
}
}
}
class Circle {
double radius;
Circle(double radius) {
this.radius = radius;
}
double area() {
return Math.PI * radius * radius;
}
}
직접 해 보기
cd 02_객체지향/06_클래스와_객체/src
javac Rectangle.java
java Rectangle다음 단원
[07_캡슐화](../07_캡슐화/) — `private` 필드, getter/setter, `record` 입문을 배웁니다.