클래스, 변수, 메서드의 선언부에 사용되어 부가적인 의미를 부여한다.
제어자는 크게 접근 제어자와 그 외에 제어자로 나뉜다.
==접근 제어자==
public, protected, default, private
==그 외 제어자==
static, final, abstract, native, transient, synchronized,
volatile, strictfp
접근제어자는 단 하나만 사용할 수 있다.public class Static {
// 클래스 변수 : 인스턴스 생성없이 사용 가능
static int x = 100, y = 200;
// 클래스 초기화 블럭 : static변수의 복잡한 초기화 수행
public Static() {}
// static메서드 : 인스턴스 생성없이 호출 가능
static int add(int x, int y) {
return x + y;
}
public static void main(String[] args) {
System.out.println(Static.add(x, y));
}
}
// 클래스앞에 final이 붙으면 다른 클래스의 조상이 될 수 없다.
final class Final {
// 변수 앞에 final이 붙으면 상수
final int X = 100;
// final로 지정된 메서드는 오버라이딩 불가
final int getX() {
return X;
}
}
public class Card {
final int WIDTH, HEIGHT;
// 생성자에서 매개변수를 받아 상수 초기화 진행
public Card(int w, int h) {
WIDTH = w;
HEIGHT = h;
}
}
public class CardTest {
public static void main(String[] args) {
Card card = new Card(50, 50);
// card.WIDTH = 60; Error : 상수는 값 변경 불가
}
}
상수를 선언함과 동시에 초기화를 진행한다면
해당 클래스에 모든 인스턴스는 동일한 상수값을 가지게 된다.
해당 클래스에서 다른 상수 값을 가지고 있는 인스턴스를
만들고 싶을 경우 상수를 생성자에서 초기화 해야한다.
추상의, 미완성의라는 의미에 제어자
abstract가 사용될 수 있는 곳 : 클래스, 메서드
abstract class AbstractTest{ // 추상클래스
abstract void abstractMethod(); // 추상메서드
}
멤버 or 클래스에 사용되어 외부로부터 접근을 제한한다.
접근 제어자가 사용될 수 있는 곳 : 클래스, 멤버변수, 메서드, 생성자
클래스에는 public과 default만 사용할 수 있다.
멤버변수와 메서드에는 접근제어자 4개를 모두 사용할 수 있다.
외부에서의 직접적인 접근을 막는 것접근제어자를 이용해서 멤버변수는 private으로 해서 내부에 감춘다.
메서드는 public으로 해서 외부에 노출시킴으로 같은 클래스에 정의된
멤버들끼리는 서로 자유롭게 접근하고 외부에서는 메서드를 통해서만
멤버변수에 접근할 수 있는 구조로 만든다.
외부에서는 객체의 노출된 public 메서드만 호출이 가능하고
실제 내부가 어떻게 되어 있는지 알 수 없다.
public class Time {
private int hour, minute, second;
// 해당 멤버변수들은 외부클래스에서 직접접근 불가
public Time(int h, int m, int s) {
setTime(h, m, s);
}
public void setTime(int h, int m, int s) {
if(s >= 60 ) {
m++;
s -= 60;
}
if(m >= 60) {
h++;
m -= 60;
}
if(h >= 24) {hour = 0;}
this.hour = h;
this.minute = m;
this.second = s;
}
public void setMinute(int m) {
minute += m;
if(minute >= 60) {
hour++;
minute -= 60;
if(hour >= 24) {
hour = 0;
}
}
}
public void getTime() {
System.out.println(hour + " : " + minute + " : " + second);
}
}
public class TimeTest {
public static void main(String[] args) {
Time t1 = new Time(23, 59, 59);
// t1.hour = 546546; Error : private로 외부에 접근을 제한하고 있다.
t1.setMinute(40);
t1.getTime();
}
}
일반적으로 생성자의 접근 제어자는 클래스의 접근 제어자와 동일하다.
필요에 따라서 생성자의 접근 제어자를 사용하여
인스턴스의 생성을 제한할 수 있다.
생성자의 접근제어자가 private인 경우 다른 클래스의 조상이 될 수 없다.
자손클래스의 인스턴스를 생성하면 조상의 생성자를 호출하는데
조상의 생성자가 private이라서 호출할 수 없기 때문
클래스 앞에 final을 사용하여 상속을 통해 확장할 수 없는
클래스라는 것을 알려주는 것이 좋다.
final class Singleton {
// 내부적으로 인스턴스를 생성해서 접근제어자를 private로 감춘다.
private static Singleton s = new Singleton();
// 생성자의 접근제어자를 private로 지정할 경우
// 연산자 new를 통해 인스턴스를 생성할 수 없다.
private Singleton() {}
// 메서드에 접근제어자를 public을 사용함으로써 생성된 인스턴스에 접근한다.
// 외부에서 인스턴스를 생성할 수 없기 때문에 static메서드로 정의
public static Singleton getInstance() {
// 참조변수s가 아무것도 참조하고 있지 않다면 인스턴스를 생성하여 s가 참조
if(s == null) {
s = new Singleton();
}
// 참조변수 s를 return한다.
return s;
}
}
public class SingletonTest {
public static void main(String[] args) {
// 생성자의 접근제어자가 private라서
// new 를 통한 인스턴스 생성 불가
// Singleton s = new Singleton();
// static메서드를 통해 이미 생성된 인스턴스를 참조한다.
Singleton s1 = Singleton.getInstance();
}
}