본문 바로가기

프로그래밍/JAVA

[JAVA] 제어자(modifier)

JAVA의 정석(2nd Editionm) (남궁 성 著) 254p~264p 를 참조해 코드를 작성했으며

개인적인 공부 내용을 적은 것이므로 오류가 있을 수 있습니다.


0. 들어가기에 앞서


제어자는 " 규제 " 이다.

사회도 커지면 질서가 필요하듯이

프로그래밍 코드가 추가되면서 내용이 늘어나면 역시 질서가 필요하다.


1. 제어자(modifier)



modify에 대한 뜻을 찾아보면 다음과 같다. '한정어'라는 말이 잘 어울린다.



<출처 : http://www.noesispoint.com/jsp/scjp/SCJPch3.htm>



접근제어자 - public, protected, default, private (오른쪽으로 갈수록 범위가 좁아짐)

그        외 - static, final, abstract, native, transient, synchronized, volatile, strictfp


제어자는 클래스, 멤버변수 또는 메서드의 선언부에 주로 사용. 여러 제어자를 조합하는 것이 가능하다.

단, 접근 제어자는 네 가지 중 하나만 선택해서 사용할 수 있다.



2. static(메서드, 멤버변수, 초기화블럭) - 클래스의, 공통적인


static은 영어 뜻으로 '움직이지 않고 고정된' 이라는 의미이다.

따라서 정적(靜的)이라고도 한다.


클래스변수 (static멤버변수)는 인스턴스에 관계없이 같은 값을 갖는다. 

하나의 변수를 모든 인스턴스가 공유한다. static이 붙으면 인스턴스를 생성하지 않고도 사용할 수 있다.


static을 이용하면 인스턴스를 생성하지 않고도 호출이 가능해서 더 편리하고 속도도 더 빠르다.



3. final(메서드, 멤버변수, 지역변수, 클래스) - 마지막의, 변경될 수 없는


abstract 제어자가 상속을 강제하는 것이라면

final은 상속 / 변경을 금지하는 규제이다.


만약에 static final double PI = 3.14;라면

모든 클래스에서 공유(static) 할 수 있지만 , 그 값을 변경할 수 없는(final) 원주율 3.14가 된다.


거의 모든 대상에 사용할 수 있다. 

변수 : 값을 변경할 수 없는 상수가 되며,

메서드 : 오버라이딩을 할 수 없고

클래스 : 자신을 확장하는 자손클래스를 정의하지 못한다.



대표적인 final 클래스로는 String과 Math가 있다.



4. 생성자를 이용한 final 멤버변수 초기화


final이 붙은 변수는 상수이므로 일반적으로 선언과 초기화를 동시에 한다.

반면에 인스턴스변수의 경우 생성자에서 초기화 할 수 있다.


5. abstract(클래스, 메서드) - 추상의, 미완성의


메서드의 선언부만 작성하고 실제 수행내용은 구현하지 않은 추상메서드를 선언하는데 사용된다.



6. 접근 제어자(access modifier)


접근제어자(access modifier)를 사용할 수 있는 곳은 - 클래스, 멤버변수, 메서드, 생성자  4가지이다.

( 제어자(modifer)를 사용하는 곳은 클래스, 멤버변수 또는 메서드의 선언부에 주로 사용 )

<출처 : https://opentutorials.org/course/1223/6061>

<출처 : 오픈 튜토리얼>

 오픈튜토리얼의 저자는 "public과 private만 구분해서 사용만해도 더 안전하고 결고한 에플리케이션을 만들 수 있을 것이다."라고 이야기 한다.


   "public"은 누구나 접근할 수 있는 은행 창구

   "private"은 관계자 외 출입이 금지된 금고라고 명쾌하게 설명한다.

만약에, 인스턴스 변수가 private로 지정되어있다면 이 변수는 객체 외부에서 호출될 수 없다.


<사용 가능한 접근제어자>

클래스 : public, (default)

메서드, 지역변수 : public, protected, (default), private)

지역변수 : 사용가능한 접근 제어자 없음


7. 접근 제어자를 이용한 캡슐화


접근 제어자를 사용하는 이유는  클래스 내부에 선언된 데이터를 보호하기 위해서이다.

데이터가 유효한 값을 유지하도록, 비밀번호 같은 중요 데이터를 외부에서 변경하지 못하도록 제한한다.

이것을 데이터 감추기(data hiding), 객체지향개념의 캡슐화(encapsulation)라고 한다.


또다른 이유는 ② 외부에서 접근할 필요가 없는 멤버들을 private로 만들어 복잡성을 줄일 수 있다.


8. 생성자의 접근 제어자


위의 예제처럼 생성자에 접근 제어자를 사용해 인스턴스의 생성을 제한할 수 있다.


생성자에 private로 지정하면 외부에서 생성자에 접근할 수 없으므로 인스턴스를 생성할 수 없게 된다.

그래도 클래스 내부에서는 인스턴스의 생성이 가능하다.


대신 인스턴스를 생성해서 반환해주는 public 메서드를 만들어 외부에서 이 클래스의 인스턴스를 사용할 수 있다. 이 메서드는 public인 동시에 static이어야 한다.



private Singleton()는 생성자이고, private를 통해 인스턴스를 생성하지 못하게 하고

public 메서드를 통해 인스턴스에 접근함으로써 사용할 수 있는 인스턴스의 개수를 제한할 수 있다.


또한, 생성자가 private인 클래스는 다른 클래스의 조상이 될 수 없다. 왜냐하면 자손클래스의 인스턴스를 생성할 때 조상클래스의 생성자를 호출해야 하는데, 생성자의 접근 제어자가 private이므로 자손 클래스에서 호출이 불가능하기 때문이다.


그래서 클래스 앞에 final을 추가해야 한다.



9. 제어자(modifier)의 조합


1. 메서드에 static과 abstract를 함께 사용할 수 없다.

 - static 메서드는 몸통이 있는 메서드에만 사용 가능


2. 클래스에 abstract와 final을 동시에 사용할 수 없다.

 - 클래스에 사용되는 final은 클래스를 확장할 수 없다는 의미이고

   abstract는 상속을 통해서 완성되어야 한다는 의미이므로 서로 모순


3. abstract 메서드의 접근 제어자가 private일 수 없다.

 - abstract 메서드는 자손클래스에서 구현해주어야 하는데 

   접근 제어자가 private이면 자손클래스에서 접근할 수 없기 때문이다.


4. 메서드에 private와 final을 같이 사용할 필요는 없다.

 - 접근 제어자가 private인 메서드는 오버라이딩(상속받은 내용을 변경)될 수 없다.

   이 둘 중 하나만 사용해도 의미가 충분하다.


10. 내가 헷갈리는 점을 정리해보자


 1. 접근제어자 그 외 제어자는 무슨 차이인가?

 접근 제어자(access modifier) : "멤버" or "클래스"에 사용되어 외부에서 접근하지 못하도록 제한한다.

     제어자(modifier) : "클래스", "멤버변수", "메서드 선언부"에 사용되며 여러 제어자 조합이 가능하다.


 2. public과 static은 무슨 차이인가

public은 접근제어자

static은 제어자


 3. private와 final은 무슨 차이인가

private는 접근제어자

final은 제어자