-
접근제한자, 접근제어자 (public, private, protected, default) 가 뭔데? - JavaJava 2020. 6. 4. 15:12
tl;dr
public > protected > default > private
private : 속해있는 class 에서만 접근가능
default : private + 같은 패키지 안에서 접근가능
protected : default + 상속받은 클래스에도 접근가능
public : protected + 접근제한 없음
서론
접근제한자는 Java 의 기본이나 다름없지만 자세히 들여다 볼 생각하지 않고, 프로그래밍을 하였다.
상황에 맞게 사용하기 위해서 필요할 때만 찾아서 사용하다 보니 전체 구조가 틀어지고 어지럽혀지는 경험을 해본 적도 있다.
보다 더 자세히 접근제한자에 대해 알아볼 필요성을 느껴서 포스팅을 남기기로 했다.
본론
Java 의 접근제한자의 종류로는 public, private, protected 그리고 default 가 있다.
사용하는 변수나 메소드, 생성자 앞에 붙여서 해당 변수, 메소드, 생성자의 사용할 수 있는 자격을 어디까지 줄 것인지 정해 준다.
예를 들어서 설명해 보면
살고 있는 집에 도어락이 지문인식으로 되어있다고 하면, 지문등록을 내 것만 할 것인지,
가족들도 지문등록을 할 것인지 아니면 친구들이나 누구라도 들어올 수 있도록 만들어 줄 건지 하는 것이다.
이러한 접근제한자는 객체지향 ( Object-oriented Programing ) 언어 의 3대요소 캡슐화, 상속 그리고 다향성 중에서 캡슐화에 속한다.
접근제한자를 간단하게 표로 표현해 보면 다음과 같다.
제한자 \ 범위 같은 class 같은 package 상속받은 class
(다른 package)제한없음 private O default O O protected O O O public O O O O 표에 나타낸 것과 같이 private 에서 default, protected, public 으로 갈수록 점점 제한이 풀린다는 것을 알 수 있다.
예제를 보면서 어떤 얘기인지 확인해 보도록 하자.
1. private
public class OuterJ { private int a = 4; private class Inner { public Inner(){} public int e = 5; } } class SubClass extends OuterJ { SubClass() { int a = this.a; // access 불가 int e = this.new Inner().e; // access 불가 } } class Unrelated { Unrelated(OuterJ o) { int a = o.a; // access 불가 int e = o.new Inner().e; // access 불가 } }
OuterJ 클래스에 private 가 붙은 변수나 클래스 모두 같은 패키지라도 접근할 수 없다는 것을 알 수 있다.
상속을 받더라도 접근할 수 없다.
이것을 통해 private 이 붙게 되면 속해있는 class 내부를 제외하고는 절대 접근할 수 없다는 것을 알 수 있다.
즉 완전 폐쇄적인 상황에서만 사용해야 한다.
2. default
public class OuterJ { int b = 2; static class Inner2 { public Inner2(){} public int f = 6; } } class SubClass extends OuterJ { SubClass() { int b = this.b; // access 가능 int f = this.new Inner2().f; // access 가능 } } class Unrelated { Unrelated(OuterJ o) { int b = o.b; // access 가능 int f = o.new Inner2().f; // access 가능 } }
OuterJ 클래스에 아무것도 붙지 않은 변수나 클래스를 default 라고 한다.
위의 예시에서는 동일한 패키지 내에서 default 변수랑 클래스를 호출하였기 때문에 접근이 가능하다는 것을 확인할 수 있다.
표를 보면 같은 패키지내에서는 접근이 가능하다고 되어있는데
그렇다면 외부 패키지에서 호출할 때는 어떻게 되는지 확인해보자.
class SubClassJ extends OuterJ { SubClassJ() { int b = this.b; // access 불가 int f = this.new Inner2().f; // access 불가 } } class UnrelatedJ { UnrelatedJ(OuterJ o) { int b = o.b; // access 불가 int f = o.new Inner2().f; // access 불가 } }
위의 예시와 같이 외부패키지에서는 접근불가하다는 것을 알 수 있다.
이를통해 default 는 같은 패키지에서의 접근은 가능하지만 다른 패키지에서는 접근불가하다는 것을 알 수 잇다.
즉 default 는 같은 패키지내에서 사용하고 싶지만 다른 패키지에서는 사용하고 싶지 않을 때 사용하면 된다.
3. protected
public class OuterJ { protected int c = 3; protected class Inner3 { public Inner3() {} public int g = 7; } } class SubClass extends OuterJ { SubClass() { int c = this.c; // access 가능 int g = this.new Inner3().g; // access 가능 } } class Unrelated { Unrelated(OuterJ o) { int c = o.c; // access 가능 int g = o.new Inner3().g; // access 가능 } }
protected 같은 경우에는 같은 패키지 뿐만 아니라 다른 패키지에서도 경우에 따라 접근할 수 있다고 되어있었다.
위의 예시를 보면 같은 패키지에서는 접근할 수 있다는 것을 알 수 있다. 그렇다면 다른 패키지의 경우에는 어떻게 될까?
class SubClassJ extends OuterJ { SubClassJ() { int c = this.c; // access 가능 int g = this.new Inner3().g; // access 가능 } } class UnrelatedJ { UnrelatedJ(OuterJ o) { int c = o.c; // access 불가 int g = o.new Inner3().g; // access 불가 } }
위의 예시를 확인해 보면 OuterJ 클래스를 상속받은 SubClassJ 에서는 protected 에 접근이 가능하다.
하지만 상속받지 않은 UnrelatedJ 클래스에서는 protected 에 접근할 수 없다는 것을 알 수 있다.
이를 통해 같은 패키지 뿐만 아니라 다른 패키지에서도 접근할 수 있지만 상속받았을 때만 가능하다는 제한사항이 붙는 것을 알 수 있다.
즉 protected 는 다른패키지에서 상속받을 수 있게끔 만들고 싶을 때만 사용하면 된다고 할 수 있겠다.
4. public
public class OuterJ { public int d = 4; public class Inner4 { public Inner4(){} public int h = 8; } } class SubClass extends OuterJ { SubClass() { int d = this.d; // access 가능 int h = this.new Inner4().h; // access 가능 } } class Unrelated { Unrelated(OuterJ o) { int d = o.d; // access 가능 int h = o.new Inner4().h; // access 가능 } }
public 의 경우에는 접근제한없이 어떤 상황이라도 접근할 수 있다.
위의 예시와 같이 같은 패키지 뿐만 아니라, 아래와 같이 다른 패키지에서도 접근이 가능하다.
class SubClassJ extends OuterJ { SubClassJ() { int d = this.d; // access 가능 int h = this.new Inner4().h; // access 가능 } } class UnrelatedJ { UnrelatedJ(OuterJ o) { int d = o.d; // access 가능 int h = o.new Inner4().h; // access 가능 } }
이를 통해 같은 패키지 뿐만아니라 다른 패키지에서도 모든 상황에 대해 public 은 접근이 가능하다는 것을 알 수 있다.
즉 상황에 구애받지 않고 사용하고 싶을 때 public 을 붙여주면 된다.
마지막으로 접근제한자 사용 범위에 대해서 알아보도록 하자.
클래스 public, default 생성자 public, protected, default, private 멤버변수 public, protected, default, private 멤버메소드 public, protected, default, private 지역번수 접근제한자 사용 제한 (사용할 수 없음) 결론
접근제한자에 대해 알아보았다.
비교적 어렵지 않은 내용이지만, 정확한 사용법을 알아보지 않고 사용하게 되면 코드가 중구난방식이 될 수 있기 때문에 주의 해야할 필요가 있다. 그리고 Java 의 기본이 되는 내용이니 만큼 반드시 머리속에 들어가 있어야하는 부분이다.
참조
https://www.javatpoint.com/access-modifiers
https://beginnersbook.com/2013/05/java-access-modifiers/
전체코드
더보기// 같은 패키지 일 때 public class OuterJ { private int a = 1; int b = 2; protected int c = 3; public int d = 4; private class Inner { public Inner(){} public int e = 5; } class Inner2 { public Inner2() {} public int f = 6; } protected class Inner3 { public Inner3() {} public int g = 7; } public class Inner4 { public Inner4(){} public int h = 8; } } class SubClass extends OuterJ { SubClass() { int a = this.a; // access 불가 int b = this.b; // access 가능 int c = this.c; // access 가능 int d = this.d; // access 가능 int e = this.new Inner().e; // access 불가 int f = this.new Inner2().f; // access 가능 int g = this.new Inner3().g; // access 가능 int h = this.new Inner4().h; // access 가능 } } class Unrelated { Unrelated(OuterJ o) { int a = o.a; // access 불가 int b = o.b; // access 가능 int c = o.c; // access 가능 int d = o.d; // access 가능 int e = o.new Inner().e; // access 불가 int f = o.new Inner2().f; // access 가능 int g = o.new Inner3().g; // access 가능 int h = o.new Inner4().h; // access 가능 } }
// 다른 패키지 일 때 class SubClassJ extends OuterJ { SubClassJ() { int a = this.a; // access 불가 int b = this.b; // access 불가 int c = this.c; // access 가능 int d = this.d; // access 가능 int e = this.new Inner().e; // access 불가 int f = this.new Inner2().f; // access 불가 int g = this.new Inner3().g; // access 가능 int h = this.new Inner4().h; // access 가능 } } class UnrelatedJ { UnrelatedJ(OuterJ o) { int a = o.a; // access 불가 int b = o.b; // access 불가 int c = o.c; // access 불가 int d = o.d; // access 가능 int e = o.new Inner().e; // access 불가 int f = o.new Inner2().f; // access 불가 int g = o.new Inner3().g; // access 불가 int h = o.new Inner4().h; // access 가능 } }
'Java' 카테고리의 다른 글
그래서 Stream 이 뭔데? - Java (0) 2020.06.01 입력(Input)이란 무엇인가? (Scanner과 BufferedReader 에 대해 이해하기) - Java (0) 2019.07.05 자바[JAVA]란? (0) 2019.06.25