클래스와 객체의 개념 및 정의
클래스(Class)는 현실 세계의 사물이나 개념을 프로그래밍적으로 추상화한 설계도입니다. 클래스는 크게 두 가지 요소로 구성됩니다.
- 속성(Attribute): 사물의 특징을 나타내는 데이터 (예: 전자기기의 제조사, 가격)
- 행동(Behavior): 사물이 수행할 수 있는 기능 (예: 전화 걸기, 메시지 전송)
객체(Object)는 클래스라는 설계도를 바탕으로 메모리에 실제 생성된 실체입니다.
클래스 구현
클래스 내부에서는 속성을 멤버 변수로, 행동을 멤버 메서드로 정의합니다. 메서드를 정의할 때는 static 키워드를 생략하여 인스턴스 메서드로 선언합니다.
public class SmartDevice {
// 멤버 변수 (속성)
String manufacturer;
double cost;
// 멤버 메서드 (행동)
public void makeCall() {
System.out.println("전화를 겁니다.");
}
public void sendText() {
System.out.println("문자 메시지를 전송합니다.");
}
}
객체의 생성 및 활용
객체는 new 키워드를 사용하여 인스턴스화하며, 도트(.) 연산자를 통해 내부 멤버에 접근합니다.
public class DeviceTest {
public static void main(String[] args) {
// 객체 생성
SmartDevice myDevice = new SmartDevice();
// 멤버 변수 접근 및 초기화
myDevice.manufacturer = "Samsung";
myDevice.cost = 1200.0;
// 멤버 변수 출력
System.out.println("제조사: " + myDevice.manufacturer);
System.out.println("가격: " + myDevice.cost);
// 멤버 메서드 호출
myDevice.makeCall();
myDevice.sendText();
// 추가 객체 생성
SmartDevice anotherDevice = new SmartDevice();
anotherDevice.manufacturer = "Apple";
anotherDevice.cost = 1500.0;
}
}
개발 시에는 데이터를 관리하는 비즈니스 클래스(JavaBean)와 실행 진입점인 main 메서드를 포함하는 테스트 클래스를 분리하는 것이 좋습니다. 비즈니스 클래스는 특정 도메인의 상태와 행위만을 담당하고, 테스트 클래스는 객체 생성 및 시나리오 검증에 집중하여 관심사를 분리(Separation of Concerns)합니다.
캡슐화와 접근 제어
캡슐화는 객체의 내부 데이터를 외부로부터 숨기고, 오직 정의된 메서드를 통해서만 데이터에 접근하도록 하는 객체 지향의 핵심 원리입니다. 이를 통해 데이터의 무결성을 보장하고 외부 의존성을 낮출 수 있습니다.
private 키워드와 Getters/Setters
멤버 변수에 private 접근 제어자를 적용하면 해당 변수는 클래스 내부에서만 접근 가능합니다. 외부에서 데이터를 읽거나 수정하려면 public으로 선언된 get 및 set 메서드를 제공해야 합니다.
public class Employee {
private String workerName;
private int workerAge;
// Setter: 유효성 검사를 통한 데이터 보호
public void setWorkerAge(int age) {
if (age < 18 || age > 65) {
System.out.println("유효하지 않은 근무 연령입니다.");
} else {
this.workerAge = age;
}
}
// Getter: 데이터 조회
public int getWorkerAge() {
return this.workerAge;
}
public void displayProfile() {
System.out.println("이름: " + workerName + ", 나이: " + workerAge);
}
}
public class EmployeeTest {
public static void main(String[] args) {
Employee emp = new Employee();
emp.workerName = "Alice";
emp.setWorkerAge(28); // private 필드는 setter를 통해 접근
emp.displayProfile();
}
}
this 키워드의 활용
this는 현재 메서드를 호출한 객체自身の 참조 주소를 나타냅니다. 주로 메서드의 매개변수와 멤버 변수의 이름이 동일할 때, 멤버 변수임을 명시하기 위해 사용됩니다.
public class BankAccount {
private double accountBalance;
public void deposit(double accountBalance) {
// 매개변수와 멤버 변수의 이름이 동일하므로 this로 구분
this.accountBalance += accountBalance;
System.out.println("현재 잔액: " + this.accountBalance);
}
}
생성자(Constructor)
생성자는 객체가 생성되는 시점에 JVM에 의해 자동으로 호출되며, 멤버 변수의 초기화를 담당합니다.
- 클래스명과 동일한 이름을 가지며 반환 타입이 없습니다.
- 기본 생성자: 매개변수가 없으며, 개발자가 명시하지 않을 경우 컴파일러가 자동으로 추가합니다.
- 매개변수 생성자: 객체 생성 시 외부에서 전달받은 값으로 필드를 초기화합니다.
- 매개변수 생성자를 명시하면 기본 생성자는 자동 제공되지 않으므로, 필요시 직접 오버로딩하여 정의해야 합니다.
표준 JavaBean 설계
표준 JavaBean은 데이터 캡슐화, 기본 및 전체 매개변수 생성자 제공, Getter/Setter 메서드 구비를 규칙으로 합니다.
public class Product {
private String productId;
private String productName;
private int stockQuantity;
// 기본 생성자
public Product() {
}
// 전체 매개변수 생성자
public Product(String productId, String productName, int stockQuantity) {
this.productId = productId;
this.productName = productName;
this.stockQuantity = stockQuantity;
}
// Getters and Setters
public String getProductId() { return productId; }
public void setProductId(String productId) { this.productId = productId; }
public String getProductName() { return productName; }
public void setProductName(String productName) { this.productName = productName; }
public int getStockQuantity() { return stockQuantity; }
public void setStockQuantity(int stockQuantity) { this.stockQuantity = stockQuantity; }
}
객체의 메모리 구조 분석
힙(Heap)과 스택(Stack) 영역
객체를 생성하면 실제 데이터는 힙 메모리에 저장되며, 스택 메모리에 선언된 참조 변수는 힙에 할당된 객체의 주소를 보관합니다. 하나의 참조 변수가 객체를 가리킬 수도 있고, 여러 참조 변수가 동일한 힙 메모리 주소를 공유할 수도 있습니다. 후자의 경우, 하나의 변수를 통해 객체 상태를 변경하면 다른 변수를 통해서도 변경된 상태가 반영됩니다. this 키워드의 본질 또한 현재 메서드를 호출한 객체의 힙 메모리 주소값입니다.
기본형과 참조형 데이터 타입
- 기본형 데이터 타입(Primitive): 변수의 메모리 공간에 실제 값 자체가 저장됩니다. 다른 변수에 할당 시 값이 복사됩니다.
- 참조형 데이터 타입(Reference): 변수의 메모리 공간에는 힙에 위치한 실제 객체의 주소값이 저장됩니다. 다른 변수에 할당 시 주소값이 복사되어 동일한 객체를 가리키게 됩니다.
멤버 변수와 지역 변수의 차이
- 멤버 변수(인스턴스 변수): 클래스 영역에 선언되며, 객체가 생성될 때 힙 메모리에 할당됩니다. 객체가 소멸될 때까지 생명 주기를 유지하며, 명시적으로 초기화하지 않아도 자료형에 따른 기본값으로 자동 초기화됩니다.
- 지역 변수: 메서드나 블록 내부에 선언되며, 메서드가 호출될 때 스택 메모리에 할당됩니다. 메서드 실행이 종료되면 소멸하며, 사용하기 전에 반드시 명시적으로 초기화해야 합니다.