티스토리 뷰

Java

제어자

Alledy 2019. 5. 9. 17:55

제어자(modifier)

  • 제어자는 클래스, 변수, 메서드 선언부에서 사용되며 부가적인 의미를 부여한다.

  • 제어자의 종류

    • 접근 제어자: public, protected, default, private(접근제어자는 한 번에 한 개만 가능)
    • 그 외: static, final, abstract, native, syncronized 등
  • static

    • static이 붙으면 클래스의, 공통적인 이라는 의미이다. 인스턴스 생성없이 호출할 수 있으며, static(클래식) 메서드 내에서는 인스턴스 멤버들을 직접 사용할 수 없다.
  • final

    • final이 붙으면 변경될 수 없다는 의미이다. 클래스에 붙으면 다른 클래스의 조상이 될 수 없다. 메서드에 붙으면 오버라이딩될 수 없다. 변수 앞에 붙으면 값을 변경할 수 없다.

    • 일반적으로 final변수는 상수이므로 선언과 초기화를 동시에 하지만, 인스턴스 변수의 경우 생성자에게 단 한번만 초기화 되도록 할 수 없다. (이 후 변경은 불가)

      class Card {
          final int NUMBER; // 인스턴스 변수이면서 final변수. 초기화 되지 않음.
          Card(int number) {
              NUMBER = number; // this를 붙여 구별할 필요가 없다. 
          }
      }
      
      class FinalCardTest {
          public static void main(String args[]) {
               Card c = new Card(1); // 초기화
              c.NUMBER = 10; // Err! cannot assign a value to final variable NUMBER   
          }
      }
  • abstract

    • 추상클래스는 미완성 메서드가 존재하는 미완성 설계도이므로 인스턴스를 생성할 수 없다.
    • 클래스에 선언하여 해당 클래스 내에 추상메서드가 있음을 알린다. 그리고 해당 메서드 앞에도 붙여 추상 메서드임을 알린다.
    • 메서드에서 abstract과 static은 함께 쓸 수 없음에 주의. static은 body가 있는 메서드에서만 사용할 수 있다.

 

접근 제어자(access modifier)

  • 접근 제어자의 범위

    • private: 같은 클래스 내에서 접근 가능
    • default: 같은 패키지 내에서 접근 가능
    • protected: 같은 패키지 내 & 다른 패키지의 자손클래스에서 접근 가능
    • public: 접근 제한 없음
  • 캡슐화

    • 접근제어자를 사용하는 이유는 클래스 내부의 데이터 보호를 위함이다. 이를 data hiding_이라고 하며 객체지향개념의 캡슐화(_encapsulation)에 해당하는 내용이다.

    • 또는 외부에는 불필요한, 내부적으로만 사용되는 부분을 감추기 위해서이다.

      class Time {
        private int hour, minute, second; // 직접 접근을 막음. 다른 클래스에서 접근 불가. 
      
        // setter를 통한 컨스트럭터
        Time(int hour, int minute, int second) {
          setHour(hour);
          setMinute(minute);
          setSecond(second); 
        }
      
        // getter & setter. public이므로 다른 클래스에서 접근.
        public int getHour() { return hour; }
        public void setHour(int hour) {
          if(hour < 0 || hour > 23) return;
          this.hour = hour; // 같은 Time class내에 위치하므로 접근 가능
        }
      
        public int getMinute() { return minute; }
        public void setMinute(int minute) {
          if(minute > 59 || minute <0) return;
          this.minute = minute;
        }
      
        public int getSecond() { return second; }
        public void setSecond(int second) {
          if(second > 59 || second < 0) return;
          this.second = second;
        }
      
        // print 
        public String toString() {
          return hour + "시  " + minute + "분 " + second + "초";
        } 
      }
      
      class TimeTest {
        Time t = new Time(12,35,30);
        t.hour = 13 // Err! private변수에 직접 접근할 수 없음
        t.setHour(t.getHour()+1);
        System.out.printlin(t.toString()); // prints 13시 35분 30초
      }
      
  • 생성자가 private인 경우

    생성자는 보통 클래스의 접근제어자와 동일하지만 다르게 설정할 수 있다. private으로 설정하면 외부에서 인스턴스 생성은 못하지만 내부에서 생성한 다음, getter로 인스턴스를 반환하게 할 수 있다.

    class Singleton {
    
      // private constructor
      private Singleton() { ... }
    
      private static Singleton s = new Singleton(); // getInstance()에서 사용될 수 있도록 인스턴스가 미리 생성되어 있어야하므로 이것도 static변수로 선언
    
      public static Singleton getInstance() { return s; } // 외부에서 인스턴스 생성없이 접근할 수 있으려면 static이어야 한다.
    }
    

    이렇게 하면 생성자를 통해 직접 인스턴스 생성을 하지 못하기 때문에 사용할 수 있는 인스턴스 개수를 제한할 수 있다. 다만, 생성자가 private인 클래스는 다른 클래스의 조상이 될 수 없다. 자손클래스의 인스턴스 생성 시 조상 클래스의 생성자를 호출하게 되는데, 이것이 private으로 막혀있기 때문이다. 그래서 보통 이런 경우 final을 클래스 앞에 붙여서 조상이 될 수 없는 클래스임을 알리는 것이 좋다.

'Java' 카테고리의 다른 글

Instanceof, 참조변수와 인스턴스의 연결  (0) 2019.05.12
다형성  (0) 2019.05.12
오버라이딩, Super, Super()  (0) 2019.05.08
클래스 상속, 포함  (0) 2019.05.07
메서드 호출  (0) 2019.05.07
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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
글 보관함