Static
클래스 레벨의 변수나 메소드, 블록을 정의할 때 사용된다.
- 인스턴스 생성 없이 접근 가능하며, 모든 인스턴스에서 공유 가능
- JVM 에서 드러나는 특성
- 메모리의 메소드 영역에 할당
- Static 변수와 static 메소드는 Static 메모리 영역에 존재
- 프로그램 시작 시 메모리에 할당되고 프로그램 종료될 때까지 유지된다.
- 객체가 생성되기 이전에 이미 할당이 되어 있다.
- 메모리의 메소드 영역에 할당되기 때문이다.
- 주된 사용법
- 모든 인스턴스가 공통적으로 사용해야 하는 값이 존재할 때
- 단점
- 객체지향 프로그래밍 원칙과 상반된다.
- 과도한 static 사용 시 메모리 누수의 원인이 될 수 있다.
💡 메모리의 메소드 영역
- Static 영역을 포함하고 있으며 GC 의 관리 영역 밖에 존재한다.
- 일반적으로 우리가 만든 Class는 Static 영역에 생성된다.
- 클래스 정보를 처음 메모리 공간에 올릴 때 초기화되는 대상을 저장하기 위한 메모리 공간
- Runtime Constant Pool 영역을 통해 상수 자료형을 저장하여 참조하고 중복을 방지한다.
Static 변수
- class 의 변수이다.
- 프로그램의 생명주기 동안 메모리에 상주한다.
- 특정 데이터를 모든 인스턴스가 공유해야 할 때 유용하다.
- 장점
- 인스턴스마다 별도의 복사본을 유지할 필요가 없어 메모리 사용을 최적화할 수 있다.
- 부작용
- static 변수의 남용은 객체지향의 원칙에 어긋난다
- 메모리 관리 측면에서도 부정적인 영향을 줄 수 있다
public class Employee {
public static int employeeCount = 0; // static 변수
public Employee() {
employeeCount++;
}
}
- static 변수는 프로그램이 실행되는 동안 계속 살아있다
- 함수 내에서 인스턴스를 생성하는 것이 함수 호출이 끝난 후 인스턴스가 소멸되면서 객체의 라이프타임에 더욱 적합할 수 있다.
Static 메서드
인스턴스(객체)를 생성하지 않고도 메소드를 호출할 수 있다.
- 메모리에 할당시켜 호출이 가능한 Static 메서드가 된다.
- static 메서드 내에서는 인스턴스 멤버들을 직접 사용할 수 없다.
- static 메소드는 클래스 변수만 사용할 수 있다는 단점이 있다.
- 장점
- 인스턴스의 상태에 의존하지 않는 연산을 수행할 때 유용
- 메소드 호출 시 인스턴스 생성의 오버헤드 없이 빠른 실행이 가능
- 한계
- 클래스의 다른 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() 생성자로 클래스가 생성
- static Block 내부 코드 실행
- 생성자 내부 코드 실행
주의점
- 예외를 발생시킬 경우
- 프로그램 초기화 과정에 영향을 줄 수 있다
- → 프로그램의 안정성을 해칠 수 있다.
- 복잡한 초기화 로직을 다룰 때 주의하자.
Static 으로 선언한 클래스
Static nested class
- Static nested 클래스를 감싸고 있는 외부 클래스를 먼저 생성
- 이후 Static 으로 선언한 클래스 생성
- Static Nested 클래스는 static 변수만 참조할 수 있다.
- 부모 클래스에서 static 하지 않은 변수를 참조할 수 없다.
Nested 클래스
클래스 안의 클래스
- Static 키워드 유무에 따른 1차 분류 (static, non-static)
- Static Nested class
- Inner(내부) class
- Non-static nested class 는 함께 포함되어 있는 다른 class 의 member 들에 접근할 수 있다.
- 해당 class 가 private 이라 하더라도.
- Static nested classes 들은 다른 class 의 member 에 접근할 수 없다.
- inner class 는 '인스턴스 메소드, 변수' 처럼 inner class 를 포함하는 클래스의 인스턴스에 연결된다.
- ⇒ inner class 의 인스턴스는 outer class 의 인스턴스가 존재해야만 존재할 수 있다.
- 이름 유무에 따른 Inner class 2차 분류
- Local inner class
- Anonymous class
필요성
- 한 곳에서만 사용되는 클래스를 논리적으로 묶어서 처리할 필요가 있을 때
- ⇒ Static Nested 클래스
- 캡슐화가 필요할 때
- ⇒ Inner Class
- 소스의 가독성과 유지보수성을 높이고 싶을 때
언제 Static 으로 inner 클래스를 생성할까?
[ 알아두어야 할 점 ]
- Inner class (Non-static nested class) 는 Outer class 의 인스턴스화 이후 Inner class 의 인스턴스화가 가능
- 두 인스턴스의 관계정보는 Inner class의 인스턴스 안에 만들어져 메모리 공간을 더 차지하며, 생성시간도 더 걸린다.
- Inner class 가 Outer class 인스턴스에 대한 참조를 갖고 있다: inner class, outer class 두 인스턴스가 연결되어 있어서 outer class 인스턴스의 메모리를 빼앗을 수 없다.
- ⇒ Garbage Collection 은 Outer class 의 인스턴스를 GC 대상으로 보지 않게 된다.
[ 결론 ]
- 때문에 Outer class 를 참조할 일이 없다면, Nested class 는 static 을 붙여 무조건 static nested class 를 만들자
Static 는 신중히 사용하자.
메모리 측면
- memory leak 메모리 누수
- static 변수는 프로그램이 실행되는 동안 계속 살아있다. (메소드 영역)
- 함수 내에서 인스턴스를 생성하는 것이 함수 호출이 끝난 후 인스턴스가 소멸되기에 객체의 라이프타임에 더욱 적합할 수 있다.
- 무분별하게 이 곳에 저장하다보면 메모리를 낭비하여 필요한 변수만 사용할 필요가 있다.
객체지향 측면
- static 은 객체 지향적이지 않다.
- 객체지향 프로그래밍 원칙
- 한 객체가 지니는 데이터는 외부에서 함부로 접근하여 수정할 수 없다.
- static 은 전역 변수로 사용할 때 유효하지만 캡슐화되어야 한다는 원칙에 위반된다.
- 객체지향 프로그래밍 원칙
- static 은 재사용성이 떨어진다.
- static 메서드는 interface 를 구현하는데 사용 될 수 없다.
- 따라서, 재사용성을 높여주는 객체지향적 설계에 방해될 수 있다.
- https://velog.io/@yyy96/static
- https://f-lab.kr/insight/understanding-and-using-java-static-keyword?gad_source=1&gclid=Cj0KCQjwsPCyBhD4ARIsAPaaRf1jdSNsTvOESOErMeak_vrOI0rveiJIErtRZfpLZf_E24ofTole62gaAj7QEALw_wcB
- https://wikidocs.net/228
- https://my-codinglog.tistory.com/m/entry/Nested-Class-에-언제-static-을-붙여야-할까
- https://velog.io/@mooh2jj/Java-static-변수-static-메서드-그리고-static-클래스#중첩-클래스inner-클래스란
static 과 객체지향적 관점
static 에 관하여. 그리고 자바가 static을 지양하는 이유는?
velog.io
'자바' 카테고리의 다른 글
[JAVA] String Literal & String Object (0) | 2024.05.14 |
---|---|
[Java] JVM의 이해(3) - Garbage Collection (2) | 2024.02.22 |
[Java] JVM의 이해(2) - 주요 메모리와 static (0) | 2024.02.21 |
[Java] 자바 가상 머신 이해(1) - JVM 구조 (0) | 2024.02.20 |