본문 바로가기

자바

[Java] static, 잘 알고 사용하자.

Static

클래스 레벨의 변수나 메소드, 블록을 정의할 때 사용된다.

  • 인스턴스 생성 없이 접근 가능하며, 모든 인스턴스에서 공유 가능
  1. JVM 에서 드러나는 특성
    • 메모리의 메소드 영역에 할당
    • Static 변수와 static 메소드는 Static 메모리 영역에 존재
      • 프로그램 시작 시 메모리에 할당되고 프로그램 종료될 때까지 유지된다.
      • 객체가 생성되기 이전에 이미 할당이 되어 있다.
      • 메모리의 메소드 영역에 할당되기 때문이다.
  2. 주된 사용법
    • 모든 인스턴스가 공통적으로 사용해야 하는 값이 존재할 때
  3. 단점
    • 객체지향 프로그래밍 원칙과 상반된다.
    • 과도한 static 사용 시 메모리 누수의 원인이 될 수 있다.

💡 메모리의 메소드 영역

  • Static 영역을 포함하고 있으며 GC 의 관리 영역 밖에 존재한다.
  • 일반적으로 우리가 만든 Class는 Static 영역에 생성된다.
  • 클래스 정보를 처음 메모리 공간에 올릴 때 초기화되는 대상을 저장하기 위한 메모리 공간
  • Runtime Constant Pool 영역을 통해 상수 자료형을 저장하여 참조하고 중복을 방지한다.

 

 

Static 변수

  • class 의 변수이다.
  • 프로그램의 생명주기 동안 메모리에 상주한다.
  • 특정 데이터를 모든 인스턴스가 공유해야 할 때 유용하다.
  1. 장점
    • 인스턴스마다 별도의 복사본을 유지할 필요가 없어 메모리 사용을 최적화할 수 있다.
  2. 부작용
    • static 변수의 남용은 객체지향의 원칙에 어긋난다
    • 메모리 관리 측면에서도 부정적인 영향을 줄 수 있다
    ⇒ 메모리 자원이 제한적인 환경에서 문제가 될 수 있다.
public class Employee {
    public static int employeeCount = 0; // static 변수

    public Employee() {
        employeeCount++;
    }
}
  • static 변수는 프로그램이 실행되는 동안 계속 살아있다
    • 함수 내에서 인스턴스를 생성하는 것이 함수 호출이 끝난 후 인스턴스가 소멸되면서 객체의 라이프타임에 더욱 적합할 수 있다.

 

 

Static 메서드

인스턴스(객체)를 생성하지 않고도 메소드를 호출할 수 있다.

  • 메모리에 할당시켜 호출이 가능한 Static 메서드가 된다.
  • static 메서드 내에서는 인스턴스 멤버들을 직접 사용할 수 없다.
  • static 메소드는 클래스 변수만 사용할 수 있다는 단점이 있다.
  1. 장점
    • 인스턴스의 상태에 의존하지 않는 연산을 수행할 때 유용
    • 메소드 호출 시 인스턴스 생성의 오버헤드 없이 빠른 실행이 가능
  2. 한계
    • 클래스의 다른 static 메소드나 변수만 접근 가능
    • 인스턴스의 상태를 직접 변경할 수 없다.
      • 인스턴스 멤버에 접근해야 하는 경우에는 사용 불가
public class ReferenceStatic{
		String name = "min"; // 인스턴스 변수
		...
		public static void staticMethod(){
		// non-static variable name cannot be referenced from a static contenxt (error)
				System.out.println(name);
		}
}

 

 

Static 클래스 변수, 멤버변수

하나의 변수를 모든 인스턴스가 공유한다.

  • 원래 인스턴스 변수는 하나의 클래스로부터 생성되었더라도 각기 다른 값을 갖늗나. 하지만 static 멤버변수는 인스턴스에 관계 없이 같은 값을 갖는다.
  • 모든 인스턴스에서 같은 값이 유지되어야 하는 변수는 static 을 붙여서 정의 (final 은 값 수정 불가, static 가능)

클래스 변수

  • 모든 객체에서 하나의 값을 바라보게 된다.
  • 멤버 클래스에서 바깥 인스턴스에 접근할 일이 없다면 무조건 static을 붙여서 정적 멤버 클래스로 만들자
public class ReferenceStatic{
//		String name = "min"; // 인스턴스 변수
		static String name // 클래스 변수
		...
		public static void staticMethod(){
		// non-static variable name cannot be referenced from a static contenxt (error)
				System.out.println(name);
		}
}

 

 

Static 블록

객체는 여러개를 생성하지만 한번만 호출되어야 하는 코드가 있다면 static 블록을 사용한다.

