반응형
해당 글에서는 Java의 접근 제한자/제어자에 대해 이해를 돕기 위해 작성한 글입니다.
1) 접근 제어자(Access Modifier)
💡 접근 제어자(Access Modifier)
- 클래스, 메서드, 변수의 '접근 범위'를 지정할 수 있는 제어자를 의미합니다.
- 이러한 접근 제어자를 사용하여 적절한 접근 범위를 설정함으로써 클래스와 멤버의 캡슐화를 유지하고 응집도를 높이며 코드의 재사용성과 유지보수성을 향상할 수 있습니다.
[ 더 알아보기 ]
💡 클래스의 멤버
- 클래스 내에서 정의된 변수와 메서드를 의미합니다.
- '클래스의 멤버'는 클래스의 객체 또는 인스턴스를 생성할 때 사용됩니다.
- '클래스의 멤버 변수'는 클래스의 속성이나 상태를 나타내는 데 사용됩니다.
- '클래스의 멤버 메서드'는 클래스의 동작이나 기능을 정의합니다.
1. 접근 제어자의 종류
💡 접근 제어자의 종류
- 접근 제어자는 public, protected, default, private가 있습니다.
- 아래의 이미지는 각각 접근 제어자의 범위를 알려줍니다.
접근 제어자 | 설명 |
public | 해당 제어자는 ‘어떤 클래스에서든 접근이 가능‘합니다. |
protected | 해당 제어자는 ‘같은 패키지 내‘에서 또는 해당 클래스를 ‘상속 받은 클래스‘에서 접근 가능합니다. |
default | 해당 제어자는 제어자는 명시하지 않는 경우를 의미하며, ‘같은 패키지 내에서만 접근 가능‘합니다. |
private | 해당 제어자는 ‘같은 클래스 내에서만 접근 가능‘합니다 |
public
💡 public
- 클래스, 메서드 또는 필드가 다른 클래스나 패키지에서 접근할 수 있도록 선언하는 데 사용되는 제어자입니다.
- 클래스, 메서드 또는 필드가 public으로 선언되면 프로그램의 모든 다른 클래스와 패키지에서 접근할 수 있다는 의미입니다.
protected
💡 protected
- 클래스의 멤버(필드, 메서드)가 '같은 패키지' 내의 다른 클래스 또는 서브클래스에서 접근할 수 있도록 선언하는 데 사용됩니다.
default
💡 default
- 클래스, 메서드 또는 필드가 ‘같은 패키지 내’의 다른 클래스에서만 접근할 수 있도록 선언하는 데 사용됩니다.
- default 접근 제어자는 별도의 키워드 없이 접근 제어자를 지정하지 않았을 때 기본적으로 적용되는 접근 제어자입니다.
private
💡 private
- ‘클래스 내부’에서만 접근할 수 있는 멤버를 선언하는데 사용됩니다.
- private으로 선언된 멤버는 클래스 외부에서 직접 접근할 수 없으며, 해당 클래스의 메서드를 통해서만 접근할 수 있습니다.
2. 접근 제어자의 사용 가능 범위
💡 접근 제어자의 사용 가능 범위
- 클래스, 생성자, 멤버 변수, 멤버 클래스, 지역 변수 내에서 접근 제어자가 사용이 가능한 범위에 대해 확인해 봅니다.
위치 | 사용가능 접근제한자 |
클래스 | public, default |
생성자 | public, protected, default, private |
멤버 변수 | public, protected, default, private |
멤버 클래스 | public, protected, default, private |
지역 변수 | 사용 불가능 |
2) 접근 제어자의 사용 목적
1. 캡슐화
💡 캡슐화
- 접근 제어자를 사용하여 ‘클래스의 멤버’에 대한 접근을 제한함으로써 캡슐화를 구현할 수 있습니다.
- 이를 통해 클래스의 내부 구현 세부사항을 숨기고 외부에서 직접 접근하지 못하도록 함으로써 안정성과 유지 보수성을 높일 수 있습니다.
💡 캡슐화 사용예시
- Car라는 클래스에서 멤버 변수로 brand를 선언하였습니다.
- 해당 brand 변수는 클래스 내에만 유효한 ‘private’ 접근 제어자로 지정을 하였습니다.
- 그렇기에 외부에서 해당 변수를 접근할 수 있는 방법은 없지만 getter/setter를 통해 직접적인 변수 접근 및 변경이 아닌 메서드를 통한 접근이 가능하도록 구성을 하여 캡슐화를 구성하였습니다.
public class Car {
private String brand; // private 접근 제어자를 사용하여 brand 변수에 접근을 제한
public String getBrand() { // public 메소드를 통해 brand 변수에 접근
return brand;
}
public void setBrand(String brand) { // public 메소드를 통해 brand 변수를 수정
this.brand = brand;
}
}
2. 데이터 보호
💡 데이터 보호
- 접근 제어자를 사용하여 ‘멤버 변수에 대한 접근을 제한’함으로써 데이터의 무결성과 안정성을 보호할 수 있습니다.
- 외부에서 무작위로 데이터를 수정하는 것을 방지하고, 유효한 메서드를 통해만 데이터에 접근할 수 있도록 합니다.
💡 데이터 보호 사용예시
- BankAccount라는 클래스에서 멤버 변수로 balance를 선언하였습니다.
- 해당 balance 변수는 클래스 내에만 유효한 ‘private’ 접근 제어자로 지정을 하였습니다.
- 그렇기에 외부에서 해당 변수에 대해 직접적인 접근이 불가능하지만 deposit(), withdraw() 메서드를 통해서 변수를 조작하여 반환하여 데이터 값을 반환하도록 구성하였습니다.
public class BankAccount {
private double balance; // private 접근 제어자를 사용하여 balance 변수에 접근을 제한
public double getBalance() { // public 메소드를 통해 balance 변수에 접근
return balance;
}
public void deposit(double amount) { // public 메소드를 통해 balance 변수를 수정
balance += amount;
}
public void withdraw(double amount) { // public 메소드를 통해 balance 변수를 수정
if (amount <= balance) {
balance -= amount;
} else {
System.out.println("Insufficient funds");
}
}
}
3. 코드 재사용
💡 코드 재사용
- 접근 제어자를 사용하여 상속 관계에서 부모 클래스의 메서드와 변수를 하위 클래스에서 재사용할 수 있습니다.
- 이를 통해 코드의 중복을 피하고, 효율적인 개발을 할 수 있습니다.
💡 사용 예시
- Animal이라는 클래스와 Dog라는 클래스가 있으며 Dog 클래스는 Animal로부터 상속을 받은 관계입니다.
- Animal 클래스에서는 protected 접근 제어자를 두고 멤버 변수를 선언하였기에, Dog 클래스에서는 Animal 클래스의 멤버 변수에 대한 접근이 가능합니다.
- 또한 상속관계이기에 Dog 클래스의 인스턴스를 생성 후 eat() 메서드 접근 역시 가능합니다.
public class Animal {
protected String name; // protected 접근 제어자를 사용하여 name 변수에 접근
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + " is eating");
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
public void bark() {
System.out.println(name + " is barking");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("Buddy");
dog.eat(); // 상위 클래스인 Animal의 eat 메소드 재사용
dog.bark(); // 하위 클래스인 Dog의 bark 메소드 사용
}
}
3) 접근 제어자(Access Modifier) 사용 예시
1. 사용 예시 구조
💡 사용 예시 구조
- 호출을 받을 클래스 선언부로 AClass라는 이름의 클래스를 구성하였습니다.
- 그리고 호출을 하는 BClass라는 이름의 클래스를 구성하였습니다.
1.1. 클래스 선언부 : AClass
💡 클래스 선언부 : AClass
- 해당 클래스의 구조는 모두 접근이 가능한 public class로 접근 제어자를 두었습니다.
- 클래스 내에 멤버 변수로 접근 제어자 public, protected, default, private으로 선언을 하였습니다.
package com.adjh.multiflexapi;
public class AClass {
/**
* 클래스의 멤버 변수에 대해 접근 제어자를 확인하봅니다.
*/
// public
public String publicUserNickname = "adjh54";
// protected
protected String protectedUserNickname = "adjh54";
// default
String defaultUserNickname = "adjh54";
// private
private String privateUserNickname = "adjh54";
}
1.2. 클래스 호출부 : BClass
💡 클래스 호출부 : BClass
- 해당 클래스의 구조는 모두 접근이 가능한 public class로 접근 제어자를 두었습니다.
- 실제 AClass로 인스턴스를 생성하고 멤버 변수를 호출하는 클래스입니다
package com.adjh.multiflexapi.test2;
public class BClass {
public void callAClass() {
}
}
💡 아래와 같이 사용예시를 확인해 볼 예정입니다.
사용 예시 | 접근 가능 |
두 개의 클래스가 같은 패키지에 있는 경우 | public, default, protected |
두 개의 클래스가 다른 패키지에 있는 경우 | public |
두 개의 클래스가 같은 패키지에 있고 클래스 간 상속 관계인 경우 | public, protected |
두 개의 클래스가 다른 패키지에 있고 클래스 간 상속 관계인 경우 | public, protected |
사용예시 -1 : 두 개의 클래스가 같은 패키지에 있는 경우
💡 사용예시 -1 : 두 개의 클래스가 같은 패키지에 있는 경우
- 아래와 같이 AClass와 BClass는 동일한 test라는 패키지 내에 소속되어 있습니다.
💡 멤버 변수 호출
- 아래와 같이 BClass에서 AClass의 인스턴스를 생성하고 멤버 변수에 접근합니다.
- 아래의 표와 같이 같은 클래스에만 있어야 하는 private를 제외하고는 모두 접근이 잘됨을 확인하였습니다.
사용예시 -2 : 두 개의 클래스가 다른 패키지에 있는 경우
💡 사용 예시 -2 : 두 개의 클래스가 다른 패키지에 있는 경우
- 아래와 같이 AClass는 test 패키지에 속해 있고, BClass는 test2 패키지에 속해 있는 경우입니다.
💡 멤버 변수 호출
- 아래와 같이 BClass에서 AClass의 인스턴스를 생성하고 멤버 변수에 접근합니다.
- 아래의 표와 같이 같은 클래스, 같은 패키지에 있는 경우 접근이 허용되는 경우는 public만 가능함을 확인하였습니다.
사용예시 -3 : 두 개의 클래스가 같은 패키지에 있고 클래스 간 상속 관계인 경우
💡 사용예시 -3 : 두 개의 클래스가 같은 패키지에 있고 클래스 간 상속 관계인 경우
- 아래와 같은 AClass와 BClass는 동일한 test라는 패키지 내에 소속되어 있고, BClass는 AClass로부터 상속을 받는 관계입니다.
💡 멤버 변수 호출
- 아래와 같은 AClass와 BClass는 동일한 test라는 패키지 내에 소속되어 있습니다.
- 아래의 표와 같이 같은 클래스, 같은 패키지에 있는 경우이며 상속 관계가 있는 경우는 public, protected만 접근이 가능함을 확인하였습니다.
사용예시 -4 : 두 개의 클래스가 다른 패키지에 있고 클래스 간 상속 관계인 경우
💡 사용예시 -4 : 다른 패키지, 상속 관계에 있는 경우
- 아래와 같은 AClass는 test라는 패키지, BClass는 test2라는 패키지 내에 소속되어 있고, BClass는 AClass로부터 상속을 받는 관계입니다.
💡 멤버 변수 호출
- 아래와 같은 AClass는 test라는 패키지, BClass는 test2라는 패키지 내에 소속되어 있습니다.
- 아래의 표와 같이 다른 패키지에 있는 경우이며, 상속 관계가 있는 경우는 public, protected만 접근이 가능함을 확인하였습니다. (* protected는 같은 패키지 or 상속관계에서 허용됩니다.)
오늘도 감사합니다. 😀
반응형
'Java > 이론 및 문법' 카테고리의 다른 글
[Java] @Transactional 어노테이션 상세 이해하기 : Checked, Unchecked Exception Rollback (2) | 2024.01.03 |
---|---|
[Java] 예외처리(Exception Handling) 이해하기 -1 : try - catch / throws (0) | 2023.12.24 |
[Java] API 캐시와 세션 이해하기 (1) | 2023.10.22 |
[Java] JVM(Java Virtual Machine) 이해하기 -3 : 가비지 컬렉터(GC, Garbage Collector) (0) | 2023.10.09 |
[Java] JVM(Java Virtual Machine) 이해하기 -2 : 메모리 영역(Runtime Data Area) (0) | 2023.10.07 |