클래스(class) 변수로 클래스가 메모리에 적재(load)될 때 한 번만 메모리에 할당되는 변수
생명주기 : 프로그램의 실행부터 종료까지
전역 변수의 성격을 갖는다.
JVM의 메서드 영역(method area)에 저장된다.
모든 인스턴스에 공통적으로 사용해야 할 경우 static을 붙인다.
객체지향은 모듈화된 객체를 전면에 내세우기 때문에 프로그램 전체에서 동일하게 사용되는 전역 변수의 필요성은 줄어든다.
😇 장점 : 공용 자원에 대한 접근
👿 단점 : 위의 이유로 static은 테스트를 힘들게 할 수 있는 요인이 된다.
❗️주의사항 : 다중 스레드 환경에서 공유된 데이터에 대한 동기화가 필요하다. 여러 스레드에서 동시에 접근이 일어날 수 있기 때문이다.
🖥 올바른 사용 : static 사용은 최소화하고, 주로 속성 정보를 변경하지 않는 방식(final)을 사용한다.
클래스와 함께 자동으로 메모리의 static 영역에 생성되어서, static 메서드는 객체 생성할 필요 없이 사용 가능하다.
🚯 Garbage Collector가 처리하지 못한다.
static 메서드 내에서는 this를 사용할 수 없다(❌).
java.lang.Math 클래스의 메서드들은 주로 static으로 선언되어 있다. 왜냐하면 자주 사용하는 클래스이기 때문에 프로세스 실행 중에 따로 객체를 생성하지 않고도 바로 사용할 수 있도록 한 것이다.
static 메서드는 몸체가 있는 메서드(구현 기능이 있는 메서드)에서만 사용 가능하기 때문에 abstract 제어자와는 함께 사용할 수 없다(❌).
public class Main {
public void print(){
System.out.print("이게 실행될까요"); // (❌)
}
public static void main(String[] args){
print();
}
}
값을 변경할 수 없는 상숫값
값을 재할당 할 수 없다.
final 변수의 이름은 관례적으로 대문자를 많이 사용한다.
final 은 해당 변수의 재할당만을 막아줄 뿐, 참조하고 있는 객체 내부의 상태가 변할 수 있다.
final List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3));
System.out.println(numbers); // [1, 2, 3]
numbers.add(4);
System.out.println(numbers); // [1, 2, 3, 4]
final List<Integer> numbers = Collections.unmodifiableList(new ArrayList<>(Arrays.asList(1, 2, 3)));
System.out.println(numbers); // [1, 2, 3]
// 아래의 코드는 변경을 시도하면 예외가 발생합니다.
numbers.add(4); // UnsupportedOperationException 발생
// List.of() 사용
final List<Integer> numbers = List.of(1, 2, 3);
System.out.println(numbers); // [1, 2, 3]
// 아래의 코드는 변경을 시도하면 예외가 발생합니다.
numbers.add(4); // UnsupportedOperationException 발생