Programing Language/Java
[Java] 정적 & 불변 제어자(Static & Final Modifier)
vinedpillar
2022. 6. 27. 16:27
클래스 멤버의 메모리 저장 방식
- 클래스의 인스턴스가 생성되면 스택 메모리에 변수와 인스턴스가 생성된 힙 메모리의 주소가 생성되며, 힙 메모리에는 인스턴스의 데이터들이 저장됩니다.
- 클래스의 필드 데이터는 생성된 인스턴스마다 값이 다를 수 있지만, 메서드는 인스턴스가 달라도 같은 기능을 가지게 됩니다.
- 동일한 기능을 수행하는 메서드 코드가 여러 인스턴스에 중복하여 저장되면 메모리를 불필요하게 낭비하는 셈이 되기 때문에 JVM에서는 이를 메서드 영역(= 클래스 영역) 이라는 별도의 메모리 공간을 나눠 저장하고 있습니다.
- 또한 이렇게 별도로 저장된 메서드를 호출할 때 인스턴스가 생성되지 않으면 호출될 수 없도록 제한을 걸어놓고 있습니다.

정적 제어자(Static Modifier)
- 정적(static) 제어자는 클래스의 요소를 인스턴스를 생성하지 않아도 사용할 수 있게 만들어주는 제어자입니다.
- 클래스의 멤버를 정적으로 선언할 경우 데이터를 힙 메모리가 아닌 메서드 영역에 저장하게 됩니다.
- 때문에 인스터스 생성 없이도 바로 필드나 메서드의 사용이 가능하게 됩니다.
정적 필드 사용 방법
public class 클래스이름 {
// 정적 필드 선언
// 초기값 지정 가능
static 타입 변수이름
// 정적 메서드 선언
static 리턴타입 메서드이름(매개변수) {
메서드 내용
}
}
- 클래스의 모든 인스턴스가 동일하게 가지고 있어야할 공용적인 필드는 정적 필드로 선언하는 것이 좋습니다.
- 인스턴스의 필드 값을 매개변수나 연산 값으로 사용하지 않는 메서드는 정적 메서드로 선언하는 것이 좋습니다.
정적 필드와 메서드 선언 예시
// 계산기 프로그램 예시
public class calculator {
// 인스터스(일반) 필드
String calculatorName;
// 정적 필드
static double pi = 3.14159;
static double euler = 2.71828;
// 인스턴스(일반) 메서드
// 인스턴스 값을 매개로 하기 때문에 일반 메서드로 선언
void setcalculatorName(String calculatorName) {
this.calculatorName = calculatorName;
}
// 정적 메서드
static int plus(int x, int y) {
return x + y;
}
// 정적 메서드
static int minus(int x, int y) {
return x - y;
}
}
정적 블록(static block)
- 정적으로 사용되는 필드 값은 선언과 동시에 초기값을 대입하는 것이 일반적입니다.
- 하지만 필드값의 초기화 작업이 복잡하다면 정적 블록을 활용할 수 있습니다.
- 정적 블록은 클래스가 메모리로 로딩될 때 자동으로 실행되며, 선언된 순서대로 실행됩니다.
- 정적 메서드와 정적 블럭은 인스턴스가 생성되지 않아도 실행되기 때문에 인스턴스가 생성되어야만 값을 사용할 수 있는 인스턴스 필드와 메서드는 사용할 수 없습니다.
- 마찬가지로 자신의 인스턴스 값을 참조하는 this 키워드도 사용할 수 없습니다.
정적 블럭 사용 방법
static {
정적 블럭 선언 위치
}
정적 블럭 사용 예시
public class calculator {
static String companyCode = "ASO";
static String productCode = "CAL";
static String productionDate = "20180328";
static String serialNumber;
// serialNumber에 20180328CALASO 저장
static {
serialNumber = productionDate + productCode + companyCode;
}
}
불변 제어자(Final Modifier)
- 불변(final) 제어자는 선언된 클래스나 필드, 메서드가 변경되는 것을 막아주는 제어자입니다.
- 불변으로 선언된 필드 값은 프로그램 실행 중에는 수정할 수 없습니다.
- final 필드의 초기값을 선언하는 방법은 2가지 뿐입니다.
- 필드 선언시 변수와 값을 같이 선언하는 방법
- 생성자를 통해 초기화 할 때 선언
불변(final) 키워드 사용 방법
public class 클래스이름 {
// 불변 필드 선언
final 타입 변수이름 = 초기값;
}
불변 제어자 사용 예시
public class Calculator {
// 불변 필드 선언
// 초기값 미지정
final String calculatorName;
// 초기값 지정
final double pi = 3.14159;
final double euler = 2.71828;
// 컨스트럭터를 통한 필드값 초기화
public Calculator(String calculatorName) {
this.calculatorName = calculatorName;
}
}
- 추가적으로 불변(final) 예약어는 각 선언된 위치에 따라서 아래의 기능을 가지게 됩니다.
- 클래스 단위에서 final 제어자가 선언될 경우 상속을 할 수 없게 됩니다.
- 필드 단위에서 final 제어자가 선언될 경우 값을 변경 할 수 없게 됩니다.
- 메서드 단위에서 final 제어자가 선언될 경우 오버라이딩을 할 수 없게 됩니다.
상수(Constant)
- 상수는 설정된 값이 절대 변하지 않으면서 어디서나 쓰일 수 있는 값을 뜻합니다.
- 상수는 static final 두 예약어를 붙여서 선언합니다.
- 선언된 상수는 인스턴스 생성 없이 클래스로 접근하여 바로 사용할 수 있습니다.
- 상수는 모든 문자를 대문자로 쓰고 단어 사이를 언더바 연결하는 방식으로 사용하는 것이 관례입니다.
상수 선언 방법
// 초기값 동시에 선언
static final 타입 상수이름 = 초기값;
// 정적 블럭을 이용한 대입
static final 타입 상수이름;
static {
상수이름 = 초기값;
}
상수 선언 예시
// 구체의 표면적을 저장하는 클래스
public class Sphere {
static final double PI = 3.14159;
static final double DIAMETER = 200;
static final double SURFACE_AREA;
// SURFACE_AREA 초기값 계산 후 선언
static {
SURFACE_AREA = 4 * PI * (DIAMETER / 2) * (DIAMETER / 2);
}
}