클래스, 변수, 메서드 등에 접근할 수 있는 범위를 지정하는 키워드.
접근 제한자를 적절히 사용하면 캡슐화(encapsulation)를 구현할 수 있으며, 코드의 보안성과 유지보수성을 높일 수 있다.
어디서나 접근 가능.
클래스, 메서드, 변수 등에 사용 가능.
public class Car {
public String brand;
public void drive() {
System.out.println("Driving...");
}
}
같은 패키지 내 또는 다른 패키지의 자식 클래스에서 접근 가능.
주로 상속 관계에서 자식 클래스에게만 노출하고 싶을 때 사용한다.
public class Animal {
protected void eat() {
System.out.println("먹고 있어요");
}
}
class Dog extends Animal {
void barkAndEat() {
eat(); // 부모의 protected 메서드 접근 가능
System.out.println("멍멍!");
}
}
접근 제한자를 명시하지 않으면 기본적으로 이 제한자가 적용된다.
같은 패키지 내에서만 접근 가능하고, 다른 패키지에서는 불가하다.
class PackageExample {
void show() {
System.out.println("같은 패키지에서만 접근 가능");
}
}
해당 클래스 내부에서만 접근 가능. (외부 클래스나 상속받은 클래스에서는 접근 불가능.)
데이터 은닉을 위해 가장 많이 사용된다.
public class Account {
private int balance = 1000;
public int getBalance() {
return balance;
}
}
| 접근 제한자 | 같은 클래스 | 같은 패키지 | 하위 클래스 | 다른 패키지 |
|---|---|---|---|---|
public | ✅ | ✅ | ✅ | ✅ |
protected | ✅ | ✅ | ✅ | ❌(상속 시 ✅) |
| (default) | ✅ | ✅ | ❌ | ❌ |
private | ✅ | ❌ | ❌ | ❌ |
※ (default)는 접근 제한자를 명시하지 않았을 때 적용
| 접근 제한자 | 사용 목적 |
|---|---|
public | 어디서나 접근 허용 (API 등 외부에 공개할 때) |
protected | 상속 관계에서 사용, 패키지 내부도 허용 |
| (default) | 같은 패키지 안에서만 공유 (패키지 단위 모듈화) |
private | 내부 구현 은닉 (캡슐화 핵심) |
package lesson04;
public class Ex04_Person {
public String name = "김사과";
private int age = 20; // 같은 클래스 내에서만 가능
protected String hobby = "코딩";
String job = "개발자";
public void showInfo(){
System.out.println("이름: " + name);
System.out.println("나이: " + age);
System.out.println("취미: " + hobby);
System.out.println("직업: " + job);
}
}
package lesson04;
public class Ex04_Main {
public static void main(String[] args) {
Ex04_Person person = new Ex04_Person();
System.out.println(person.name);
// System.out.println(person.age);
System.out.println(person.hobby);
System.out.println(person.job);
}
}
김사과
코딩
개발자
데이터(속성)와 행위(메서드)를 하나의 단위(객체)로 묶고,
외부에서는 직접 접근하지 못하게 하여 보안성과 무결성 유지
package lesson04;
class Account {
private int balance = 0; // 은닉성(외부에서 직접 접근 불가)
// public 메서드를 통해서만 접근 가능
public void deposit(int amount){
if(amount > 0) balance += amount;
}
public int getBalance(){
return balance;
}
}
public class Ex05_Main {
public static void main(String[] args) {
Account account = new Account();
account.deposit(1000);
// account.balance = 10000; // ❌ private이므로 직접 접근 불가
// 안전한 방식으로 입금
System.out.println("잔액: " + account.getBalance());
}
}
잔액: 1000
기존 클래스 재사용하여 새로운 클래스를 만들 수 있음
코드의 중복 제거, 유지보수 편리성 향상
부모 클래스의 속성과 메서드를 자식 클래스가 물려받음
class Animal {
public void eat() {
System.out.println("먹는다.");
}
}
class Dog extends Animal {
public void bark() {
System.out.println("멍멍!");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // Animal 클래스에서 상속받은 메서드
dog.bark(); // Dog 클래스의 메서드
}
}
같은 이름의 메서드가 다양한 동작을 하도록 허용
메서드 오버로딩, 오버라이딩, 업캐스팅 등을 통해 구현
동일한 인터페이스로 다양한 구현체를 처리 가능
package lesson04;
class Ex06_Animal{
public void speak(){
System.out.println("동물이 소리를 냅니다.");
}
}
class Ex06_Cat extends Ex06_Animal{
@Override
public void speak() {
System.out.println("야옹~");
}
}
class Ex06_Dog extends Ex06_Animal {
@Override
public void speak() {
System.out.println("멍멍!");
}
}
public class Ex06_Main {
public static void main(String[] args) {
Ex06_Animal a1 = new Ex06_Cat();
Ex06_Animal a2 = new Ex06_Dog();
a1.speak();
a2.speak();
}
}
야옹~
멍멍!
복잡한 시스템에서 필요한 정보만 선별하여 노출하고, 나머지 세부 구현은 감추는 것
사용자에게 불필요한 내부 동작은 숨기고, 중요한 동작만 보여줌
package lesson04;
abstract class Vehicle {
abstract void move(); // 구현은 하지 않음 (추상 메서드)
public void start() {
System.out.println("시동을 겁니다.");
}
}
class Car extends Vehicle {
@Override
void move() {
System.out.println("도로를 달립니다.");
}
}
public class Ex07_Main {
public static void main(String[] args) {
Car car = new Car();
car.start();
car.move();
}
}
시동을 겁니다.
도로를 달립니다.