제어자는 클래스, 메서드, 혹은 변수 선언부 앞에 붙어서 사용하며 부가적인 의미를 부여하는 역할을 합니다. 제어자는 접근 제어자와 그 외 제어자, 이렇게 크게 2가지로 나눌 수 있습니다.
- 접근 제어자: 멤버 또는 클래스에 사용되어, 해당하는 멤버 혹은 클래스를 외부에서 접근하지 못하도록 제어하는 역할
- public: 접근 제한이 전혀 없어 어디서든 접근가능
- protected: 같은 패키지 내, 혹은 다른 패키지의 자손 클래스에서 접근가능
- default: 같은 패키지 내에서만 접근가능
- private: 같은 클래스 내에서만 접근가능
- 그 외: static, final, abstract, volatile, transient, native, synchronized, strictfp
위의 여러 가지 제어자들 중, static과 final에 대해서 자세히 알아보겠습니다.
static
static은 '클래스의', '공통적인'이라는 의미를 내재하고 있습니다. 따라서 인스턴스에 관계없이 모두 같은 값을 가질 수 있습니다. 즉, 인스턴스끼리 공유하는 값이라고 할 수 있겠죠.
static이 붙을 수 있는 곳은 멤버변수, 메서드, 초기화 블록이 있습니다.
초기화 블록 및 static 관련 사항은 아래 포스팅에서 더 자세히 나와있으니 참고하세요!
https://silver-programmer.tistory.com/29
1. static (멤버) 변수
- 해당 클래스의 모든 인스턴스에서 공통적으로 사용하는 변수
- < 클래스. 변수명>으로 접근하여 인스턴스를 생성하기 전에도 사용 가능한 변수
2. static 메서드
- 해당 클래스를 상속한 자식 클래스는 이 메서드 오버라이딩 불가
- static 메서드 내에서는 인스턴스 변수 사용 불가
- 인스턴스 메서드보다 호출되는 속도가 빠르므로 인스턴스 변수를 사용하지 않는 메서드는 static을 붙이자.
3. static 초기화 블록
- 클래스가 메모리에 로딩될 때 단 한 번만 수행
- 주로 static 변수를 초기화하는 데 사용
추가로, 메서드에 static과 abstract를 함께 사용할 수 없습니다. static메서드는 몸통이 있는 메서드에만 사용할 수 있는데 abstract 메서드는 몸통이 없는 메서드이기 때문입니다.
final
final은 '마지막의', '변경될 수 없는'의 의미를 내재하고 있고, 거의 모든 곳에서 사용할 수 있습니다.
final이 붙을 수 있는 곳은 클래스, 메서드, 멤버변수, 지역변수가 있습니다.
1. final 클래스
- 변경될 수 없는 클래스로, 상속 불가 (다른 클래스의 조상이 될 수 없다.)
2. final 메서드
- 변경될 수 없는 메서드로, 오버라이딩으로 재정의 불가
- final 메서드에는 private을 별도로 붙일 필요가 없습니다. 어차피 오버라이딩이 불가능하므로 final 하나만으로도 의미 충분하기 때문입니다.
3. final 변수
- 변경될 수 없는 값으로, 상수
- final이 붙은 인스턴스 변수일 경우에는 생성자를 통해 처음에 한 번 초기화 가능 ==> 인스턴스마다 다른 값을 가질 수 있지만, 한 번 설정되면 각 인스턴스 내에서 변경이 불가
추가로, 클래스에 abstract과 final은 함께 사용할 수 없습니다. final은 클래스가 확장 불가능하다는 의미이고 abstract은 상속을 통해 구현이 완료되어야 한다는 의미이기 때문에 서로 대립되는 관계이기 때문이죠.
아래는 static과 final을 이용한 예제코드입니다.
class Animal {
final int size, legCount; // final 변수
static int count; // 클래스 변수
static boolean start; // 클래스 변수
static {
start = true;
} // static 초기화 블럭
{
count++;
} // 인스턴스 초기화 블럭
Animal(int size, int legCount) {
this.size = size;
this.legCount = legCount;
}
void makeSound() {
System.out.printf("My Size is %d. I have %d legs", size, legCount);
}
}
위에서 static 초기화 블록을 이용해 start 변수를 true로 초기에 한 번 실행합니다. 그리고 final 형 변수를 생성자를 통해 초기화해 줍니다. 이 변수는 후에 접근하여 변경이 불가능합니다. 위 클래스의 객체를 만들어서 아래와 같이 호출하면 3개 객체가 생성됨을 확인할 수 있습니다.
if (Animal.start) { // 클래스 변수 접근
while (Animal.count < 3) {
Animal animal = new Animal(30, 4);
// animal.legCount = 2; 변경 불가
animal.makeSound();
}
}
'Java' 카테고리의 다른 글
다형성(Polymorphism) (2) | 2023.10.15 |
---|---|
추상클래스(Abstract)과 인터페이스(Interface) (0) | 2023.10.15 |
JVM의 메모리 구조 (0) | 2023.10.14 |
가변인자(varargs) (0) | 2023.10.14 |
자바의 변수 (종류 및 초기화) (0) | 2023.10.14 |