public class AppConfig {
    static {
        // 한번만 수행되어야 하는 코드
    }
    public AppConfig(){
		    // ... 생략
    }
}
  • 클래스 내에 선언되며 메소드나 생성자 내에서는 선언할 수 없다.
  • 여러개의 static 블록을 등록할 수 있으며 선언된 순서대로 호출된다.
  • 클래스를 초기화할 때 반드시 수행되어야 하는 작업이 있을 경우 유용하다.
  • static 블록 안에서는 static 으로 선언된 것만 사용 가능하다.

실행 순서

클래스가 메모리에 로드될 때 실행된다.

⇒ static 블럭이 먼저 호출되고 AppConfig() 생성자로 클래스가 생성

  1. static Block 내부 코드 실행
  2. 생성자 내부 코드 실행

주의점

  • 예외를 발생시킬 경우
    • 프로그램 초기화 과정에 영향을 줄 수 있다
    • → 프로그램의 안정성을 해칠 수 있다.
    • 복잡한 초기화 로직을 다룰 때 주의하자.

 

 

Static 으로 선언한 클래스

Static nested class

  • Static nested 클래스를 감싸고 있는 외부 클래스를 먼저 생성
  • 이후 Static 으로 선언한 클래스 생성
  • Static Nested 클래스는 static 변수만 참조할 수 있다.
    • 부모 클래스에서 static 하지 않은 변수를 참조할 수 없다.

Nested 클래스

클래스 안의 클래스

  • Static 키워드 유무에 따른 1차 분류 (static, non-static)
    • Static Nested class
    • Inner(내부) class
    1. Non-static nested class 는 함께 포함되어 있는 다른 class 의 member 들에 접근할 수 있다.
      • 해당 class 가 private 이라 하더라도.
    2. Static nested classes 들은 다른 class 의 member 에 접근할 수 없다.
    3. inner class 는 '인스턴스 메소드, 변수' 처럼 inner class 를 포함하는 클래스의 인스턴스에 연결된다.
    4. ⇒ inner class 의 인스턴스는 outer class 의 인스턴스가 존재해야만 존재할 수 있다.
  • 이름 유무에 따른 Inner class 2차 분류
    • Local inner class
    • Anonymous class

필요성

  • 한 곳에서만 사용되는 클래스를 논리적으로 묶어서 처리할 필요가 있을 때
  • ⇒ Static Nested 클래스
  • 캡슐화가 필요할 때
  • ⇒ Inner Class
  • 소스의 가독성과 유지보수성을 높이고 싶을 때

언제 Static 으로 inner 클래스를 생성할까?

[ 알아두어야 할 점 ]

  1. Inner class (Non-static nested class) 는 Outer class 의 인스턴스화 이후 Inner class 의 인스턴스화가 가능
  2. 두 인스턴스의 관계정보는 Inner class의 인스턴스 안에 만들어져 메모리 공간을 더 차지하며, 생성시간도 더 걸린다.
  3. Inner class 가 Outer class 인스턴스에 대한 참조를 갖고 있다: inner class, outer class 두 인스턴스가 연결되어 있어서 outer class 인스턴스의 메모리를 빼앗을 수 없다.
  4. Garbage Collection 은 Outer class 의 인스턴스를 GC 대상으로 보지 않게 된다.

[ 결론 ]

  1. 때문에 Outer class 를 참조할 일이 없다면, Nested class 는 static 을 붙여 무조건 static nested class 를 만들자

 

 

 

Static 는 신중히 사용하자.

메모리 측면

  • memory leak 메모리 누수
    • static 변수는 프로그램이 실행되는 동안 계속 살아있다. (메소드 영역)
    • 함수 내에서 인스턴스를 생성하는 것이 함수 호출이 끝난 후 인스턴스가 소멸되기에 객체의 라이프타임에 더욱 적합할 수 있다.
  • 무분별하게 이 곳에 저장하다보면 메모리를 낭비하여 필요한 변수만 사용할 필요가 있다.

객체지향 측면

  • static 은 객체 지향적이지 않다.
    • 객체지향 프로그래밍 원칙
      • 한 객체가 지니는 데이터는 외부에서 함부로 접근하여 수정할 수 없다.
      • static 은 전역 변수로 사용할 때 유효하지만 캡슐화되어야 한다는 원칙에 위반된다.
  • static 은 재사용성이 떨어진다.
    • static 메서드는 interface 를 구현하는데 사용 될 수 없다.
    • 따라서, 재사용성을 높여주는 객체지향적 설계에 방해될 수 있다.

 


 

 

 

static 과 객체지향적 관점

static 에 관하여. 그리고 자바가 static을 지양하는 이유는?

velog.io