Post

Java 문법 (7) - 접근 제어자

Java 문법 (7) - 접근 제어자




접근 제어자


자바는 public , private 같은 접근 제어자(access modifier)를 제공합니다. 접근 제어자를 사용하면 해당 클래스 외부에서 특정 필드나 메서드에 접근하는 것을 허용하거나 제한할 수 있습니다.




접근 제어자 종류


  • private: 모든 외부 호출을 막음
  • default(package-private): 같은 패키지 안에서 호출만 허용
  • protected: 같은 패키지 안에서의 호출과, 상속관계의 호출은 허용
  • public: 모든 외부의 호출을 허용




접근 제어자 예시 - 필드, 메서드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// access.a 패키지의 AccessData 클래스
package access.a;  
  
public class AccessData {  
    public int publicField;  
    int defaultField;  
    private int privateField;  
  
    public void publicMethod(){  
        System.out.println("publicMethod 호출 " + publicField);  
    }  
  
    void defaultMethod(){  
        System.out.println("defaultMethod 호출 " + defaultField);  
    }  
  
    private void privateMethod(){  
        System.out.println("privateMethod 호출 " + privateField);  
    }  
  
    public void innerMethod() {  
        System.out.println("내부 호출");  
        publicField = 100;  
        defaultField = 200;  
        privateField = 300;  
        publicMethod();  
        defaultMethod();  
        privateMethod();  
    }  
}

access.a라는 패키지 안에 AccessData라는 클래스를 만들어서 각각 public, default, private 필드와 메서드를 선언했습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// access.a 패키지의 AccessinnerMain 클래스
package access.a;  
  
public class AccessinnerMain {  
    public static void main(String[] args) {  
        AccessData data = new AccessData();  
  
        // public 호출 가능  
        data.publicField = 1;  
        data.publicMethod();  
  
        // default 같은 패키지여서 호출 가능  
        data.defaultField = 2;  
        data.defaultMethod();  
  
        // private 호출 불가능  
        //data.privateField = 3;  
        //data.privateMethod();  
        
        // 내부를 건드리는 함수  
        data.innerMethod();  
    }  
}

같은 패키지인 access.a 안에서 AccessinnerMain 클래스를 만들고, AccessData 객체를 생성해서 사용하는 테스트를 했습니다. public은 호출 가능하고, default도 같은 패키지에 있기 때문에 호출이 가능했으며, private는 접근 불가능합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// access.b 패키지의 AccessOuterMain 클래스
package access.b;  
  
import access.a.AccessData;  
  
public class AccessOuterMain {  
    public static void main(String[] args) {  
        AccessData data = new AccessData();  
  
        // public 호출 가능  
        data.publicField = 1;  
        data.publicMethod();  
  
        // default 다른 패키지여서 호출 불가능  
        //data.defaultField = 2;  
        //data.defaultMethod();  
        // private 호출 불가능  
        //data.privateField = 3;  
        //data.privateMethod();  
        // 내부를 건드리는 함수  
        data.innerMethod();  
    }  
}

이번엔 다른 패키지인 access.b 패키지에서 AccessOuterMain 클래스를 만들어서 AccessData 객체를 생성했습니다. public은 호출이 가능하지만, 패키지가 다르기 때문에 default는 호출 불가능했고, private 또한 호출이 불가능합니다.




접근 제어자 - 클래스 레벨


클래스 레벨의 접근 제어자는 public, default만 사용할 수 있습니다. 또한 public 클래스는 반드시 파일명과 이름이 같아야하고, 하나의 자바 파일에 하나의 public 클래스만 존재할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package access.a;  
  
// public 클래스는 파일명과 이름이 같아야 한다.  
// 클래스 레벨의 접근 제어자는 public, default만 있다.  
public class PublicClass {  
    int test;  
    public static void main(String[] args) {  
        PublicClass publicClass = new PublicClass();  
        // 같은 파일 접근 가능  
        DefaultClass1 class1 = new DefaultClass1();  
        DefaultClass2 class2 = new DefaultClass2();  
  
        publicClass.test = 1;  
    }  
}  
  
class DefaultClass1{

}  
class DefaultClass2{

}

예시처럼 public 클래스는 파일에 하나만 존재합니다. public으로 선언한 PublicClass는 파일명과 이름이 같아야합니다. 나머지 DefaultClass1, DefaultClass2 는 현재 패키지에서만 사용 가능한 default 클래스입니다.




캡슐화


캡슐화는 객체지향 프로그래밍의 중요한 개념 중 하나입니다. 캡슐화는 데이터와 해당 데이터를 처리하는 매서드를 하나로 묶어서 외부에서의 접근을 제한하는 방법을 말합니다. 캡슐화를 통해서 데이터의 직접적인 변경을 방지하거나 제한할 수 있습니다. 쉽게 이야기해서 속성과 기능을 하나로 묶고, 외부에는 꼭 필요한 기능만 노출하고 나머지는 모두 내부로 숨기는 것입니다.

객체에는 속성(데이터)기능(매서드)가 있습니다. 속성은 필수로 숨겨야합니다. 자동차의 속도를 사용자가 직접 변경하는게 아닌 것 처럼 속도(데이터)는 숨겨두고 엑셀을 밟는다는 기능을 통해 속도를 변경할 수 있게 해야합니다.

객체의 기능중에도 외부에서는 사용하지 않고 내부에서만 사용되는 기능들이 있습니다. 이러한 기능들도 private로 숨기는 것이 좋습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 캡슐화 예제
package access;  
// 캡슐화 예제  
public class BankAccount {  
    private int balance;  // 속성 private로 숨기기 
  
    public BankAccount() {  
        balance = 0;  
    }  

	// 입금 기능 (public 외부에 노출)
    public void deposit(int amount){  
        if (isAmountValid(amount)){  
            balance += amount;  
        }else {  
            System.out.println("유효하지 않은 금액입니다.");  
        }  
    }  
	// 출금 기능(public 외부 노출)
    public void withdraw(int amount){  
        if(isAmountValid(amount) && balance - amount >= 0){  
            balance -= amount;  
        } else {  
            System.out.println("유효하지 않은 금액이거나, 잔액이 부족합니다.");  
        }  
  
    }  
	// 잔액 확인 기능(public 외부 노툴)
    public void showBalance(){  
        System.out.println("현재 잔액: " + balance);  
    }  
  
  
    // 들어온 금액이 올바른지 판단 (private 내부에서만 사용하는 코드 숨김)
    private boolean isAmountValid(int amount){  
        return amount > 0;  
    }  
}

캡슐화 예제 코드입니다. balance 속성은 private로 내부에 숨겼습니다. deposit, withdraw, showBalance입금, 출금, 잔액확인 등 사용자가 써야할 꼭 필요한 기능으로 public을 사용해 외부에서 접근할 수 있게 합니다. isAmountValid는 입력으로 들어온 금액이 유효한지 판단하는 기능으로, 내부에서만 사용되기 때문에 private로 숨겨줍니다.