[JAVA] 객체와 객체 지향 – static변수 와 변수의 유효 범위와 메모리 static응용(싱글톤패턴)

– static변수

자바에서 static 변수는 클래스 변수라고도 불리며, 클래스에 속하는 변수로, 해당 클래스의 모든 인스턴스가 공유합니다. static 변수는 클래스가 메모리에 로드될 때 초기화되며, 프로그램 종료 시까지 존재합니다.
다음은 static 변수의 주요 특징입니다:
  1. 클래스 레벨에서 선언: static 변수는 클래스 내부에 선언되지만, 특정 인스턴스에 속하지 않고 클래스 자체에 속합니다. 따라서 클래스의 모든 인스턴스가 동일한 static 변수를 공유합니다.
  2. 공유된 값: 클래스의 모든 인스턴스는 동일한 static 변수 값을 공유합니다. 이는 어떤 인스턴스에서 static 변수의 값을 변경하면, 다른 모든 인스턴스에서 그 변경된 값을 사용할 수 있음을 의미합니다.
  3. 클래스 이름으로 접근: static 변수는 클래스 이름을 통해 직접 접근할 수 있습니다. 인스턴스를 생성하지 않고도 static 변수에 접근할 수 있다는 점이 큰 장점입니다. 예를 들어, ClassName.variableName과 같이 사용합니다.
  4. 메모리 관리: static 변수는 클래스 로딩 시 한 번만 초기화되며, 프로그램이 종료될 때까지 메모리에 유지됩니다. 이는 메모리 사용을 효율적으로 관리하는 데 도움이 됩니다.
  • 여러 인스턴스가 공유하는 기준 값이 필요한 경우
  • 학생마다 새로운 학번 생성
  • 카드회사에서 카드를 새로 발급할때마다 새로운 카드 번호를 부여
  • 회사에서 사원이 입사할때 마다 새로운 사번이 필요함
public class Employee {
    private static int serialNum = 1000;
    private int employeeId;
    private String employeeName;
    private String department;

    public Employee(){
        employeeId = ++serialNum;
    }

    public int getEmployeeId() {
        return employeeId;
    }
    public void setEmployeeId(int employeeId) {
        this.employeeId = employeeId;
    }
    public String getEmployeeName() {
        return employeeName;
    }
    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }
    public String getDepartment() {
        return department;
    }
    public void setDepartment(String department) {
        this.department = department;
    }
    public static int getSerialNum() {
        return serialNum;
    }
    public static void setSerialNum(int serialNum) {
        Employee.serialNum = serialNum;
    }
}

public class EmployeeTest {
    public static void main(String[] args) {
        Employee employeeLee = new Employee();
        employeeLee.setEmployeeName("이순신");

        Employee employeeKim = new Employee();
        employeeLee.setEmployeeName("김유신");

        System.out.println(employeeLee.getEmployeeId());
        System.out.println(employeeKim.getEmployeeId());
        System.out.println(Employee.getSerialNum());

    }
}

– 변수의 유효 범위와 메모리

자바에서 변수의 유효 범위(Scope)와 메모리 관리는 변수의 선언 위치에 따라 결정됩니다. 이를 이해하는 것은 코드 작성 시 변수의 생명주기와 접근 가능성을 효과적으로 관리하는 데 중요합니다.

변수의 유효 범위(Scope)

