핵심 개념 : 접근 제한자는 클래스, 필드, 생성자, 메서드에 대한 접근 권한을 제어하여 객체의 무결성을 유지한다. 4가지 수준이 있다: public, protected, default, private.
| 접근 제한자 | 적용 대상 | 접근 범위 |
| public | 클래스, 필드, 생성자, 메서드 | 제한 없음 (모든 곳에서 접근 가능) |
| protected | 필드, 생성자, 메서드 | 같은 패키지 + 자식 클래스 |
| (default) | 클래스, 필드, 생성자, 메서드 | 같은 패키지 |
| private | 필드, 생성자, 메서드 | 클래스 내부만 |
💡 default는 키워드가 아니라 접근 제한자를 생략한 상태를 말한다.
넓음 ←──────────────────────────────→ 좁음
public > protected > default > private
public class A { } // public: 모든 패키지에서 사용 가능
class B { } // default: 같은 패키지에서만 사용 가능
| 클래스 선언 | 같은 패키지 | 다른 패키지 |
public class A | ✅ 가능 | ✅ 가능 |
class B (default) | ✅ 가능 | ❌ 불가능 |
// package1/A.java
package package1;
class A { } // default 접근 제한
// package1/B.java
package package1;
public class B {
A a; // ✅ 같은 패키지 → 접근 가능
}
// package2/C.java
package package2;
public class C {
A a; // ❌ 다른 패키지 → 컴파일 에러
B b; // ✅ public 클래스 → 접근 가능
}
public class ClassName {
public ClassName() { } // 모든 곳에서 객체 생성 가능
ClassName() { } // 같은 패키지에서만 객체 생성 가능
private ClassName() { } // 클래스 내부에서만 객체 생성 가능
}
| 생성자 | 클래스 내부 | 같은 패키지 | 다른 패키지 |
| public | ✅ | ✅ | ✅ |
| default | ✅ | ✅ | ❌ |
| private | ✅ | ❌ | ❌ |
public class A {
public A(boolean b) { } // public 생성자
A(int i) { } // default 생성자
private A(String s) { } // private 생성자
}
// 같은 패키지/B.java
class B {
A a1 = new A(true); // ✅ public 생성자
A a2 = new A(1); // ✅ default 생성자
A a3 = new A("hi"); // ❌ private 생성자 (컴파일 에러)
}
// 다른 패키지/C.java
class C {
A a1 = new A(true); // ✅ public 생성자
A a2 = new A(1); // ❌ default 생성자 (컴파일 에러)
A a3 = new A("hi"); // ❌ private 생성자 (컴파일 에러)
}
public class A {
public int field1; // public 필드
int field2; // default 필드
private int field3; // private 필드
public void method1() { } // public 메서드
void method2() { } // default 메서드
private void method3() { } // private 메서드
}
| 위치 | public | default | private |
| 클래스 내부 | ✅ | ✅ | ✅ |
| 같은 패키지 | ✅ | ✅ | ❌ |
| 다른 패키지 | ✅ | ❌ | ❌ |
// 같은 패키지/B.java
class B {
void method() {
A a = new A();
a.field1 = 1; // ✅ public
a.field2 = 1; // ✅ default
a.field3 = 1; // ❌ private (컴파일 에러)
a.method1(); // ✅ public
a.method2(); // ✅ default
a.method3(); // ❌ private (컴파일 에러)
}
}
// 다른 패키지/C.java
class C {
void method() {
A a = new A();
a.field1 = 1; // ✅ public
a.field2 = 1; // ❌ default (컴파일 에러)
a.field3 = 1; // ❌ private (컴파일 에러)
a.method1(); // ✅ public
a.method2(); // ❌ default (컴파일 에러)
a.method3(); // ❌ private (컴파일 에러)
}
}
public class A {
private int field;
private void method() { }
public A() {
this.field = 1; // ✅ private 필드도 클래스 내부에서는 접근 가능
this.method(); // ✅ private 메서드도 클래스 내부에서는 접근 가능
}
}
💡 중요: 클래스 내부에서는 접근 제한자의 영향을 받지 않는다.
클래스 같은 다른
내부 패키지 패키지
public ✅ ✅ ✅
protected ✅ ✅ ✅(자식만)
default ✅ ✅ ❌
private ✅ ❌ ❌
| 요소 | public | protected | default | private |
| 클래스 | ✅ | ❌ | ✅ | ❌ |
| 필드 | ✅ | ✅ | ✅ | ✅ |
| 생성자 | ✅ | ✅ | ✅ | ✅ |
| 메서드 | ✅ | ✅ | ✅ | ✅ |
✅ public → 외부에 공개할 API
✅ protected → 상속 관계에서만 공유
✅ default → 같은 패키지 내에서만 공유
✅ private → 클래스 내부에서만 사용 (정보 은닉)
public class Person {
private String name; // 외부 접근 차단
public String getName() { // public getter로 간접 접근 허용
return name;
}
public void setName(String name) { // public setter로 간접 수정 허용
this.name = name;
}
}
🔒 정보 은닉: 필드는 private으로 감추고, getter/setter로 간접 접근하는 것이 안전하다.