private

private 접근 제한

private 키워드를 사용하면 클래스 외부의 접근을 차단하겠다는 의미이다.

접근을 차단하기만 하면 이용할 수 없기 때문에, 반드시 우회적으로 이용할 수 있는 방법을 마련해야 하며, 변수, 메소드, 생성자 등 클래스의 구성요소들을 원한다면 private 으로 잠금 처리할 수 있다.

데모 1 : 점수가 0~100점으로 설정되는 클래스

class Student {
    private String name;
    private int score;
    
    public void setName(String name){
        this.name = name;
    }
    public void setScore(int score){
        if(score < 0){
            return;
        }
        this.score = score;
    }
    public String getName(){
        return this.name;
    }
    public int getScore(){
        return this.score;
    }
}

public class AccessModifierExample01 {
    public static void main(String[] args){
        Student stu = new Student();
        stu.setName("마리오");
        stu.setScore(50);//허용
        stu.setScore(-50);//차단
        
        System.out.println("이름 : " + stu.getName());
        System.out.println("점수 : " + stu.getScore());
    }
}

score를 설정하는 과정을 그림으로 살펴보면 다음과 같다.

클래스에 직접 접근하는 것은 아니지만 인스턴스가 클래스의 형태와 동일하기 때문에 클래스에 표기하였으며, score로의 직접 접근은 private 키워드에 의해 차단되었기 때문에 우회적으로 setScore 메소드를 이용할 수밖에 없으며, setScore에 작성된 조건으로 인하여 0~100값을 제외한 나머지는 차단됨을 알 수 있다.

데모 2 : 객체 생성이 불가능한 클래스 만들기

이 내용을 살펴보기에 앞 static 관련 내용을 먼저 알아야 한다.

정적(static)
class Utility {
    
    private Utility(){}
    
    public static int random(int begin, int end){
        Random r = new Random();
        return r.nextInt(end - begin + 1) + begin;
    }
    
}

public class AccessModifierExample02 {
    public static void main(String[] args){

        //Utility utility = new Utility();//error 발

        int dice = Utility.random(1, 6);
        System.out.println("주사위 = " + dice);
        
        int lotto = Utility.random(1, 45);
        System.out.println("로또 = " + lotto);
        
    }
}

Utility 클래스의 경우 단순 계산을 위한 클래스로 객체 생성 없이 편하게 호출할 수 있도록 메소드들을 모두 정적(static) 처리하고 생성자를 private 처리하여 객체 생성이 불가능하도록 구현하였다. 이처럼 자주 사용할 것으로 예상되는 객체와 연관없는 기능들은 정적 처리하고 객체 생성을 금지하면 좀 더 나은 성능을 보여준다.

데모 3 : 싱글톤(singleton) 클래스

class Manager {
    private String id;
    private int point;
    
    private Manager(String id, int point){
        this.id = id;
        this.point = point;
    }
    
    public void setId(String id){
        this.id = id;
    }
    public String getId(){
        return this.id;
    }
    public void setPoint(int point){
        this.point = point;
    }
    public int getPoint(){
        return this.point;
    }
    
    public void print(){
        System.out.println("매니저 ID : " + this.id);
        System.out.println("가용 포인트 : " + this.point);
    }
    
    private static Manager manager = new Manager("master", 5000);
    public static Manager getInstance(){
        return manager;
    }
    
}

public class AccessModifierExample03 {
    public static void main(String[] args){
        
        Manager m1 = Manager.getInstance();
        m1.print();
        
        Manager m2 = Manager.getInstance();
        m2.print();
        
    }
}

데모 2에서는 객체로서의 기능을 완전히 사용하지 못하도록 구성했지만, 데모 3에서는 객체의 기능은 유지한 채 개수만 제어하기 위한 코드를 작성하였다.

private Manager(String id, int point){
    this.id = id;
    this.point = point;
}

우선 생성자를 잠금 처리하여 객체 생성이 외부에서 이루어지지 못하도록 진행하였다.

private static Manager manager = new Manager("master", 5000);
public static Manager getInstance(){
    return manager;
}

클래스 내부에서 정적 변수로 master라는 id, 5000포인트를 가진 매니저 객체를 단 하나만 생성해둔 뒤 이용할 수 있도록 getter 메소드를 구현해두었다. 따라서, 외부에서는 이미 만들어진 manager만 대여 형식으로 이용할 수 있게 되며, 의도적으로 해당 클래스의 객체 수를 모든 프로그램을 통틀어 1개로 제어할 수 있다.

이렇게 객체의 전체 개수를 제어하여 일관성을 유지하도록 구현하는 방식을 싱글톤(singleton) 방식이라고 한다.

Manager m1 = Manager.getInstance();
m1.print();

Manager m2 = Manager.getInstance();
m2.print();

위의 코드에서 m1과 m2는 같은 대상을 바라보는 참조 변수이다.

Last updated