[Java] Modifier(접근제어자)

Hoplin·2023년 1월 7일
0

제어자란?

자바에서 제어자란, 클래스, 변수 혹은 메소드 등 선언부에 함께 사용되어, 확장 범위 및 부가적인 의미를 부여해주는 역할을 한다. 제어자는 두 종류로 나뉘며, 각각 무엇이 있는지 살펴보자.

  • 접근 제어자 : public, protected, default, private
  • 기타 제어자 : static, final, abstract, native, synchronized ... etc

이 두개의 큰 차이점은, 기타 제어자의 경우에는 여러개를 조합해서 사용하는것이 가능하다. 단 접근제어자는 하나만 선택해서 사용할 수 있다.

접근제어자 범위

접근 제어자는 객체지향 특성중 정보 은닉을 위해 사용한다. 사용자가 알 이유가 없거나, 알아서는 안되는 정보는 숨겨야 하기도 하며, 사용자가 이용해야 하는 경우에는 사용자가 사용할 수 있도록 해주어야 한다. 각각의 접근제어자는 제한의 강화에 따라 강도가 다르다. 그리고 강화 순서는 아래와 같다

각각의 특징을 살펴보자

접근 제어자특징
public선언된 클래스 외부로 공개되며, 해당 객체를 사용하는 프로그램 어디서나 접근할 수 있다.
protected이 멤버를 선언한 클래스 멤버, 같은 패키지에 속한 멤버, 해당 멤버가 존재하는 클래스를 상속받은 자식 클래스의 멤버에서만 접근할 수 있다.
default접근제어자를 명시하지 않는경우, 기본값이며, default를 가지는 멤버는 같은 클래스와 같은 패키지에 속하는 멤버에서만 접근할 수 있다.
private자신이 선언된 클래스 이외에서는 접근할 수 없다.외부에서 접근하기 위해서는 public객체를 통해 접근이 가능하다.(동일한 패키에서는 default객체로도 괜찮다)

static

static 은 '공통적인' 이라는 의미를 가진다. 인스턴스 변수는 하나의 클래스로부터 생성되었어도 서로 다른 값을 가진다. 하지만 static을 사용하여 선언된 클래스변수는 인스턴스 관계없이 같은 값을 가진다. 클래스 변수는 기본적으로 모든 인스턴스가 동일하게 공유하기 때문이다. static키워드가 붙은 자원들은 클래스가 로드될때 Method Area에 함께 미리 로드되는것을 기억하자.(이로인해, 클래스 메소드는 인스턴스 멤버/메소드를 사용하지 못함)

static 키워드가 붙은 멤버변수, 메소드, 초기화블록은 인스턴스 생성 없이 클래스를 통해 접근할 수 있다. static키워드로 선언된 자원들은, 메모리에 로딩된 후 프로그램이 종류될때 같이 사라진다. 인스턴스 멤버를 사용하지 않는 메소드라면, static을 붙여서 선언하고 사용하는것이 더 빠르다.

제어자 대상 의미
static 멤버변수 - 모든 인스턴스에 공통적으로 공유되는 클래스변수가 된다
- 클래스변수는 인스턴스를 생성하지 않고도 사용 가능하다
- 클래스가 메모리에 로드될 때 생성된다.
메소드 - 인스턴스를 생성하지 않고도 호출이 가능한 메소드가 된다.(클래스 메소드)
- static 메소드 내에서는 인스턴스 멤버들을 직접 사용할 수 없다

예시 코드는 아래와 같다.

class Testing{
    public static void main(String[] args){
        StaticResourceTest srt = new StaticResourceTest();
        StaticResourceTest srt2 = new StaticResourceTest();
        StaticResourceTest srt3 = new StaticResourceTest();

        System.out.println(StaticResourceTest.getNumber());
    }
}

class StaticResourceTest{
    private static int number;
    // static 초기화 블록
    static {
        // 명시적 초기화로 대체해도 됨
        number = 100;
    }
    // 초기화 블록
    {
        ++number;
    }

    public static int getNumber(){
        return StaticResourceTest.number;
    }
}

final

final은 자바에서 정적상수를 선언할때 사용하는 키워드이다. 이는 단지 정적상수를 선언할때 뿐만 아니라, 클래스, 메소드, 지역변수를 선언할때도 사용할 수 있다.

제어자 대상 의미
final 클래스 변경될 수 없는 클래스로서 확장될 수 없다는 의미를 가진다. 이는 다른 클래스의 조상 클래스가 될 수 없다(즉 상속 불가)
메소드 변경될 수 없는 메소드로서, final로 지정된 메소드는 Override를 할 수 없다.
멤버변수 및 지역변수 정적상수 선언의 의미이다.

예시 코드는 아래와 같다.

// final 키워드가 쓰인 클래스
final class FinalResourceTest{
    // 일반적으로 정적상수는 Uppercase로 표기한다
    final int MAX = 10;
}

// Inherit이 불가능하다고 오류가 나온다.
class ExtendFinal extends FinalResourceTest{

}

// final 키워드가 쓰인 메소드
class FinalResourceTest{
    // 일반적으로 정적상수는 Uppercase로 표기한다
    final int MAX = 10;
    final void finalMethod(){
        System.out.println("Final method");
    }
}

// Inherit이 불가능하다고 오류가 나온다.
class ExtendFinal extends FinalResourceTest{
    @Override
    void finalMethod(){
        
    }
}

간단하게 싱글톤 구현해보기

위의 접근제어자 개념을 활용해 싱글톤을 구현해보자. 싱글톤의 간단한 개념을 말하자면, 인스턴스를 여러개 생성하지 못하게끔 하고 하나로만 사용하도록 하는 디자인패턴이다.

생성자를 우선 private로 해야한다. 그리고 클래스변수로 하나의 인스턴스를 가지고 있는 변수를 가지고 있어야한다. 단 이 인스턴스는 클래스 외부에서 접근해서는 안된다. 추가적으로 인스턴스를 외부에 반환하는 메소드인 getInstance()라는 메소드가 있어야한다.

class Singleton{
    private static Singleton instance = new Singleton();
    private Singleton(){}

    public static Singleton getInstance(){
        return instance;
    }
}

private접근제어자로 된 클래스는 다른 클래스의 조상클래스가 될 수 없다. 그 이유는 자손 클래스가 접근할 수 있는 조상 클래스의 생성자가 없기 떄문이다. 그렇기 때문에 싱글톤으로 구현된 클래스 앞에 final을 붙여서 다른 크래스의 조상이 될 수 없다라는것을 명시해주는것도 좋다.

final class Singleton{
    private static Singleton instance = new Singleton();
    private Singleton(){}

    public static Singleton getInstance(){
        return instance;
    }
}
profile
더 나은 내일을 위해 오늘의 중괄호를 엽니다

0개의 댓글