
자바에서 정말 중요한 접근제어자(Access Modifier)는 내가 만든 코드(변수나 함수)를 다른 코드에서 얼마나 쉽게 볼 수 있고 사용할 수 있는지 정해주는 '비밀번호'나 '울타리' 같은 거예요.
🔑 접근제어자는 '공개 범위'를 정하는 규칙이에요!자바에는 크게 네 가지 규칙이 있어요.\
1. public (공개! 📢)
- 의미: 누구나 볼 수 있고, 누구나 사용할 수 있어요.
- 비유: 학교 운동장에 있는 미끄럼틀 같아요. 학교 안의 모든 학생(다른 코드)은 물론, 학교 밖의 사람(다른 프로그램)도 와서 탈 수 있죠. 완전히 공개되어 있어요!
2. protected (가족끼리만! 🏡)
- 의미: 나와 내 가족(상속받은 클래스), 그리고 같은 동네(같은 패키지) 사람들만 볼 수 있어요.
- 비유: 우리 집 마당에 있는 강아지 같아요. 나(강아지 클래스)는 당연히 볼 수 있고, 우리 가족(나를 상속받은 클래스)도 볼 수 있고, 같은 동네에 사는 이웃(같은 패키지)도 강아지를 볼 수 있어요. 하지만 다른 동네 사람은 못 보죠.
3. (아무것도 안 씀) 기본/Default (같은 동네만! 🏘️)
- 의미: 아무것도 안 쓰면, 같은 동네(같은 패키지) 사람들만 볼 수 있어요.
- 비유: 우리 집 현관 비밀번호 같아요. 나(클래스)는 당연히 알고, 같은 동네(같은 패키지) 이웃들끼리는 비밀번호를 공유해서 들어갈 수 있지만, 가족이라도 이 동네를 벗어나 살면 못 들어와요.
4. private (나만 볼 거야! 🔒)
- 의미: 오직 나만(내가 만든 이 클래스 안에서만) 볼 수 있어요. 다른 곳에서는 절대 볼 수 없어요.
- 비유: 내 방 책상 서랍 속 비밀 일기장 같아요. 나(클래스)만이 내용을 볼 수 있고, 심지어 가족이나 이웃이라도 볼 수 없답니다. 가장 강력한 비밀이에요!
왜 이런 규칙이 필요할까요?
만약 모든 것이 public처럼 다 공개되어 있다면, 누구든지 내가 만든 중요한 물건이나 정보를 함부로 만지거나 바꿀 수 있어서 복잡하고 위험해질 수 있겠죠?
접근제어자는 우리가 만든 프로그램이 질서 있고 안전하게 돌아가도록 도와주는 아주 중요한 약속이에요! 이렇게 비밀의 정도를 정해 놓아야 서로에게 피해를 주지 않고 멋진 프로그램을 만들 수 있답니다.
1. public (공개! 📢) 예제
개념: public으로 선언된 요소는 어디에서든 접근할 수 있습니다. 마치 학교 운동장의 미끄럼틀처럼 누구나 이용할 수 있는 것이죠.
pack1/Car.java
java
package pack1; // pack1 패키지에 Car 클래스를 선언합니다.
public class Car {
// public 필드는 어디서든 접근 가능합니다.
public String model = "테슬라 모델 3";
// public 메서드도 어디서든 호출 가능합니다.
public void startEngine() {
System.out.println(model + "의 시동이 걸렸습니다! 🚗");
}
}
pack2/CarExam.java
java
package pack2; // pack2 패키지에 CarExam 클래스를 선언합니다.
import pack1.Car; // 다른 패키지에 있는 Car 클래스를 사용하기 위해 import 합니다.
public class CarExam {
public static void main(String[] args) {
// Car 객체를 생성합니다.
Car myCar = new Car();
// public 필드에 직접 접근하여 값을 출력합니다. (어디서든 접근 가능)
System.out.println("내 차의 모델은: " + myCar.model); // 출력: 내 차의 모델은: 테슬라 모델 3
// public 메서드를 호출합니다. (어디서든 호출 가능)
myCar.startEngine(); // 출력: 테슬라 모델 3의 시동이 걸렸습니다! 🚗
}
}
실행 결과: CarExam.java를 컴파일하고 실행하면, Car 클래스의 public 필드와 메서드에 pack2 패키지에 있는 CarExam에서 아무 문제 없이 접근하는 것을 볼 수 있습니다.
내 차의 모델은: 테슬라 모델 3
테슬라 모델 3의 시동이 걸렸습니다! 🚗
2. protected (가족끼리만! 🏡) 예제
개념: protected로 선언된 요소는 같은 패키지 내에서는 모두 접근 가능하며, 다른 패키지에 있어도 해당 클래스를 상속받은(자식 클래스) 경우에만 접근할 수 있습니다.
pack1/Car.java
java
package pack1; // pack1 패키지
public class Car {
// protected 필드는 같은 패키지 또는 상속받은 자식 클래스에서 접근 가능합니다.
protected String color = "빨간색";
// protected 메서드도 같은 패키지 또는 상속받은 자식 클래스에서 호출 가능합니다.
protected void accelerate() {
System.out.println(color + " 차가 속도를 냅니다. 💨");
}
}
pack2/SportsCar.java (Car를 상속받은 자식 클래스)
java
package pack2; // pack2 패키지
import pack1.Car; // Car 클래스를 상속받기 위해 import 합니다.
// SportsCar는 Car의 자식 클래스입니다.
public class SportsCar extends Car {
public void turboBoost() {
// 상속받은 SportsCar는 부모 Car의 protected 필드와 메서드에 접근할 수 있습니다.
System.out.println(color + " 스포츠카가 터보 부스트를 사용합니다! 🚀");
accelerate(); // 부모의 protected 메서드 호출
}
}
pack2/CarExam.java
java
package pack2; // pack2 패키지
import pack1.Car; // Car 클래스를 사용하기 위해 import 합니다.
public class CarExam {
public static void main(String[] args) {
// 1. SportsCar (자식 클래스)를 통해 protected 멤버 접근
SportsCar mySportsCar = new SportsCar();
mySportsCar.turboBoost();
// 출력: 빨간색 스포츠카가 터보 부스트를 사용합니다! 🚀
// 출력: 빨간색 차가 속도를 냅니다. 💨
System.out.println("---");
// 2. Car (부모 클래스) 객체를 직접 생성하여 protected 멤버에 접근 시도 (다른 패키지)
Car normalCar = new Car();
// 아래 두 줄은 컴파일 에러가 발생합니다!
// 왜냐하면 pack2의 CarExam은 pack1의 Car와 다른 패키지에 있고,
// CarExam은 Car를 상속받은 자식 클래스가 아니기 때문입니다.
// System.out.println(normalCar.color); // 에러 발생!
// normalCar.accelerate(); // 에러 발생!
System.out.println("일반 Car 객체에서는 protected 멤버에 직접 접근할 수 없습니다. (컴파일 에러 예상)");
}
}
실행 결과: pack2/CarExam.java를 컴파일하면 normalCar.color와 normalCar.accelerate() 부분에서 컴파일 에러가 발생합니다. SportsCar를 통한 접근은 정상적으로 이루어집니다.
빨간색 스포츠카가 터보 부스트를 사용합니다! 🚀
빨간색 차가 속도를 냅니다. 💨
---
일반 Car 객체에서는 protected 멤버에 직접 접근할 수 없습니다. (컴파일 에러 예상)
(실제 컴파일 시 에러가 발생하여 System.out.println문만 출력되고 프로그램이 완료되지 않습니다. 주석 처리된 부분을 풀어보면 에러를 확인할 수 있습니다.)
3. (아무것도 안 씀) default (같은 동네만! 🏘️) 예제
개념: 접근제어자를 명시하지 않으면 default (또는 package-private) 접근 권한을 가집니다. 같은 패키지 내에서만 접근할 수 있고, 다른 패키지에서는 접근할 수 없습니다.
pack1/Car.java
java
package pack1; // pack1 패키지
class Car { // 클래스 자체에도 default 접근제어자를 적용할 수 있습니다. (다른 패키지에서 이 클래스 자체를 사용할 수 없음)
// default (접근제어자 명시 안 함) 필드는 같은 패키지 내에서만 접근 가능합니다.
String brand = "현대";
// default (접근제어자 명시 안 함) 메서드도 같은 패키지 내에서만 호출 가능합니다.
void honk() {
System.out.println(brand + " 차가 빵! 빵! 하고 경적을 울립니다. 📢");
}
}
pack1/CarExam.java (같은 패키지)
java
package pack1; // pack1 패키지
public class CarExam {
public static void main(String[] args) {
// 같은 pack1 패키지에 있는 Car 객체를 생성합니다.
Car myCar = new Car();
// 같은 패키지이므로 default 필드에 접근하여 값을 출력할 수 있습니다.
System.out.println("내 차의 브랜드는: " + myCar.brand); // 출력: 내 차의 브랜드는: 현대
// 같은 패키지이므로 default 메서드를 호출할 수 있습니다.
myCar.honk(); // 출력: 현대 차가 빵! 빵! 하고 경적을 울립니다. 📢
}
}
pack2/OtherPackageCarExam.java (다른 패키지)
java
package pack2; // pack2 패키지
// import pack1.Car; // Car 클래스 자체가 default 이므로 다른 패키지에서 import 자체가 안 됩니다. (컴파일 에러)
public class OtherPackageCarExam {
public static void main(String[] args) {
// 다른 패키지에 있는 Car 클래스는 default 접근제어자이므로 접근할 수 없습니다.
// 아래 줄은 컴파일 에러가 발생합니다!
// Car otherCar = new Car(); // 에러 발생!
System.out.println("다른 패키지에서는 default 접근제어자를 가진 Car 클래스에 접근할 수 없습니다. (컴파일 에러 예상)");
}
}
실행 결과: pack1/CarExam.java는 정상적으로 컴파일 및 실행됩니다. pack2/OtherPackageCarExam.java를 컴파일하려고 하면 Car 클래스를 찾을 수 없다는 컴파일 에러가 발생합니다.
<pack1/CarExam.java 실행 결과>
내 차의 브랜드는: 현대
현대 차가 빵! 빵! 하고 경적을 울립니다. 📢
<pack2/OtherPackageCarExam.java 컴파일 시도 시 에러 메시지>
error: Car is not public in pack1; cannot be accessed from outside package
4. private (나만 볼 거야! 🔒) 예제
개념: private으로 선언된 요소는 오직 해당 클래스 내부에서만 접근할 수 있습니다. 외부에서는 그 누구도 접근할 수 없습니다. 마치 개인 일기장처럼 말이죠.
pack1/Car.java
java
package pack1; // pack1 패키지
public class Car {
// private 필드는 오직 이 Car 클래스 내부에서만 접근 가능합니다.
private int speed = 0; // 현재 속도
// private 메서드도 오직 이 Car 클래스 내부에서만 호출 가능합니다.
private void checkSpeedLimit() {
if (speed > 100) {
System.out.println("속도 위반! 천천히 운전하세요! 🚨");
} else {
System.out.println("안전 속도 유지 중입니다. 😊");
}
}
// private 필드에 접근하기 위한 public 메서드 (getter)
public int getSpeed() {
return speed;
}
// private 필드를 변경하기 위한 public 메서드 (setter)
public void setSpeed(int newSpeed) {
if (newSpeed >= 0) { // 속도는 음수가 될 수 없습니다.
this.speed = newSpeed;
System.out.println("현재 속도는 " + this.speed + "km/h 입니다.");
checkSpeedLimit(); // private 메서드는 같은 클래스 내에서 호출 가능합니다.
} else {
System.out.println("속도는 음수가 될 수 없습니다.");
}
}
}
pack1/CarExam.java
java
package pack1; // pack1 패키지
public class CarExam {
public static void main(String[] args) {
Car myCar = new Car();
// private 필드에는 직접 접근할 수 없습니다. (컴파일 에러 발생!)
// System.out.println(myCar.speed); // 에러 발생!
// myCar.checkSpeedLimit(); // 에러 발생!
System.out.println("private 필드와 메서드에는 직접 접근할 수 없습니다. (컴파일 에러 예상)");
// private 필드에 접근하기 위해서는 public 메서드 (getter/setter)를 사용해야 합니다.
myCar.setSpeed(60); // setter를 통해 속도를 60으로 설정합니다.
// 출력: 현재 속도는 60km/h 입니다.
// 출력: 안전 속도 유지 중입니다. 😊
myCar.setSpeed(120); // setter를 통해 속도를 120으로 설정합니다.
// 출력: 현재 속도는 120km/h 입니다.
// 출력: 속도 위반! 천천히 운전하세요! 🚨
System.out.println("현재 차의 속도: " + myCar.getSpeed() + "km/h"); // getter를 통해 속도를 가져옵니다.
// 출력: 현재 차의 속도: 120km/h
}
}
실행 결과: myCar.speed와 myCar.checkSpeedLimit() 부분을 주석 처리하지 않으면 컴파일 에러가 발생합니다. 주석 처리된 상태로 CarExam.java를 컴파일하고 실행하면 아래와 같은 결과를 볼 수 있습니다.
private 필드와 메서드에는 직접 접근할 수 없습니다. (컴파일 에러 예상)
현재 속도는 60km/h 입니다.
안전 속도 유지 중입니다. 😊
현재 속도는 120km/h 입니다.
속도 위반! 천천히 운전하세요! 🚨
현재 차의 속도: 120km/h
이렇게 public, protected, default, private 접근제어자가 실제 코드에서 어떻게 동작하는지 살펴보았습니다.
'Java_language' 카테고리의 다른 글
| 캡슐화 (private) (0) | 2025.12.01 |
|---|---|
| 자바의 static과 this에 대해서 (0) | 2025.12.01 |
| BankAccount 클래스 (0) | 2025.11.27 |
| 클래스를 활용한 학생 정보 출력 프로그램 (0) | 2025.11.26 |
| 클래스 만들기 연습문제 (0) | 2025.11.26 |