접근제어자는 매우 중요한 개념인데 규모있는 애플리케이션을 만드는 과정에서 깊은 절망감을 경험해보지 않았다면 관념적인 개념처럼 여겨질 수 있다. 애플리케이션이 커진다는 것은 다른 말로 망가질 확률이 커진다는 의미와 같다. 특히 로직이 망가지는 첫번째 용의자는 사용자다. 즉 객체를 사용하는 입장에서 객체 내부적으로 사용하는 변수나 메소드에 접근함으로서 개발자가 의도하지 못한 오동작을 일으키게 되는 것이다.
그래서 사용자가 의도하지 않은 방법으로 내부적인 메소드의 상태(변수값)를 바꾸는 불상사를 막을 수 있는 방법으로 접근제어자를 사용할 수 있고, 사용자는 private 메소드에는 관심을 가지지 않아도 되기 때문에 더 적은 메뉴얼로 의도한 대로 사용할 수 있게하는 장점을 얻을 수 있다.

예시로 은행창구에서 고객(사용자)와 대면하는 일을 하는 직원들 public이라고 한다면
조직 안에서도 특별한 권한을 가진 사람만이 들어갈 수 있는 금고는 private이다.
아무나 금고에 들어갈 수 있다면 그 은행은 안전하지 않을 것 이다.
은행 시스템을 보호하기 위해서 두 영역을 구분하는 것처럼 객체에서는 접근제어자를 통해 영역을 분리하는 역할을 한다.
접근제어자는 객체 안에 소속되어 있는 멤버들(메소드나 변수)을
사용하는 입장에서 누가 이것을 사용할 수 있는가에 대한 권한의 차등을 주는 것을 의미한다.
접근제어자를 코드레벨에서 예시를 살펴보자
class A {
public String y() {
return "public void y()";
}
private String z() {
return "private void y()";
}
public String x() {
return z();
}
}
public class Access {
public static void main(String[] args) {
A a = new A();
System.out.println(a.y());
//System.out.println(a.z()); //에러발생
System.out.println(a.x());
}
}
Access 클래스는 A 클래스를 사용하고 있다.
y메소드를 호출하는 경우에는 public void y()가 정상적으로 출력되지만
z메소드를 호출하는 경우에는 compile-time error가 발생한다.
두 메소드는 시그니처 맨 앞의 접근제어자가 public이냐 private이냐의 차이가 있는데
public인 경우에는 누구든지 클래스를 호출해서 사용할 수 있지만
private인 경우에는 소속된 클래스 내부에서만 사용 가능하고 클래스 바깥쪽의
외부 클래스에서는 사용할 수 없기 때문이다.
그런데 x메소드의 경우에는 같은 클래스에 소속되어 있는 z메소드를 사용할 수 있기 때문에
z를 직접적으로 호출할 수 없어도 x를 통해 z를 호출할 수 있다는 것을 알 수 있다.
접근제어자는 메소드 뿐만 아니라 변수에도 적용하여 원하는 규제를 할 수 있다.
class Example {
public int publicVar;
private int privateVar;
protected int protectedVar;
int defaultVar; // default 접근 제어자
}
제어자(Modifier)는 클래스, 필드, 메서드, 생성자에 부가적인 의미를 부여하는 키워드이다.
자바의 클래스 맴버 접근제어자 키워드는 4개가 있다.
public, protected, default, private

| 접근제어자 | 접근제한범위 |
|---|---|
| public | 접근제한 없음 |
| protected | 동일 패키지 + 다른 패키지의 하위 클래스에서만 접근가능 |
| default | 동일 패키지내에서만 접근가능 |
| private | 동일 클래스에서만 접근가능 |
접근제어자를 사용하면 클래스 외부로의 불필요한 데이터 노출을 방지할 수 있다.(data hiding)
외부로부터 데이터가 임의로 변경되지 않도록 막을 수 있다.
접근제어자를 명시하지 않으면 기본 설정인 default 접근제어자가 된다.
| 같은 클래스 | 같은패키지 | 다른패키지서브클래스 | 관계없음(다른패키지,상속도없음) | |
|---|---|---|---|---|
| public | O | O | O | O |
| protected | O | O | O | X |
| default | O | O | X | X |
| private | O | X | X | X |
같은패키지에 있는 클래스는 인스턴스를 만들어서 접근하는 경우나 상속 관계를 이용해서 접근할 때도 private을 제외하고는 모두 접근이 가능하다.

다른패키지에 있는 클래스를 인스턴스 시켜서 접근하는 경우에는 public만 가능하지만(protected 접근 불가)
예외적으로 protected는 다른 패키지에 있는 클래스를 상속받아 상위클래스에 있던 메소드에도 접근이 가능하다.

클래스도 접근 제어자가 있고 키워드는 2개이다.
public, default
public class PublicCalss{}
class DefaultClass{}
클래스의 접근 제어자는 패키지와 관련된 개념으로 접근제어자가 public인 클래스는 다른 패키지의 클래스에서도 사용할 수 있고, default인 경우에는 같은 패키지에서만 사용 가능하다.
따라서 다른 패키지에 소속된 클래스에서 패키지를 로드(import)하여 사용하려면 public 클래스여야 할 것이다.
그리고 public 클래스가 포함된 소스코드는 클래스명과 소스코드 파일명(코드파일명.java)이 같아야하는 중요한 제약사항이 있다. 즉 하나의 소스코드 안에는 하나의 public 클래스가 존재할 수 있다는 의미이다.
static, final, abstract, native...
| 기타제어자 | 접근제한범위 |
|---|---|
| Static | Static변수와 Static메소드를 만들 수 있다. (클래스맴버) |
| final | final변수와 final메소드를 만들 수 있다. 처음 정의된 상태가 변하지 않는다. (고정적) |
| abstract | 추상클래스와 추상메소드를 만들 수 있다. |
| native | 자바가 아닌 언어(보통 C나 C++)로 구현한 후 자바에서 사용하려고 할 때 이용하는 키워드이다. |
기타제어자는 여러개 사용할 수 있다. 더 많은 종류들이 있으니 기회가 되면 추가해야겠다.