Menu

자바 접근 제어자: public, private, protected, default

자바의 네 가지 접근 수준 - public, private, protected, package-private - 이 다른 코드가 무엇을 보고 건드릴 수 있는지 어떻게 제어하는지 살펴봅니다.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

누가 당신의 코드를 건드릴 수 있는가

접근 제어자는 클래스, 필드, 메서드, 생성자 앞에 붙는 키워드로, 그 밖에 누가 그것을 사용할 수 있는지를 결정합니다. 이는 캡슐화의 토대입니다. 클래스의 어수선한 내부를 숨기고, 다른 코드가 호출하도록 믿고 맡기는 부분만 노출하는 것입니다.

자바에는 가장 열린 것에서 가장 닫힌 것까지 네 가지 수준이 있습니다. public, protected, default(키워드가 아예 없음), private입니다. 이것들을 제대로 고르면 클래스는 나중에 안전하게 변경할 수 있게 됩니다. 외부의 어떤 것도, 유지하겠다고 약속한 적 없는 세부 사항에 의존하지 않기 때문입니다.

private: 클래스 안에서만 보임

private은 가장 엄격한 수준입니다. private 멤버는 같은 클래스 안에 작성된 코드만 건드릴 수 있습니다. 하위 클래스도, 같은 패키지의 다른 클래스도, 그 누구도 안 됩니다. 당신의 필드 대부분이 속해야 할 곳이 바로 여기입니다.

balanceprivate이므로 그것을 바꾸는 유일한 방법은 음수 금액을 거부하는 deposit을 통하는 것입니다. 만약 balancepublic이었다면 어떤 코드든 account.balance = -9999라고 써서 검사를 완전히 건너뛸 수 있었을 것입니다. 그 검사야말로 필드를 숨기는 목적 전부입니다.

main에서 account.balance = 500;의 주석을 풀어 보세요. balance has private access in BankAccount라는 컴파일 오류가 납니다.

public: 어디서나 보임

public은 정반대 극단입니다. 어디에 있는 누구든 그 멤버를 사용할 수 있습니다. 다른 코드가 호출하도록 의도된 메서드 이름은 보통 public입니다. 다른 패키지에서 도달할 수 있어야 할 때는 클래스 자체도 마찬가지입니다.

흔한 패턴 - 때로는 클래스의 공개 API라고도 불리는 것 - 은 private 필드, public 메서드입니다. 필드는 다른 누구도 건드려서는 안 되는 상태를 담고, 메서드는 드나드는 통제된 문입니다. 위의 getBalancedeposit이 바로 이것입니다.

default(package-private): 키워드가 아예 없음

아무 제어자도 쓰지 않으면 default 접근, 다른 말로 package-private를 얻습니다. 그 멤버는 같은 패키지의 모든 클래스에는 보이고 그 밖의 모든 것에는 보이지 않습니다. 이 수준에는 키워드가 없습니다. 키워드의 부재 그 자체가 곧 수준입니다.

class Invoice {       // 제어자 없음 -> 이 패키지 안에서만 보임
    int amount;       // 제어자 없음 -> package-private 필드
}

이것은 많은 초보자를 함정에 빠뜨립니다. public을 빠뜨린다고 해서 무언가가 private이 되는 것이 아니라 package-private가 됩니다. 비밀로 두려고 했던 필드도 우연히 같은 패키지에 있는 어떤 클래스든 여전히 완전히 읽고 쓸 수 있습니다. 정말로 숨기고 싶다면 private을 명시적으로 써야 합니다.

default 접근은 한 패키지의 구현 세부 사항인 헬퍼 클래스에 정말로 유용합니다. 그것들을 내보내지는 않지만, 패키지 안에서 협력하는 클래스들은 여전히 자유롭게 사용할 수 있습니다.

protected: 패키지에 더해 하위 클래스

