제어자는 클래스, 변수 또는 메서드의 선언부에 함께 사용되어 부가적인 의미를 부여한다.
접근 제어자: public, protected, default, private
그 외: static, final, native, transient, synchronized, volatile, strictfp
제어자는 클래스나 멤버 변수와 메서드에 주로 사용되며 하나의 대상에 대해 여러 제어자를 조합하여 사용 가능하다. 단, 접근 제어자는 한 번에 네 가지 중 하나만 선택할 수 있다.
static이 사용될 수 있는 곳 - 멤버변수, 메서드, 초기화 블럭
[final이 사용될 수 있는곳]
final class FinalTest { // 조상이 될 수 없는 클래스
final int MAX_SIZE = 10; // 값을 변경할 수 없는 멤버 변수 (상수)
final void getMaxSize() { // 오버라이딩 할 수 없는 메서드 (변경 불가)
final int LV = MAX_SIZE; // 값을 변경할 수 없는 지역 변수 (상수)
return MAX_SIZE;
}
}
인스턴스 변수의 경우 생성자에서 초기화 되도록 할 수 있다.
class Card {
final int NUMBER; // 상수지만 선언과 함께 초기화 하지 않고 생성자에서 단 한 번 초기화 할 수 있다.
Card(int num) {
NUMBER = num;
}
}
'미완성'의 의미를 가진다. 메서드의 선언부만 작성하고 실제 수행 내용은 구현하지 않은 추상 메서드를 선언하는데 사용된다.
[abstract가 사용될 수 있는 곳]
추상 클래스는 아직 완성되지 않은 메서드가 존재하는 미완성 설계도이므로 인스턴스를 생성할 수 없다.
abstract class AbstractTest { // 추상 클래스 (추상 메서드를 포함한 클래스)
abstract void move(); // 추상 메서드 (구현부가 없는 메서드)
}
💡 드물지만 추상 메서드가 없는 완성된 클래스도 추상 클래스로 만드는 경우도 있다. (예를 들어, WindowAdapter) 이 클래스 자체로는 쓸모가 없지만, 다른 클래스가 이 클래스를 상속 받아서 일부의 원하는 메서드만 오버라이딩해도 된다는 장점이 있다.
제어자 | 같은 클래스 | 같은 패키지 | 자손 클래스 | 전체 |
public | O | O | O | O |
protected | O | O | O | X |
(default) | O | O | X | X |
private | O | X | X | X |
[접근 제어자를 사용하는 이유]
[사용 가능한 제어자]
❗ 주의 사항
1. 메서드에 static과 abstract를 함께 사용할 수 없다.
-> static 메서드는 몸통이 있는 메서드에만 사용할 수 있다.
2. 클래스에 abstract와 final을 동시에 사용할 수 없다.
-> 클래스에 사용되는 final은 클래스를 확장할 수 없다는 의미이고 abstract는 상속을 통해서 완성되어야 한다는 의미이므로 서로 모순되기 때문이다.
3. abstract 메서드의 접근 제어자가 private일 수 없다.
-> abstract 메서드는 자손클래스에서 구현해주어야 하는데 접근 제어자가 pricate이면, 자손 클래스에서 접근할 수 없기 때문이다.
4. 메서드에 private과 final을 같이 사용할 필요는 없다.
-> 접근 제어자가 pricate인 메서드는 오버라이딩 될 수 없기 때문에 둘 중 하나만 사용해도 의미가 충분하다.