![](https://blog.kakaocdn.net/dn/kJjSu/btskBCywoJO/KJARlOtQzaE2K50Np4RJfk/img.png)
access modifiers을 지칭할 때 "접근 지시자”, “접근 제어 지시자”, “접근 제어자”, “접근 제한자” 등은 동일한 의미로 사용되고 있습니다. 아래에서는 접근 제어자로 통일하겠습니다.
✅ 접근 제어자의 사용이유 : 캡슐화
객체 지향 프로그래밍에서 캡슐화는 클래스의 데이터(상태)와 그 데이터를 조작하는 메소드(행동)를 하나로 묶는 것을 의미합니다. 이렇게 하면 클래스의 내부 구조를 외부에서 직접 접근하거나 변경하는 것을 제한하고, 메소드를 통해서만 데이터를 변경하거나 액세스할 수 있게 합니다. 즉, 데이터를 '캡슐' 안에 보호하고, 외부에서는 해당 '캡슐'에 어떻게 접근하고 조작할 수 있는지에 대한 인터페이스만 제공하는 것입니다.
자바에서는 이를 구현하기 위해 접근 제어자(access modifiers)를 사용합니다. `public`, `private`, `protected`, 그리고 `default(선언되지 않은 경우)`가 있습니다.
`private` 키워드를 사용하면 해당 필드나 메소드는 같은 클래스 내에서만 접근할 수 있습니다. 이를 통해 클래스의 내부 데이터를 외부에서 직접 변경하거나 액세스하는 것을 방지할 수 있습니다.(자식 클래스도 접근할 수 없습니다)
✅ 접근제어자의 종류
접근 제어(Access Control)는 객체 지향 프로그래밍에서 클래스의 멤버(필드, 메서드, 생성자) 또는 클래스 자체의 접근 수준을 지정하는 기능입니다. 이를 통해 클래스의 내부 정보를 캡슐화하고, 외부에서 접근할 수 있는 수준을 제어할 수 있습니다. Java에서는 다음과 같이 4가지의 접근 제어자를 제공합니다.
Modifier | Within Class | Within Package | Same Package by subclasses | Outside Package by subclasses | Global |
---|---|---|---|---|---|
public | Yes | Yes | Yes | Yes | Yes |
protected | Yes | Yes | Yes | Yes | No |
no modifier(default) | Yes | Yes | Yes | No | No |
private | Yes | No | No | No | No |
※Within Class : 클래스의 내부
※Within Package : 동일한 패키지에 있는 다른 일반 클래스
※Same Package by subclasses : 동일한 패키지 안에 있는 상속 받은 하위 클래스
※Outside Package by subclasses : 다른 패키지 안에 있는 상속 받은 하위 클래스
※Global : 외부 패키지에 있는 일반 클래스
![](https://blog.kakaocdn.net/dn/bAhqUY/btskrcIdyPG/qxG8CV7sda3mLm1nKBDgKk/img.png)
→ 화살표는 상속관계를 나타냅니다.
- public = 어디서든 접근 가능
public
접근 제어자는 가장 넓은 범위의 접근 수준을 가지며, 어떤 클래스에서든 접근할 수 있습니다.public
으로 선언된 멤버(필드, 메서드, 생성자)는 외부 클래스에서 직접 접근할 수 있으며, 해당 클래스의 인스턴스를 생성한 후에도 접근이 가능합니다. 예를 들어,public
으로 선언된 필드는 다른 클래스에서 값을 읽고 변경할 수 있습니다.- Person
public class Person { public String name; public void sayHello() { System.out.println("Hello, my name is " + name); } }
위의 예시에서
Person
클래스는public
으로 선언되었습니다. 이는 다른 클래스에서도Person
클래스에 접근할 수 있음을 의미합니다.또한,
name
필드와sayHello()
메서드도public
으로 선언되었습니다.name
필드는 외부에서 직접 접근하여 값을 읽고 변경할 수 있으며,sayHello()
메서드도 외부에서 호출할 수 있습니다. 이렇게public
으로 선언된 멤버는 클래스를 사용하는 다른 부분에서 해당 멤버에 자유롭게 접근할 수 있습니다.
- Main
public class Main { public static void main(String[] args) { Person person = new Person(); person.name = "John"; person.sayHello(); } }
위의 코드에서
Main
클래스가Person
클래스에 접근하고 있습니다.Person
클래스와sayHello()
메서드는public
으로 선언되어 있기 때문에Main
클래스에서 해당 멤버에 접근할 수 있습니다.Main
클래스에서Person
객체를 생성하고,name
필드에 값을 할당하고,sayHello()
메서드를 호출하여 결과를 출력하는 것을 확인할 수 있습니다. 이는Person
클래스에 접근하여 해당 클래스의 멤버를 사용할 수 있음을 보여주는 예시입니다.❗public
접근 제어자를 사용할 때에는 주의해야 할 점도 있습니다.public
으로 선언된 멤버는 외부에서 자유롭게 접근할 수 있기 때문에, 클래스 내부의 상태를 외부에서 마음대로 변경할 수 있다는 점을 고려해야 합니다. 클래스의 캡슐화를 유지하고, 외부로부터의 접근을 제어해야 할 경우에는public
접근 제어자 대신 더 제한적인 접근 제어자를 고려해야 합니다.
- Person
- protected = 다른 패키지 안의 하위 클래스까지
protected
접근 제어자는 같은 패키지 내에서 접근 가능하며, 다른 패키지에서 상속 관계에 있는 하위 클래스에서도 접근할 수 있습니다. 이는 클래스의 상속과 관련하여 유용한 접근 제어자입니다.protected
로 선언된 멤버는 다른 패키지의 상속받은 하위 클래스에서 사용될 수 있으며, 같은 패키지 내의 클래스에서도 접근할 수 있습니다. 다른 패키지에 속하고, 상속 받지 않은 클래스에서는 해당 멤버에 접근할 수 없습니다.- Person, protected
public class Person { protected String name; protected void sayHello() { System.out.println("Hello, my name is " + name); } }
- Student, protected
public class Student extends Person { public void introduce() { name = "John"; sayHello(); } }
위의 코드에서
Person
클래스의name
필드와sayHello()
메서드는protected
로 선언되어 있습니다. 이는 같은 패키지 내에서 접근 가능하고, 상속 관계에 있는 하위 클래스에서도 접근할 수 있음을 의미합니다.Student
클래스는Person
클래스를 상속받고 있으므로Person
클래스의protected
멤버에 접근할 수 있습니다.introduce()
메서드에서name
필드에 값을 할당하고,sayHello()
메서드를 호출하여 결과를 출력하는 것을 확인할 수 있습니다.protected
접근 제어자는 상속 관계에 있는 클래스 간에 정보를 공유하고 재사용하는 데 사용됩니다. 이를 통해 상위 클래스의 멤버를 하위 클래스에서 오버라이딩하거나 확장하여 유연한 코드 구조를 구성할 수 있습니다. 상속 관계에 있다면 다른 패키지에서도 사용할 수 있음을 기억해야 합니다. - Person, protected
- default = 같은 패키지까지
default
접근 제어자는 아무 접근 제어자도 지정하지 않은 경우의 기본 접근 수준입니다.default
로 선언된 멤버는 같은 패키지 내에서만 접근 가능하며, 다른 패키지에 속한 클래스에서는 접근할 수 없습니다.default
접근 제어자는 접근 제어자를 명시적으로 지정하지 않았을 때의 기본 동작을 정의하는 데 사용됩니다.- 패키지 “com.example.package1” 내의 Person.java 파일
package com.example.package1; class Person { String name; void sayHello() { System.out.println("Hello, my name is " + name); } }
- 패키지 “com.example.package2” 내의 AnotherClass.java 파일
package com.example.package2; public class AnotherClass { public static void main(String[] args) { Person person = new Person(); // 다른 패키지에서 Person 클래스에 접근 불가능 person.name = "John"; // 접근 불가능 person.sayHello(); // 접근 불가능 } }
위의 코드에서
Person
클래스는default
접근 제어자로 선언되어 있으며, “com.example.package1” 패키지에 속해 있습니다. 다른 패키지인 “com.example.package2” 패키지에서Person
클래스를 사용하려고 할 때, 해당 클래스에 접근할 수 없습니다. 따라서 다른 패키지에 있는AnotherClass
에서Person
클래스를 사용하려면Person
클래스를 아래와 같이 클래스 상단에서import
하면 사용할 수 있습니다.import com.example.package1.Person;
protected 와 default 의 차이점은 다른 패키지에서 상속 관계에 있는 클래스가 접근할 수 있는지 여부입니다.
- 패키지 “com.example.package1” 내의 Person.java 파일
- private = 현재 클래스 안에서만
private
접근 제어자는 가장 제한적인 접근 수준을 가지며, 해당 멤버를 선언한 클래스 내에서만 접근할 수 있습니다.private
으로 선언된 멤버는 외부 클래스나 하위 클래스에서 직접 접근할 수 없습니다.private
멤버는 주로 클래스의 내부 구현을 숨기고, 외부로부터의 직접적인 접근을 제한하기 위해 사용됩니다. 다른 클래스에서private
멤버에 접근하려면 해당 클래스 내에서 접근 가능한 메서드를 통해 간접적으로 접근해야 합니다.- Person, private
public class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { if (age >= 0) { this.age = age; } else { System.out.println("Age cannot be negative."); } } }
위의 코드에서
Person
클래스의name
과age
필드는private
접근 제어자로 선언되어 있습니다. 이는 해당 필드들이 클래스 내부에서만 접근 가능하도록 제한한다는 의미입니다. 외부에서는 직접적으로 접근하여 수정하거나 읽을 수 없습니다.그러나
private
접근 제어자를 사용하더라도 클래스 외부에서 필드 값을 설정하고 읽을 수 있도록,getter
와setter
메서드를 제공할 수 있습니다. 위의 코드에서는getName()
과setName()
메서드로name
필드에 접근하고,getAge()
와setAge()
메서드로age
필드에 접근할 수 있습니다. 이를 통해 외부에서Person
객체의 필드 값을 간접적으로 조작할 수 있습니다.🔎private
접근 제어자를 사용하는 이유는 캡슐화와 정보 은닉에 있습니다. 클래스의 내부 구현을 외부로부터 감추고, 필드에 대한 직접적인 접근을 제한하여 객체의 무결성을 보호합니다. 이렇게 하면 필드의 유효성을 체크하거나 필드의 값을 조작할 때 추가적인 로직을 수행할 수 있습니다. 또한,getter
와setter
를 통해 필드 값을 조작할 때 유효성 검사 등의 추가적인 로직을 적용할 수 있습니다.
- Person, private
🏷️이미지 출처 및 참고한 사이트
![](https://logicmojo.com/assets/dist/img/ico/favicon.png)
Uploaded by N2T