자바 입문 문법을 배우고 나면 다음으로 만나는 개념이 클래스와 객체입니다.
처음에는 class, new, . 같은 문법이 한꺼번에 나와서 복잡하게 느껴질 수 있습니다.
하지만 출발점은 단순합니다. 클래스는 서로 관련 있는 데이터를 하나로 묶기 위한 설계도입니다. 객체는 그 설계도를 바탕으로 실제로 만들어진 데이터 묶음입니다.
이 글에서는 상품 정보를 예제로 클래스가 왜 필요한지부터 차근차근 정리합니다. 배열 개념이 아직 익숙하지 않다면 자바 배열 정리 - 선언부터 2차원 배열까지를 먼저 보면 더 편합니다.
클래스가 필요한 이유
상품 두 개의 이름, 가격, 재고를 출력한다고 생각해보겠습니다. 클래스를 사용하지 않으면 아래처럼 변수 이름을 계속 늘려야 합니다.
public class ProductStart {
public static void main(String[] args) {
String product1Name = "키보드";
int product1Price = 45000;
int product1Stock = 8;
String product2Name = "마우스";
int product2Price = 22000;
int product2Stock = 15;
System.out.println("상품명: " + product1Name + ", 가격: " + product1Price + ", 재고: " + product1Stock);
System.out.println("상품명: " + product2Name + ", 가격: " + product2Price + ", 재고: " + product2Stock);
}
}
이 코드는 동작합니다. 하지만 상품이 늘어날수록 변수 이름도 계속 늘어납니다.
상품 하나는 이름, 가격, 재고가 서로 묶여 있어야 자연스럽습니다. 그런데 위 코드에서는 세 값이 따로 흩어져 있습니다.
product1Name
product1Price
product1Stock
product2Name
product2Price
product2Stock
데이터가 흩어져 있으면 읽기도 어렵고, 실수하기도 쉽습니다. 이럴 때 클래스를 사용하면 관련 있는 값을 하나의 단위로 묶을 수 있습니다.
클래스는 데이터 묶음의 설계도입니다
상품 하나가 가져야 할 값을 먼저 생각해보겠습니다.
- 상품명
- 가격
- 재고
이 구조를 자바 코드로 표현하면 클래스가 됩니다.
public class Product {
String name;
int price;
int stock;
}
Product 클래스는 상품 하나가 어떤 데이터를 가져야 하는지 정합니다.
여기서 name, price, stock은 클래스 안에 선언된 변수입니다.
이런 변수를 보통 필드 또는 멤버 변수라고 부릅니다.
| 이름 | 의미 |
|---|---|
| 클래스 | 객체를 만들기 위한 설계도 |
| 필드 | 객체가 가지는 데이터 |
| 멤버 변수 | 필드를 부르는 다른 표현 |
클래스를 만들었다고 바로 상품 데이터가 생기는 것은 아닙니다. 클래스는 어디까지나 설계도입니다. 실제 데이터를 만들려면 객체를 생성해야 합니다.
객체는 클래스로 만든 실제 데이터입니다
Product 클래스를 바탕으로 실제 상품 객체를 만들어보겠습니다.
Product keyboard = new Product();
이 코드는 Product 설계도를 바탕으로 상품 객체 하나를 만듭니다.
그리고 그 객체를 keyboard라는 변수로 가리킵니다.
객체를 만든 뒤에는 .을 사용해서 필드에 값을 넣을 수 있습니다.
keyboard.name = "키보드";
keyboard.price = 45000;
keyboard.stock = 8;
전체 코드는 아래처럼 작성할 수 있습니다.
public class Product {
String name;
int price;
int stock;
}
public class ProductMain {
public static void main(String[] args) {
Product keyboard = new Product();
keyboard.name = "키보드";
keyboard.price = 45000;
keyboard.stock = 8;
Product mouse = new Product();
mouse.name = "마우스";
mouse.price = 22000;
mouse.stock = 15;
System.out.println("상품명: " + keyboard.name + ", 가격: " + keyboard.price + ", 재고: " + keyboard.stock);
System.out.println("상품명: " + mouse.name + ", 가격: " + mouse.price + ", 재고: " + mouse.stock);
}
}
실행 결과는 다음과 같습니다.
상품명: 키보드, 가격: 45000, 재고: 8
상품명: 마우스, 가격: 22000, 재고: 15
변수 이름이 늘어나는 방식보다 구조가 훨씬 분명해졌습니다.
상품 하나를 표현하는 데이터가 Product 객체 안에 함께 들어 있기 때문입니다.
new Product()는 무엇을 하는 코드일까
처음에는 아래 코드가 가장 낯설 수 있습니다.
Product keyboard = new Product();
이 코드는 한 번에 세 가지를 합니다.
new Product()로Product객체를 새로 만듭니다.- 만들어진 객체의 위치를
keyboard변수에 저장합니다. - 이후
keyboard.name처럼 객체 안의 필드에 접근할 수 있게 됩니다.
여기서 중요한 점은 keyboard 변수 안에 상품 데이터 전체가 직접 들어가는 것이 아니라는 점입니다.
keyboard는 객체를 가리키는 참조값을 가지고 있습니다.
입문 단계에서는 이렇게 이해하면 충분합니다.
keyboard 변수
↓
Product 객체
name = "키보드"
price = 45000
stock = 8
아래 그림처럼 Product 클래스는 어떤 칸이 필요한지 정해두는 설계도입니다.
new Product()를 실행하면 실제 객체가 만들어지고, keyboard 변수는 그 객체를 가리킵니다.
Class And Object Flow
클래스는 설계도, 객체는 실제 데이터입니다
객체를 가리키는 이름표입니다.
Product keyboard = new Product();→keyboard.name즉 keyboard는 상품 객체로 가는 이름표입니다.
keyboard.name은 keyboard가 가리키는 객체 안의 name 필드를 읽는다는 뜻입니다.
클래스, 객체, 인스턴스 차이
클래스와 객체를 공부하다 보면 인스턴스라는 말도 같이 나옵니다. 처음에는 객체와 인스턴스를 거의 같은 의미로 이해해도 괜찮습니다.
다만 문맥에 따라 초점이 조금 다릅니다.
| 용어 | 의미 | 예시 |
|---|---|---|
| 클래스 | 객체를 만들기 위한 설계도 | Product |
| 객체 | 클래스로 만든 실제 데이터 | keyboard가 가리키는 상품 |
| 인스턴스 | 특정 클래스로부터 만들어진 객체 | keyboard는 Product의 인스턴스 |
예를 들어 아래 코드가 있다고 해보겠습니다.
Product keyboard = new Product();
Product mouse = new Product();
Product는 클래스입니다.
keyboard와 mouse가 가리키는 실제 데이터는 객체입니다.
그리고 두 객체는 모두 Product 클래스로부터 만들어진 인스턴스입니다.
객체를 배열에 담기
상품이 여러 개라면 객체도 여러 개 만들어야 합니다. 이때 객체를 배열에 담으면 반복문으로 처리하기 쉬워집니다.
Product[] products = new Product[2];
products[0] = keyboard;
products[1] = mouse;
전체 예시는 다음과 같습니다.
public class ProductArrayMain {
public static void main(String[] args) {
Product keyboard = new Product();
keyboard.name = "키보드";
keyboard.price = 45000;
keyboard.stock = 8;
Product mouse = new Product();
mouse.name = "마우스";
mouse.price = 22000;
mouse.stock = 15;
Product[] products = new Product[2];
products[0] = keyboard;
products[1] = mouse;
for (int i = 0; i < products.length; i++) {
Product product = products[i];
System.out.println("상품명: " + product.name + ", 가격: " + product.price + ", 재고: " + product.stock);
}
}
}
products 배열에는 Product 객체 자체가 순서대로 들어 있다고 생각하면 됩니다.
정확히는 객체를 가리키는 참조값이 들어 있습니다.
입문 단계에서는 아래 흐름을 기억하면 충분합니다.
Product[] products
[0] → keyboard 객체
[1] → mouse 객체
그래서 반복문에서 products[i]를 꺼내면 상품 객체 하나를 다룰 수 있습니다.
선언과 생성을 헷갈리지 않기
클래스를 배울 때 자주 헷갈리는 부분이 있습니다. 변수를 선언하는 것과 객체를 생성하는 것은 다릅니다.
Product keyboard;
이 코드는 Product 객체를 가리킬 수 있는 변수만 만든 것입니다.
아직 실제 상품 객체는 없습니다.
객체는 아래 코드에서 만들어집니다.
keyboard = new Product();
선언만 하고 객체를 만들지 않은 상태에서 필드에 접근하면 문제가 생깁니다.
Product keyboard;
keyboard.name = "키보드"; // 잘못된 코드
keyboard가 아직 어떤 객체도 가리키지 않기 때문입니다.
먼저 new Product()로 객체를 만든 뒤 필드에 접근해야 합니다.
Product keyboard = new Product();
keyboard.name = "키보드";
실수하기 쉬운 부분
클래스 이름과 변수 이름을 구분하기
Product keyboard = new Product();
여기서 앞의 Product는 타입입니다.
keyboard는 변수 이름입니다.
뒤의 new Product()는 객체 생성입니다.
처음에는 모두 비슷해 보이지만 역할이 다릅니다.
객체마다 필드 값은 따로 가진다
Product keyboard = new Product();
keyboard.name = "키보드";
Product mouse = new Product();
mouse.name = "마우스";
keyboard와 mouse는 서로 다른 객체입니다.
그래서 keyboard.name을 바꾼다고 mouse.name이 함께 바뀌지 않습니다.
배열만 만들면 객체가 자동으로 생기지 않는다
Product[] products = new Product[2];
products[0].name = "키보드"; // 잘못된 코드
이 코드는 배열만 만든 상태입니다.
배열 안에 들어갈 Product 객체는 아직 만들어지지 않았습니다.
아래처럼 각 칸에 객체를 넣어야 합니다.
Product[] products = new Product[2];
products[0] = new Product();
products[0].name = "키보드";
정리
클래스는 관련 있는 데이터를 하나로 묶기 위한 설계도입니다. 객체는 그 설계도로 실제 만들어진 데이터입니다.
new Product()는 Product 객체를 새로 만드는 코드입니다.
만든 객체는 변수에 저장해서 사용합니다.
keyboard.name처럼 .을 사용하면 객체 안의 필드에 접근할 수 있습니다.
객체가 여러 개라면 배열에 담아서 반복문으로 처리할 수 있습니다.
처음에는 아래 세 문장만 기억해도 좋습니다.
클래스는 설계도입니다.
객체는 설계도로 만든 실제 데이터입니다.
변수는 객체를 가리키는 이름표입니다.
클래스와 객체를 이해하면 자바 코드가 단순한 명령어 모음이 아니라, 데이터를 의미 있는 단위로 나누어 다루는 구조로 보이기 시작합니다.