제어자(Modifier)
1. Introduction
제어자는 클래스, 변수 혹은 메서드의 선언부에 함께 사용되어 부가적인 의미를 부여한다.
2. static
static은 멤버변수, 메서드, 초기화 블럭에 사용될 수 있다. static이 의미하는 것은 아래와 같다.
-
Member variables
- 모든 인스턴스에서 공통적으로 사용되는 클래스 변수가 된다.(전역 변수처럼)
- 클래스 변수는 인스턴스를 생성하지 않고 사용가능하다.
- 클래스가 메모리에 로드될 때 생성된다.
- Method
- 인스턴스를 생성하지 않아도 호출이 가능한 static 메서드를 생성할 때 사용
- static 메서드 내에서는 일반적인 멤버 변수를 사용할 수 없다.
3. final
final은 변경될 수 없는 의미를 가지고 있다. 변수에 사용되면 변경할 수 없는 상수(c나 c++에서의 const)가 되며, 메서드에 사용하면 Overriding을 할수 없게 되고, 마지막으로 클래스에 선언이 되면 상속을 할 수 없다.
-
Class
- 상속이 불가능 한 클래스가 된다.
-
Method
- 오버라이딩이 불가능하다.
-
Variables
- 값을 변경할 수 없는 상수가 된다.
final을 이용해서 변수를 선언 하는 경우 초기화를 동시에 수행한다. 하지만, 클래스내의 인스턴스 변수의 경우 생성자 내에서도 초기화가 가능하다.
class Test {
// final로 생성했지만 초기화를 하지 않고, 생성자에서 단 한번 초기화 가능하다.
final int num;
final String name;
Test(int num, String name) {
this.num = num;
this.name = name;
}
}
이러한 기능을 제공하는 이유는 각 인스턴스마다 final을 사용하는 변수들이 인스턴스 마다 다른 값을 가지도록 할 수 있다. 이러한 기능이 없다면 final을 사용하는 모든 변수들은 같은 값을 가져야만 할 것이다.
4. abstract
abstract 키워드는 구현되어 있지 않는 추상 메서드를 선언할 때 사용한다.
- Class : 클래스 내에 추상메서드가 선언되어 있음을 의미함
- Method : 선언부만 작성하고 구현부는 작성하지 않은 추상메서드를 의미함
5. 접근 제어자(Access modifier)
접근 제어자는 사용되는 멤버 혹은 클래스를 외부에서 접근하지 못하게 제한하는 역할을 수행한다. 자바에서는 접근 제어자를 사용하지 않으면 default 접근 제어자가 자동으로 선언되는 것이다. 접근 제어자가 사용가능한 위치는 클래스나 메서드 변수에 따라 다르다. 사용할 수 있는 접근 제어자는 아래의 표와 같다.
구분 |
사용 가능한 접근 제어자 |
클래스 |
public, (default) |
메서드 |
public, protected, (default), private |
멤버변수 |
|
지역변수 |
없음 |
Table 1. 대상에 따라 사용가능한 접근 제어자
각 접근 제어자의 의미는 아래와 같다.
- private : 같은 클래스(class) 내에서만 접근 가능
- default : 같은 패키지(package) 내에서만 접근 가능
- protected : 같은 패키지(package) 내에서와 다른 패키지의 자식클래스에서 접근이 가능함.
- public : 접근 제한이 없이 전부 접근 가능하다.
이러한 접근 제어자를 사용하는 이유는 클래스 내부에 선언된 데이터를 보호하기 위해서다. 즉, 객체 지향에서는 이러한 기능을 캡슐화(encapsulation)에 해당한다.
생성자의 접근 제어자
생성자에 접근 제어자를 사용함으로써 인스턴스 생성을 제한할 수 있다. 생성자를 private으로 선언하면, 외부에서 생성자에 접근할 수 없으므로 인스턴스를 생성할 수 없게 된다. 그러나 클래스 내부에서는 인스턴스를 생성할 수 있다. 이러한 기법을 이용하면 인스턴스 개수를 제한할 수 있게 된다. 디자인 패턴에서 이러한 기법을 사용하는 것을 Singleton 패턴이다. 간단히 사용하는 방법은 아래의 소스 코드 처럼 사용한다.
class Singleton {
// getInstance()에서 사용될 수 있도록 미리 인스턴스가 생성되어야 하므로 static으로 선언
private static Singleton s = new Singleton();
private Singleton() {
//...
}
public static Singleton getInstance() {
return s;
}
}
private으로 생성자를 지정하게 되면 다른 클래스에 조상이 될 수 없다. 그 이유는 자식 클래스의 인스턴스를 생성할 때 부모 클래스의 생성자를 호출해야 하는데, 생성자가 private로 선언되어 있으면 호출이 불가능하기 때문이다. 그래서 클래스 앞에 final을 더 추가 하여 상속할 수 없는 클래스라는 것을 명시해주면 좋다.