자바에서 변수의 유효 범위는 변수가 어디서 선언되었는지에 따라 결정됩니다. 변수의 유효 범위는 주로 네 가지로 구분됩니다.

  1. 지역 변수(Local Variables)
    • 선언 위치: 메서드나 블록 내부에서 선언됩니다.
    • 유효 범위: 선언된 블록 내에서만 유효합니다.
    • 생명주기: 메서드나 블록이 실행되는 동안에만 존재하며, 실행이 끝나면 메모리에서 해제됩니다.
    • 예시
    • public void myMethod() { int localVar = 10; // 지역 변수 System.out.println(localVar); }
  2. 인스턴스 변수(Instance Variables)
    • 선언 위치: 클래스 내부, 메서드 외부에서 선언됩니다.
    • 유효 범위: 클래스의 인스턴스(객체) 내에서 유효합니다.
    • 생명주기: 객체가 생성될 때 할당되고, 객체가 가비지 컬렉션에 의해 수거될 때 해제됩니다.
    • 예시
    • public class MyClass { int instanceVar; // 인스턴스 변수 public MyClass(int instanceVar) { this.instanceVar = instanceVar; } }
  3. 클래스 변수(Static Variables)
    • 선언 위치: 클래스 내부에서 static 키워드로 선언됩니다.
    • 유효 범위: 클래스 전체에서 유효하며, 클래스의 모든 인스턴스에서 공유됩니다.
    • 생명주기: 프로그램 시작 시 할당되고, 프로그램 종료 시 해제됩니다.
    • 예시
    • public class MyClass { static int staticVar = 0; // 클래스 변수 public MyClass() { staticVar++; } }
  4. 매개 변수(Parameter Variables)
    • 선언 위치: 메서드 선언부에서 선언됩니다.
    • 유효 범위: 메서드 내에서만 유효합니다.
    • 생명주기: 메서드가 호출될 때 생성되고, 메서드 실행이 끝나면 해제됩니다.
    • 예시
    • public void myMethod(int param) { // 매개 변수 System.out.println(param); }

메모리 관리

자바에서 메모리는 크게 세 가지 영역으로 나눌 수 있습니다

  1. 스택(Stack)
    • 지역 변수와 매개 변수가 저장됩니다.
    • 메서드 호출 시 할당되고, 메서드 종료 시 해제됩니다.
    • 빠른 접근 속도를 제공하지만, 크기가 제한적입니다.
  2. 힙(Heap)
    • 동적으로 생성된 객체와 인스턴스 변수가 저장됩니다.
    • 가비지 컬렉터에 의해 관리되며, 더 이상 참조되지 않는 객체는 자동으로 해제됩니다.
    • 크기가 크고, 동적 할당이 가능하지만, 스택에 비해 접근 속도가 느립니다.
  3. 메서드 영역(Method Area)
    • 클래스 변수와 클래스 정보(메타데이터)가 저장됩니다.
    • 프로그램이 시작될 때 할당되고, 종료될 때 해제됩니다.
    • 클래스 로딩 시 초기화되며, 모든 인스턴스가 공유합니다.
  • 변수의 유효 범위(scope)와 생성과 소멸(life cycle)은 각 변수의 종류마다 다름
  • 지역변수, 멤버 변수, 클래스 변수는 유효범위와 life cycle, 사용하는 메모리도 다름
변수 유형선언 위치사용 범위메모리생성과 소멸
지역 변수
(로컬 변수)
함수 내부에 선언함수 내부에서만 사용스택함수가 호출될 때 생성되고 함수가 끝나면 소멸함
멤버 변수
(인스턴스 변수)
클래스 멤버 변수 로 선언클래스 내부에서 사용하고 private이 아니면 참조 변수로 다른 클래스에서 사용 가능인스턴스가 생성될 때 힙에 생성되고, 가비지 컬렉터가 메모리를 수거할 때 소멸됨
static 변수
(클래스 변수)
static 예약어를 사용하여 클래스 내부에 선언클래스 내부에서 사용하고 private이 아니면 클래스 이름으로 다른 클래스에서 사용 가능데이터 영역프로그램이 처음 시작할 때 상수와 함께 데이터 영역에 생성되고 프로그램이 끝나고 메모리를 해제할 때 소멸됨

  • static 변수는 프로그램이 메모리에 있는 동안 계속 그 영역을 차지하므로 너무 큰 메모리를 할당하는 것은 좋지 않음
  • 클래스 내부의 여러 메서드에서 사용하는 변수는 멤버 변수로 선언하는 것이 좋음
  • 멤버 변수가 너무 많으면 인스턴스 생성 시 쓸데없는 메모리가 할당됨
  • 상황에 적절하게 변수를 사용 해야 함

– static응용(싱글톤패턴)

자바에서 static 키워드는 여러 용도로 활용될 수 있으며, 그 중 하나는 싱글톤 패턴(Singleton Pattern)의 구현입니다. 싱글톤 패턴은 클래스의 인스턴스를 하나만 생성하고, 이를 전역적으로 접근할 수 있도록 하는 디자인 패턴입니다. 이는 특정 클래스의 객체가 오직 하나만 존재해야 하는 상황에서 유용하게 사용됩니다.

싱글톤 패턴의 특징

  1. 단일 인스턴스: 싱글톤 패턴은 클래스의 인스턴스를 하나만 생성하고, 이를 공유합니다.
  2. 전역 접근: 생성된 인스턴스는 전역적으로 접근할 수 있습니다.
  3. 인스턴스 제어: 인스턴스 생성과 접근을 제어하여 자원의 낭비를 방지하고, 일관된 상태를 유지할 수 있습니다.
  • 프로그램에서 인스턴스가 단 한 개만 생성되어야 하는 경우 사용하는 디자인 패턴
  • static변수, 메서드를 활용하여 구현 할 수 있음
public class School {
    private static School instance = new School();
//    private School(){}
    public static School getInstance(){
        if (instance == null){
            instance = new School();
        }
        return instance;
    }
}

import java.util.Calendar;

public class SchoolTest {
    public static void main(String[] args) {
        School school1 = School.getInstance();
        School school2 = School.getInstance();

        System.out.println(school1 == school2);
    }
    Calendar calendar = Calendar.getInstance();
}

Leave a Comment