제어자 ( modifier)
: 클래스, 변수, 메서드의 선언부에 함께 사용되어 부가적인 의미를 부여한다.
제어자의 종류는 접근제어자와 그 외의 제어자로 나눌 수 있다.
접근 제어자 : public, protected, default , private
그 외 : static , final, abstract, native, transient, synchronized, volatile, strictfp
static : 공통적인, 클래스의
static 은 '클래스의' 또는 '공통적인'의 의미를 가지고 있다.
클래스변수(static변수)는 모든 인스턴스가 공유하기 때문에, 인스턴스에 관계없이 같은 값을 갖는다.
- static 이 붙은 멤버변수와 메서드는 인스턴스를 생성하지 않고도 사용할 수 있다.
- 인스턴스 메서드와 static메서드의 근본적인 차이는 메서드 내에서 인스턴스 멤버를 사용하는가의 여부에 있다.
제어자 | 대상 | 의미 |
static | 멤버변수 | - 모든 인스턴스에 공통적으로 사용되는 클래스변수가 된다. - 클래스변수는 인스턴스를 생성하지 않고도 사용 가능하다. - 클래스가 메모리에 로드될 때 생성된다. |
메서드 | - 인스턴스를 생성하지 않고도 호출이 가능한 static 메서드가 된다. - static 메서드 내에서는 인스턴스 멤버들을 직접 사용할 수 없다. |
fianl : 마지막의, 변경될 수 없는
- 변수에 사용되면 값을 변경할 수 없는 상수가 되며,
- 메서드에 사용되면 오버라이딩을 할 수 없게되고,
- 클래스에 사용되면 자신을 확장하는 자손클래스를 정의하지 못하게 된다.
제어자 | 대상 | 의미 |
final | 클래스 | 변경될 수 없는 클래스, 확장될 수 없는 클래스가 된다. 그래서 final로 지정된 클래스는 다른 클래스의 조상이 될 수 없다. |
메서드 | 변경될 수 없는 메서드, final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다. | |
멤버변수 | 변수 앞에 final이 붙으면, 값을 변경할 수 없는 상수가 된다. | |
지역변수 |
생성자를 이용한 final멤버 변수의 초기화
- 클래스 내에 매개변수를 갖는 생성자를 선언하여, 인스턴스를 생성할 때 final이 붙은 멤버변수를 초기화하는데 필요한 값을 생성자의 매개변수로부터 제공받는 것이다.
- 이 기능을 활용하면 각 인스턴스마다 final이 붙은 멤버변수가 다른 값을 갖도록 하는것이 가능하다.
- 예를 들어, 각 카드마다 다른 종류와 숫자를 갖지만, 일단 카드가 생성되면 카드의 값이 변경되면 안되는 경우 이를 활용한다.
abstract : 추상의, 미완성의
메서드의 선언부만 작성하고 실제 수행내용은 구현하지 않은 추상 메서드를 선언하는데 사용된다.
클래스에 사용되어 클래스 내에 추상메서드가 존재한다는 것을 쉽게 알 수 있게 한다.
제어자 | 대상 | 의미 |
abstract | 클래스 | 클래스 내에 추상 메서드가 선언되어 있음을 의미한다. |
메서드 | 선언부만 작성하고 구현부는 작성하지 않은 추상 메서드임을 알린다. |
- 추상 클래스는 아직 완성되지 않은 메서드가 존재하는 '미완성 설계도'이므로 인스턴스를 생성할 수 없다.
- 다른 클래스가 이 클래스를 상속받아서 일부의 원하는 메서드만 오버라이딩해도 된다는 장점이 있다.
접근제어자 ( access modifier )
접근 제어자는 멤버 또는 클래스에 사용되어, 해당하는 멤버 또는 클래스를 외부에서 접근하지 못하도록 제어하는 역할을 한다.
접근 제어자가 사용될 수 있는 곳 - 클래스, 멤버변수, 메서드, 생성자
private : 같은 클래스 내에서만 접근 가능하다.
default : 같은 패키지 내에서만 접근 가능하다.
protected : 같은 패키지 내에서, 다른 패키지의 경우 자손클래스내에서 접근 가능하다.
public : 접근 제한이 전혀 없다.
제어자 | 같은 클래스 | 같은 패키지 | 다른패키지, 자손클래스 | 전체 |
public | O | O | O | O |
protected | O | O | O | X |
(default) | O | O | X | X |
private | O | X | X | X |
접근 제어자의 접근 범위가 넓은 쪽에서 좁은 쪽의 순으로 왼쪽부터 나열하면 아래와 같다.
public > protected > (default) > private
대상에 따라 사용할 수 있는 접근 제어자는 아래와 같다.
대상 | 사용가능한 접근 제어자 |
클래스 | public, (default) |
메서드 | public, protected, (default), private |
멤버변수 | |
지역변수 | X |
접근 제어자를 사용하는 이유는
- 외부로부터 데이터를 보호하기 위해서
- 외부에는 불필요한, 내부적으로만 사용되는, 부분을 감추기 위해서 (캡슐화) 이다.
멤버변수를 private 이나 protected로 제한하고 멤버변수의 값을 읽고 변경할 수 있는 public 메서드를 제공함으로써 간접적으로 멤버변수의 값을 다룰 수 있도록 하는 것이 바람직하다.
- Time의 객체 t 는 t.hour=13 과 같이 멤버변수로의 직접적인 접근이 허가되지 않는다.
- 메서드를 통한 접근만이 허용될 뿐이다.
- 상속을 통해 확장이 예상되는 클래스라면 자손클래스에서 접근하는것이 가능하도록 하기 위해 private 대신 protected를 사용한다.
생성자의 접근제어자
- 생성자에 접근 제어자를 사용함으로써 인스턴스의 생성을 제한할 수 있다.
- 생성자의 접근 제어자를 private으로 지정하면, 외부에서 생성자에 접근할 수 없으므로 인스턴스를 생성할 수 없게 된다. 대신 내부에서 인스턴스를 생성할 수 있게 해주고 인스턴스를 생성해서 반환해주는 public메서드를 제공한다. 이로써 외부에서 이 클래스의 인스턴스를 사용하도록 할 수 있다. 이 메서드는 pulic인 동시에 static이어야 한다.
class Singleton{
private Singleton(){...}
// 인스턴스가 미리 생성되어 있어야 하므로 static이어야 한다.
private static Singleton s= new Singleton();
// 인스턴스를 생성하지 않고도 호출할 수 있어야 하므로 static이어야 한다.
public static Singleton getInstance(){
return s;
}
}
- 생성자를 통해 직접 인스턴스를 생성하지 못하게 하고 public 메서드를 통해 인스턴스에 접근하게 함으로써 사용할 수 있는 인스턴스의 개수를 제한할 수 있다.
- 생성자가 private인 클래스는 다른 클래스의 조상이 될 수 없다. 왜냐하면, 자손 클래스의 인스턴스를 생성할 때 조상클래스의 생성자를 호출해야만 하는데, 생성자의 접근제어자가 private이면 자손클래스에서 호출하는것이 불가능하기 때문이다.
- 그래서 클래스 앞에 final을 추가하여 상속할 수 없는 클래스라는 것을 알리는 것이 좋다.
//상속할 수 없는 클래스라는 것을 알리기 위해 final 사용
public final class Math{
private Math(){...}
}
제어자의 조합
제어자가 사용될 수 있는 대상을 중심으로 정리한 제어자.
대상 | 사용 가능한 제어자 |
클래스 | public, (default) , final, abstract |
메서드 | 모든 접근 제어자, final, abstract, static |
멤버변수 | 모든 접근 제어자, fianl, static |
지역변수 | final |
제어자를 조합해서 사용할 때 주의해야 할 사항
1. 메서드에 static과 abstract를 함께 사용할 수 없다.
- static메서드는 몸통이 있는 메서드에만 사용할 수 있다.
2. 클래스에 abstract과 final을 동시에 사용할 수 없다.
- 클래스에 사용되는 final은 클래스를 확장할 수 없다는 의미이고, abstract는 상속을 통해서 완성되어야 한다는 의미이므로 모순.
3. abstract메서드의 접근제어자가 private일 수 없다.
- abstract메서드는 자손클래스에서 구현해주어야 하는데 접근제어자가 private이면 자손클래스에서 접근할 수가 없다.
4. 메서드에 private과 final을 같이 사용할 필요는 없다.
- 접근제어자가 private인 메서드는 오버라이딩 될 수 없기 때문에, 둘 중 하나만 사용해도 의미가 충분하다.
'JAVA > JAVA 기본정리' 카테고리의 다른 글
추상클래스 (abstract class) / 추상 메서드 (abstract method) (0) | 2022.06.08 |
---|---|
다형성(polymorphism) (0) | 2022.06.06 |
오버라이딩(overriding) / 오버로딩 (overloading) / super / super() (0) | 2022.05.31 |
상속(inheritance) / 포함(Composite) 관계 (0) | 2022.05.31 |
열거형(Enums) (0) | 2022.05.30 |