본문 바로가기
JAVA

Java 접근지정자 알아보자 1편

by 얍얍1234 2023. 10. 7.

자바(Java)는 객체 지향 프로그래밍(OOP) 언어로서, 클래스와 클래스 간의 상호 작용을 관리하고 제어하기 위해 접근 지정자(Access Modifier)를 사용합니다. 이러한 접근 지정자는 클래스, 필드, 메서드 등의 멤버에 대한 가시성과 접근 권한을 제어하며, 정보 은닉(Encapsulation)을 실현합니다.

이 글에서는 자바에서 사용되는 접근 지정자의 종류, 역할, 사용 방법, 그리고 정보 은닉에 대해 알아보겠습니다.


1. 접근 지정자의 역할

자바에서는 접근 지정자를 사용하여 클래스 멤버의 가시성과 접근 권한을 지정합니다. 이를 통해 다음과 같은 역할을 수행합니다.


1.1. 정보 은닉

정보 은닉은 객체 지향 프로그래밍의 핵심 원리 중 하나로, 객체의 내부 상태를 외부로부터 숨기고 접근을 제한함으로써 데이터의 무결성과 보안을 보장합니다. 접근 지정자를 사용하여 클래스 멤버에 접근 권한을 부여하면, 멤버에 대한 직접적인 접근을 제한할 수 있습니다.


1.2. 모듈화

접근 지정자를 통해 클래스를 모듈화하고, 다른 클래스에서 필요한 부분만을 공개함으로써 코드의 모듈성을 높입니다. 이로써 코드의 유지보수성과 확장성을 향상시킬 수 있습니다.


1.3. 보안

중요한 데이터나 기능을 보호하기 위해 접근 지정자를 사용하여 외부로부터의 접근을 제한할 수 있습니다. 이를 통해 불필요한 데이터 노출과 변경을 방지할 수 있습니다.


2. 자바의 접근 지정자 종류

자바에서는 다음과 같은 네 가지 접근 지정자를 제공합니다.


2.1. public

- 가장 넓은 범위의 접근 지정자입니다.
- 어떤 클래스에서도 접근 가능합니다.
- 외부 패키지에서도 접근 가능합니다.


2.2. protected

- 동일 패키지 내의 클래스와 하위 클래스에서 접근 가능합니다.
- 외부 패키지에서는 접근 불가능합니다.

 

2.3. default (package-private)

- 아무 접근 지정자를 명시하지 않은 경우의 기본 접근 지정자입니다.
- 동일 패키지 내의 클래스에서만 접근 가능합니다.
- 외부 패키지에서는 접근 불가능합니다.


2.4. private

- 가장 제한적인 접근 지정자입니다.
- 동일 클래스 내에서만 접근 가능합니다.
- 다른 클래스나 하위 클래스에서는 접근 불가능합니다.


3. 접근 지정자의 사용 예제

3.1. public 접근 지정자

public class PublicExample {
    public String publicField = "public field";

    public void publicMethod() {
        System.out.println("This is a public method.");
    }
}

 

public 접근 지정자를 가진 클래스 PublicExample의 멤버인 publicField와 publicMethod()는 어떤 클래스에서도 접근할 수 있습니다.

 

3.2. protected 접근 지정자

class Parent {
    protected String protectedField = "protected field";
}

class Child extends Parent {
    void accessProtectedField() {
        System.out.println(protectedField);
    }
}

 

protected 접근 지정자를 가진 멤버는 동일 패키지 내의 클래스와 하위 클래스에서 접근 가능합니다. 위 예제에서 Child 클래스는 Parent 클래스의 protectedField에 접근할 수 있습니다.


3.3. default (package-private) 접근 지정자

class DefaultExample {
    String defaultField = "default field";

    void defaultMethod() {
        System.out.println("This is a default method.");
    }
}

default 접근 지정자를 가진 클래스 DefaultExample의 멤버는 동일 패키지 내의 클래스에서만 접근할 수 있습니다.


3.4. private 접근 지정자

public class PrivateExample {
    private String privateField = "private field";

    private void privateMethod() {
        System.out.println("This is a private method.");
    }
}


private 접근 지정자를 가진 클래스 PrivateExample의 멤버는 동일 클래스 내에서만 접근할 수 있습니다. 외부에서는 직접적으로 접근할 수 없습니다.

 


4. 정보 은닉과 캡슐화

정보 은닉은 객체 지향 프로그래밍의 핵심 원리 중 하나로, 클래스의 내부 상태를 외부로부터 숨기고 접근을 제한함으로써 데이터의 무결성을 보호합니다. 이것은 접근 지정자를 통해 구현됩니다. 클래스의 필드를 private으로 선언하고, 필요한 경우에만 public 메서드를 통해 접근하도록 하는 것이 정보 은닉과 캡슐화의 핵심 아이디어입니다.

public class BankAccount {
    private double balance;

    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }

    public void deposit(double amount) {
        if (amount > 0) {
            this.balance += amount;
        }
    }

    public void withdraw(double amount) {
        if (amount > 0 && amount <= this.balance) {
            this.balance -= amount;
        }
    }

    public double getBalance() {
        return this.balance;
    }
}


위의 `BankAccount` 클래스는 `balance` 필드를 `private`으로 선언하고, `deposit`, `withdraw`, `getBalance` 메서드를 통해 외부에서 필드에 접근할 수 있도록 하고 있습니다. 이렇게 하면 외부에서 무분별한 수정이나 접근을 막을 수 있으며, 객체의 무결성을 유지할 수 있습니다.

 

 

5. 접근 지정자와 상속

자바에서 상속 관계에 있는 클래스 간에는 접근 지정자에 따라 멤버의 가시성이 달라집니다. 이를 요약하면 다음과 같습니다.

- `public` 멤버는 상속 관계와 무관하게 어떤 클래스에서나 접근 가능합니다.
- `protected` 멤버는 하위 클래스에서 접근 가능하며, 다른 패키지의 하위 클래스에서도 접근 가능합니다.
- `default` 멤버는 동일 패키지 내에서만 접근 가능합니다.
- `private` 멤버는 해당 클래스 내에서만 접근 가능합니다.

 


6. 접근 지정자와 다형성

접근 지정자는 다형성(Polymorphism)을 구현하는데도 중요한 역할을 합니다. 상위 클래스에 선언된 멤버의 접근 지정자에 따라 하위 클래스에서 오버라이딩된 메서드의 접근 지정자가 결정됩니다. 다음 예제를 통해 살펴봅시다.

class Animal {
    protected void makeSound() {
        System.out.println("동물 소리");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("멍멍!");
    }
}

 

 

위의 코드에서 `Dog` 클래스는 `makeSound` 메서드를 `protected`로 오버라이딩하고 있습니다. 이 경우, `Dog` 클래스의 객체를 생성하고 다음과 같이 다형성을 사용할 수 있습니다.

Animal animal = new Dog();
animal.makeSound(); // "멍멍!" 출력


`animal` 변수는 `Animal` 클래스의 참조로 선언되었지만, 실제로는 `Dog` 클래스의 인스턴스를 참조하고 있습니다. 이로써 다형성을 통해 `Dog` 클래스의 오버라이딩된 메서드가 호출되었습니다.