자바 Java

Java 의 접근 제어자 - public, protected, default, private 에 대해서

leexx 2023. 9. 23. 04:42

 

Java 의 접근 제어자에 대해서

Java 에는 public, protected, default, private 라는 4개의 접근 제어자가 있다. 말 그대로 접근의 범위를 제어하는 키워드 이다.

 

따라서 접근 제어자가 클래스에 붙어 있으면 해당 클래스의 접근 범위를 제어하는 것이고, 멤버변수에 붙어있다면 멤버변수의 접근 범위를 정하는 것이다.

 

  public protected default private
접근 범위 - 어디서나
- 자손 Class 내에서 
- 같은 Package 내에서
- 같은 Class 내에서 

- 자손 Class 내에서 
- 같은 Package 내에서
- 같은 Class 내에서 
-
-
- 같은 Package 내에서
- 같은 Class 내에서 
-


- 같은 Class 내에서 

protected 는 좀 헷갈렸다. 그러다가 (요기) 블로그 글 보고 좀 이해를 했다. 

 

 

예시로 알아보기

각 package 내의 xxRun.java 파일은 public static void main(String[] args) 함수가 있는 패키지 내의 메인 클래스 이다. 

.
├── Main.java
├── myDefaultPackage
│   ├── DefaultC.java
│   └── DefaultRun.java
├── myPrivatePackage
│   ├── Other.java
│   ├── PrivateC.java
│   └── PrivateRun.java
├── myProtectedPackage
│   ├── ProtectedC.java
│   └── ProtectedRun.java
└── myPublicPackage
    ├── PublicC.java
    └── PublicRun.java

 

멤버변수의 각 접근 제어자와 접근 

 

PublicC 클래스는 public 이라서 Main.java 에서 import 를 할 수 있다. 멤버변수에서 name 도 public 이라 접근이 가능하다. 하지만 isBirthday, age. dinner 는 각각 protected, default, private 이므로 다른 package 에서 접근할 수 없다. 

 

하지만 상속을 받게 되면 protected 인 isBirthday 는 접근이 가능하다.

 

Class 와 접근제어자

이렇게 class 의 앞에 접근 제어자를 붙여서 사용할 수 있다. 

 

그런데... protected 와 private 은 pubilc, default 와 달리 최상위 클래스에서 사용을 할 수 없다

 

왜 protected 와 private 은 최상위 클래스에서 사용할 수 없을까?

private 는 자기 클래스 내에서만 접근한 접근 제한자이므로, 클래스가 자기 자신만 접근할 수 있다는 것은 말이 안된다. 그래서 private 은 최상위 클래스에서 사용할 수 없다.

 

그런데 문제는 protected 였다. 보다 타이트한 default 도 최상위 클래스의 접근제어자가 될 수 있는데, protected 는 왜 안될까? 이런 저런 자료를 찾아봤다. 

 

관련한 다양한 질문과 답변들이 있었고, 내가 이해한 바로는 의미의 중복을 제거해서, 보다 탄탄한 아키텍쳐를 만들자는 것 이었다. (요기)

의미의 중복이란, default 와 public 과 의미가 중복이 되는 상황이 생기는 것을 말한다. 만약 다른 패키지의 어떤 클래스도 protected 인 클래스를 상속 받지 않는다면, default 와 다를 것이 없다. 마찬가지로 모든 패키지의 모든 class 에서 protected 인 클래스를 상속받는다면, public 과 다를 것이 없다.

 

만약 사용하고 싶다면, 내부 클래스로 만들자 

단 내부 클래스 (Inner class, Nested class) 로 만들면 사용할 수 있다. 

package myPackage;

public class MyClass {
    protected class InnerProtected {
        public String name = "Protected";
    }

    protected class InnerPrivate {
        public String name = "Private";
    }
}