1. 학습 주제
클래스 설계에서 자주 사용하는 키워드와 객체 배열 활용 방식을 정리했다.
static과 final의 역할, 싱글톤 패턴의 구조, 변수의 생성 위치에 따른 차이, 초기화 블록의 실행 순서, 그리고 객체 배열을 다루는 방법까지 연결해서 이해할 수 있었다.
- static 필드와 메서드의 특징 이해하기
- final 변수, 메서드, 클래스의 의미 정리하기
- 싱글톤 패턴 구조 익히기
- 인스턴스 변수, 클래스 변수, 지역변수 차이 이해하기
- 정적 초기화 블록과 인스턴스 초기화 블록 학습하기
- 객체 배열 선언과 초기화 방식 익히기
- 객체 배열 순회와 최댓값 찾기 연습하기
2. static 키워드
static은 객체마다 따로 존재하는 값이 아니라, 클래스 전체에서 하나만 공유하는 멤버를 만들 때 사용한다.
private int personalLocker;
private static int sharedLocker;
- personalLocker는 객체마다 따로 존재하는 인스턴스 변수이다.
- sharedLocker는 모든 객체가 함께 사용하는 클래스 변수이다.
- 객체를 여러 개 생성해도 static 필드는 하나만 존재한다.
학생마다 개인 사물함은 따로 증가하고, 공용 사물함은 함께 증가하는 구조로 표현했다.
student1.increasePersonalLocker();
student1.increaseSharedLocker();
- 인스턴스 변수는 각 객체의 상태를 관리한다.
- 클래스 변수는 모든 객체가 공유하는 공통 상태를 관리한다.
3. static 메서드와 일반 메서드
static 메서드는 객체를 생성하지 않고도 클래스명으로 바로 호출할 수 있다.
CampusActivity.libraryAnnouncement();
- static 메서드는 클래스 차원에서 바로 실행된다.
- 객체 생성 없이 사용할 수 있다.
- 공통 기능이나 유틸성 기능을 만들 때 자주 사용된다.
반대로 일반 메서드는 객체가 있어야 호출할 수 있다.
CampusActivity student = new CampusActivity();
student.openPersonalLocker();
- 일반 메서드는 객체의 상태를 바탕으로 동작한다.
- this를 사용할 수 있다.
- static 메서드 안에서는 this를 사용할 수 없다.
4. final 키워드
final은 한 번 정해지면 바꿀 수 없다는 의미를 가진다.
변수, 메서드, 클래스에 모두 사용할 수 있다.
4.1 final 변수
public static final double PI = 3.141592;
- public static final은 대표적인 상수 선언 방식이다.
- 값이 변하지 않아야 하는 공용 데이터를 표현할 때 사용한다.
- 이름은 보통 대문자와 _를 사용하는 관례가 있다.
4.2 final 필드
final String ssn;
- 객체가 생성될 때 한 번만 초기화할 수 있다.
- 이후에는 값을 변경할 수 없다.
- 주민등록번호처럼 바뀌지 않는 값을 표현할 때 적절하다.
public Person(String ssn, String name) {
this.ssn = ssn;
this.name = name;
}
- final 필드는 생성자에서 반드시 초기화해야 한다.
4.3 final 메서드와 final 클래스
public final void coreMethod() { ... }
- final 메서드는 자식 클래스에서 오버라이딩할 수 없다.
- 핵심 로직을 보호하고 싶을 때 사용한다.
final public class SealedClass { ... }
- final 클래스는 상속 자체가 불가능하다.
- 더 이상 확장되지 않도록 막고 싶을 때 사용한다.
5. 싱글톤 패턴
싱글톤 패턴은 프로그램 전체에서 객체를 단 하나만 생성하도록 보장하는 구조이다.
- 생성자를 private으로 막는다.
- 클래스 내부에 자기 자신의 객체를 하나 저장한다.
- public static 메서드로 그 객체를 꺼내 쓸 수 있게 한다.
5.1 이른 초기화
private static EagerSingleton eager = new EagerSingleton();
- 클래스가 로드될 때 미리 객체를 생성한다.
- 구조가 단순하고 구현이 쉽다.
5.2 게으른 초기화
if(lazy == null) {
lazy = new LazySingleton();
}
- 실제로 필요할 때 객체를 생성한다.
- 처음에는 null 상태로 두고, 요청이 들어오면 만든다.
두 방식 모두 getInstance()를 통해 같은 객체를 반환한다는 점이 핵심이다.
EagerSingleton eager1 = EagerSingleton.getInstance();
EagerSingleton eager2 = EagerSingleton.getInstance();
- 여러 번 호출해도 같은 인스턴스를 공유한다.
- 전역 설정, 로그 시스템, DB 연결 설정 같은 곳에 자주 사용된다.
6. 변수의 종류
변수는 선언되는 위치에 따라 생명주기와 접근 범위가 달라진다.
6.1 인스턴스 변수
private int instanceNum;
- 클래스 영역에 선언된다.
- 객체를 만들 때 생성된다.
- 객체마다 독립적으로 존재한다.
6.2 클래스 변수
private static int staticNum;
- static 영역에 하나만 생성된다.
- 모든 객체가 공유한다.
- 프로그램이 종료될 때까지 유지된다.
6.3 지역변수와 매개변수
public void method(int num) {
int localNum;
}
- 메서드 블록 안에서 선언된다.
- 메서드가 호출될 때 생성되고 종료되면 사라진다.
- 지역변수는 사용 전에 직접 초기화해야 한다.
7. 초기화 블록
필드를 초기화하는 방법은 명시적 초기화, 초기화 블록, 생성자 등 여러 가지가 있다.
private String name = "갤럭시";
private int price = 1500000;
private static String brand = "삼성";
- 필드 선언과 동시에 값을 넣는 방식을 명시적 초기화라고 한다.
7.1 인스턴스 초기화 블록
{
name = "아이폰";
price = 1800000;
brand = "애플";
}
- 객체가 생성될 때마다 실행된다.
- 생성자보다 먼저 실행된다.
- 여러 생성자에서 공통으로 필요한 초기화 로직을 모아둘 수 있다.
7.2 정적 초기화 블록
static {
brand = "애플";
}
- 클래스가 메모리에 로드될 때 한 번만 실행된다.
- static 필드 초기화에 사용한다.
- 인스턴스 변수에는 접근할 수 없다.
8. 객체 생성 순서
객체가 만들어질 때 어떤 순서로 초기화가 진행되는지도 확인했다.
- static 초기화 블록
- 명시적 초기값
- 인스턴스 초기화 블록
- 생성자
순서를 이해하면 값이 왜 그렇게 나오는지 더 정확하게 해석할 수 있다.
9. 객체 배열
배열에는 기본 자료형뿐 아니라 객체도 저장할 수 있다.
Car[] carArr = new Car[3];
- 객체 배열을 선언하면 객체 자체가 들어가는 것이 아니라 객체의 참조값을 저장할 공간이 만들어진다.
- 처음에는 각 칸이 null 상태이다.
System.out.println(carArr[0]);
- 아직 객체를 넣지 않았으므로 null이 나온다.
- 이 상태에서 메서드를 호출하면 NullPointerException이 발생한다.
carArr[0] = new Car("페라리", 300);
- 각 인덱스에 실제 객체를 넣어야 사용할 수 있다.
10. 객체 배열 순회와 활용
객체 배열도 일반 배열처럼 반복문으로 순회할 수 있다.
for (int i=0; i<carArr.length; i++) {
carArr[i].driveMaxSpeed();
}
향상된 for문도 사용할 수 있다.
for(Car car : carArr2){
car.driveMaxSpeed();
}
- 객체 배열을 통해 여러 객체를 한 번에 관리할 수 있다.
- 반복문과 함께 사용하면 동일한 동작을 쉽게 수행할 수 있다.
가장 빠른 차를 찾는 최댓값 알고리즘도 함께 확인했다.
Car fastestCar = carArr[0];
for(int i=1; i<carArr.length; i++){
if(carArr[i].getMaxSpeed() > fastestCar.getMaxSpeed()){
fastestCar = carArr[i];
}
}
- 첫 번째 값을 기준으로 잡는다.
- 더 큰 값이 나오면 기준 대상을 교체한다.
- 객체 배열에서도 이런 비교 로직을 동일하게 적용할 수 있다.
11. 흐름 정리
11.1 클래스 설계 관련 개념
- static으로 공용 데이터와 공용 기능 만들기
- final로 변경 불가능한 값과 구조 보호하기
- 싱글톤 패턴으로 객체를 하나만 생성하기
- 변수의 위치에 따라 생명주기와 접근 범위 구분하기
- 초기화 블록과 생성자의 실행 순서 이해하기
11.2 객체 배열 활용
- 객체 배열 선언 시 처음에는 null이 들어간다는 점 확인하기
- 각 칸에 실제 객체를 생성해서 넣기
- 반복문과 향상된 for문으로 객체 배열 순회하기
- 객체 배열을 활용해 최댓값 비교 로직 적용하기
12. 핵심 정리
- static 필드는 모든 객체가 공유하는 클래스 변수이다.
- static 메서드는 객체 없이 클래스명으로 호출할 수 있다.
- final 변수는 한 번 정해지면 변경할 수 없다.
- final 메서드는 오버라이딩할 수 없고, final 클래스는 상속할 수 없다.
- 싱글톤 패턴은 인스턴스를 하나만 생성해 공유하는 구조이다.
- 변수는 인스턴스 변수, 클래스 변수, 지역변수로 나눌 수 있다.
- 인스턴스 초기화 블록은 객체가 생성될 때마다 실행되고, 정적 초기화 블록은 클래스 로드 시 한 번만 실행된다.
- 객체 배열은 처음에 null 참조를 가지므로 바로 메서드를 호출하면 오류가 발생할 수 있다.
- 객체 배열도 반복문으로 순회하며 메서드 호출과 비교 연산을 수행할 수 있다.
- 클래스 설계와 배열 활용을 함께 익히면 더 구조적인 프로그램을 만들 수 있다.
'TIL > [TIL]' 카테고리의 다른 글
| [TIL]Java API, Wrapper, 오토박싱/오토언박싱, 제네릭 (1) | 2026.05.08 |
|---|---|
| [TIL]객체 배열 활용, 상속, 오버라이딩, 다형성, 동적 바인딩, 추상클래스와 인터페이스 (0) | 2026.05.07 |
| [TIL]추상화, DTO, 생성자, 메서드 매개변수와 오버로딩 (0) | 2026.05.04 |
| [TIL]2차원 배열, 배열 복사와 정렬, 클래스와 객체, 캡슐화 (0) | 2026.05.01 |
| [TIL]Java 제어문과 배열 (0) | 2026.04.30 |