1. 제어자 


1) 클래스, 메소드 혹은 변수에 대해서 추가적인 기능을 더하는 것 

2) 선언할 때 선언부에 추가적으로 입력하여 사용 

3) 제어자를 추가 선언한다고 해서 생성한 메소드나 변수의 본래 기능은 변하지 않음

4) 제어자의 키워드에 따라서 선언한 자원들에게 특별한 의미(기능)를 부여하기 위해 사용


5) 제어자의 종류 



2. 접근 지정자 (Access modifier) 


# 자원에 대해서 외부에서 접근(사용, 참조 등) 가능한 범위를 제어한다. 

# 클래스나 메소드 혹은 변수의 선언부를 정의할 때 가장 처음 등장하는 것이 접근 제어자

# 접근 제어자는 호출하는 클래스의 위치나 관계에 따라서 자원에 대한 접근을 막거나 허락 가능


* 접근 제약이 높은 순: private > default > protected > public

* 접근 범위가 넓은 순: public > protected > default > private


1) public 

- 한 프로젝트 영역까지 공개


2) protected

- 같은 패키지에서 사용 가능

- 패키지가 달라도 상속관계라면 사용 가능


3) default

- 키워드가 없는 상태

- 패키지 상태라고 부른다.


4) private

- 클래스 밖에서는 절대 사용 금지

- 주로 변수에 붙여 변수의 직접 접근을 막는다.

- 대신 get 메서드와 set 메서드를 통해 값의 검증을 거친 데이터만 들어올 수 있도록 한다.

- 이를 '캡슐화' , '은닉화' 라고 표현한다. 


5) 접근 제어자의 종류에 따른 접근 범위 




6) 접근 제어자들과 선언 가능한 자원들 

- 모든 접근 제어자들이 모든 자원들에 사용될 수 있는 것은 아님

- 클래스: 오직 public과 default 접근 제어자를 이용하여 선언할 수 있음

- 변수, 메서드: 모든 접근 지정자 사용 가능 




3. 접근 제어자가 중요한 이유 


접근 제어자는 객체 지향 프로그래밍의 캡슐화 개념을 구현할 수 있는 키워드다. 

즉, 개발자가 원하는 클래스 변수나 메소드들만 public 키워드로 클래스 외부에 노출하고, 중요한 데이터는 private 키워드로 감출 수 있기 때문이다.

캡슐화를 사용하는 대표적인 예는 데이터를 저장하기 위한 클래스다.

클래스의 내부 속성 즉, 저장하고자 하는 데이터는 private 키워드로 완전히 외부와 차단시킨다. 

그리고 데이터를 얻거나 저장하기 위해서는 public 키워드를 사용해서 get/set 이름으로 시작하는 메소드를 선언한다.


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
39
40
41
42
43
44
45
46
package captulationex;
 
public class Student {
 
    private String name;
    private int id;
    private int age;
    private int score;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public int getScore() {
        return score;
    }
 
    public void setScore(int score) {
        if (<= score && score <= 100) {
            this.score = score;
        } else {
            System.out.println("0~100점 사이의 점수 입력!");
        }
    }
}
 
cs

# 설명 

Line 5~8: 데이터들을 private 로 지정하여 외부와 차단한다. 

Line 14~45: public + set / get 메소드를 통하여 데이터를 이용한다. 


1
2
3
4
5
6
7
8
9
10
11
12
package captulationex;
 
public class School {
    public static void main(String[] args) {
 
        Student hgd = new Student();
        
        hgd.setName("홍길동");
        System.out.println(hgd.getName());
        
    }
}
cs






4. 접근 제어자를 통한 객체 접근 


# 1. 생성자의 접근 제어자가 public 인 경우

1
2
3
4
5
6
7
8
package captulationex;
 
public class Single {
 
     public Single() {}
 
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package captulationex;
 
public class SingleMain {
    public static void main(String[] args) {
 
        // public Single() {} 
         Single s1 = new Single();
         Single s2 = new Single();
         Single s3 = new Single();
        
         System.out.println(s1);
         System.out.println(s2);
         System.out.println(s3);
 
    }
}
cs

# 실행 결과 



# 설명 

Line 7~9: public 으로 생성된 생성자를 통하여 각각 인스턴스화한다. 

때문에 각기 다른 메모리 주소값을 참조하는 비효율적인 결과가 나타난다. 



# 2. 생성자의 접근 제어자가 private 인 경우

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package captulationex;
 
public class Single {
 
    private Single() {}
    private static Single s = null;
    public static Single getInstance() {
 
        // 메모리 주소를 하나만 참조할 수 있도록 제한
        if (s == null) {
            s = new Single();
        }
        return s;
    }
}
cs

# 설명 

Line 5: 생성자의 접근 제어자를 private 로 지정하여 Single 클래스 외의 접근을 차단한다. 

Line 6: Single 객체를 null 로 선언한다. 이도 마찬가지로 private 로 지정하여 외부의 접근을 차단한다. 

    따라서 다른 클래스에서 Single 객체는 생성자를 통하여 인스턴스화 할 수 없다. 

Line 7: 클래스 메서드로 반환타입이 Single 객체인 메서드 선언부 

Line 10~12: Single s 객체가 null 이라면 new 를 통한 인스턴스화를 실행한다. 

   그러나 객체가 한 번 이상 인스턴스화 된다면 null 값 대신 주소값을 참조하게 된다. 

   null 값이 아닌 주소값을 가지게 될 때 인스턴스화를 더 이상 실행하지 않고 이미 생성된 객체 s 를 반환한다. 

   즉, 메모리 주소를 하나만 참조할 수 있도록 제한하여 메모리 절약을 실행한다.

   

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package captulationex;
 
import java.util.Calendar;
 
public class SingleMain {
    public static void main(String[] args) {
 
        Single s1 = Single.getInstance();
        Single s2 = Single.getInstance();
        
        System.out.println(s1);
        System.out.println(s2);
 
        Calendar cal = Calendar.getInstance();
        
    }
}

cs

# 실행 결과 


# 설명 

Line 14: getInstance()  메서드를 통한 객체 접근의 대표적인 예