protected는 default보다 한 단계 더 느슨합니다. protected 멤버는 default가 보이는 모든 곳(같은 패키지)에서 보이고, 게다가 하위 클래스에서도 보입니다. 다른 패키지에 있는 하위 클래스에서도요. 당신의 클래스를 확장하는 클래스와는 공유하고 싶지만 온 세상과는 공유하고 싶지 않은 것들을 위해 설계되었습니다.

Dognamesound()에 접근하는 것은 그것들이 protected이고 Dog가 하위 클래스이기 때문입니다. 하위 클래스도 아니고 패키지에도 없는 외부 코드는 여전히 그것들을 건드릴 수 없습니다. 확장되도록 의도된 클래스를 설계할 때는 protected에 손을 뻗으세요. 그렇지 않으면 private을 선호하세요.

네 가지 수준 한눈에 보기

가장 제한적인 것에서 가장 열린 것까지, 전체 그림은 다음과 같습니다.

제어자같은 클래스같은 패키지하위 클래스(다른 패키지)어디서나
private아니오아니오아니오
default아니오아니오
protected아니오
public

간단한 경험칙: private으로 시작하고, 무언가가 정말로 더 넓은 접근을 필요로 할 때만 느슨하게 하라. 다른 코드가 어떤 멤버에 의존하기 시작한 뒤에 접근을 좁히는 것보다, 나중에 접근을 넓히는 편이 훨씬 쉽습니다.

클래스 자체에 붙는 제어자

접근 제어자는 멤버뿐 아니라 클래스에도 적용됩니다. 다만 최상위 클래스(다른 클래스 안에 중첩되지 않은 것)는 public이거나 default일 수만 있습니다. 최상위 privateprotected 클래스는 작성할 수 없습니다.

public class Order { ... }   // 어느 패키지에서든 도달 가능
class LineItem { ... }       // default - 이 패키지만 볼 수 있음

public 최상위 클래스는 그 이름을 딴 파일(Order.java)에 있어야 합니다. 반면 중첩 클래스는 네 가지 제어자를 모두 사용할 수 있습니다. 위 예제들이 내부 클래스를 private이나 default로 표시할 수 있었던 이유가 바로 그것입니다. 한 가지 미묘한 점: package-private 타입을 반환하는 public 메서드는 외부 호출자에게 그리 유용하지 않으니, 공개 표면을 일관되게 유지하세요.

다음: 정적 멤버

지금까지 여기의 모든 필드와 메서드는 인스턴스에 속했습니다. new로 객체를 만든 뒤 그 위에서 메서드를 호출했지요. 하지만 때로는 값이나 동작이 클래스 전체에 속해 모든 인스턴스가 공유하기도 합니다. 예를 들어 객체가 몇 개 존재하는지 세는 카운터 같은 것이죠. 바로 그것을 위한 것이 static 키워드이며, 다음에 다룹니다.

자주 묻는 질문

자바의 네 가지 접근 제어자는 무엇인가요?

public, private, protected, 그리고 default(키워드 없음, package-private라고도 함)입니다. public은 어디서나 보이고, private은 같은 클래스 안에서만, protected는 같은 패키지에 더해 하위 클래스에서, default는 같은 패키지 안에서만 보입니다.

자바에서 public과 private의 차이는 무엇인가요?

public은 어디에 있든 어떤 코드든 그 멤버에 접근할 수 있다는 뜻입니다. private은 같은 클래스 안의 코드만 접근할 수 있다는 뜻으로, 하위 클래스나 다른 클래스는 아예 볼 수조차 없습니다. 보통 필드는 private으로 두고 public 메서드를 통해 노출합니다.

자바 필드에 접근 제어자가 없으면 무엇을 의미하나요?

키워드가 없으면 default(package-private) 접근을 의미합니다. 그 멤버는 같은 패키지의 모든 클래스에는 보이지만 그 밖에서는 보이지 않습니다. public보다는 엄격하고 private보다는 느슨합니다. 실수로 빠뜨리기 쉬우니 의도적으로 다루세요.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기