Quick Reference
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
User user = new User("Kim");
System.out.println(user.getName());class는 함께 변해야 하는 상태와 동작을 묶고, new는 constructor를 실행해 그 상태를 유효한 값으로 만듭니다. field는 기본적으로 private에 두고, 상태를 바꾸는 규칙은 method에 모읍니다.
문법
어떤 구성 요소가 있나
| 요소 | 역할 |
|---|---|
| class | 객체 설계도 |
| field | 상태 저장 |
| constructor | 생성 시 초기화 |
| method | 동작 정의 |
new | 인스턴스 생성 |
클래스와 객체: 설계도와 실체
클래스는 객체를 만들기 위한 설계도이고, 객체는 그 설계도로 만든 실제 인스턴스입니다. new 키워드로 인스턴스를 생성하면 각각 독립된 상태를 가집니다.
User u1 = new User("Kim");
User u2 = new User("Lee");
System.out.println(u1.getName()); // "Kim"
System.out.println(u2.getName()); // "Lee" — 독립적인 상태field, method, constructor의 역할
field는 객체가 가진 상태를, method는 객체가 할 수 있는 동작을 나타냅니다. constructor는 객체가 처음 만들어질 때 필요한 초기화 규칙을 담당합니다. private field와 public 접근 메서드(getter/setter) 패턴이 캡슐화의 기본 형태입니다.
public class Counter {
private int count; // field: 상태
public Counter(int initial) { // constructor: 초기화
this.count = initial;
}
public void increment() { // method: 동작
count++;
}
public int getCount() { // getter: 상태 노출
return count;
}
}인스턴스를 만들 때는 상위 클래스 초기화가 먼저 진행되고, field initializer와 instance initializer가 선언 순서대로 실행된 뒤 constructor 본문이 실행됩니다. constructor 안에서 override 가능한 메서드를 호출하면 하위 클래스 field가 아직 초기화되지 않은 상태를 볼 수 있으므로 피합니다.
class Parent {
Parent() { print(); } // 피해야 하는 패턴
void print() {}
}
class Child extends Parent {
private String label = "ready";
@Override void print() {
System.out.println(label); // Parent 생성 중에는 null일 수 있음
}
}this와 캡슐화
this는 현재 인스턴스를 가리키며, field와 매개변수 이름이 겹칠 때 중요합니다. Java 객체지향의 핵심은 단순히 클래스를 만드는 법보다 "상태와 동작을 어떤 경계 안에 모을 것인가"입니다. 이 감각이 이후 상속, 인터페이스, 캡슐화로 이어집니다.
체크포인트
| 상황 | 적합한 선택 |
|---|---|
| 객체 만들기 | new ClassName(...) |
| 상태 유지 | field (보통 private) |
| 동작 정의 | method |
| 생성 시 초기화 | constructor |
| 현재 인스턴스 참조 | this |
생성자에서 받은 mutable collection이나 array를 그대로 field에 넣으면 호출자가 나중에 상태를 바꿀 수 있습니다. 값 객체라면 List.copyOf(...)나 방어적 복사로 소유권을 분리합니다.
주의할 점
객체지향을 "필드와 메서드를 한 파일에 모으는 문법"으로만 이해하면 설계 감각이 안 생깁니다.
// ❌ 상태 없이 static 메서드만 모은 클래스 — 절차적 코드와 다를 바 없음
public class UserUtils {
public static String formatName(String first, String last) { ... }
public static boolean isValidEmail(String email) { ... }
}
// ✅ 상태와 동작을 함께 캡슐화
public class User {
private final String firstName;
private final String lastName;
private final String email;
public User(String firstName, String lastName, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
public String formatName() { return firstName + " " + lastName; }
public boolean hasValidEmail() { return email.contains("@"); }
}참고 링크
2 sources