총 게시물 25건, 최근 0 건 안내 RSS 글쓰기
이전글  다음글  목록 글쓰기
[1.기본 지식편]

4장 제한자

글쓴이 : 카이로 날짜 : 2014-01-30 (목) 13:09 조회 : 7083
글주소 : http://www.androidside.com/430/54
 
  KGIT뱅크 프로그래밍학원
C언어, 자바프로그래밍, 네트워크, 정보보안, 대학전공대비, IT취업교육상담 신청
www.hrditbank.kr
  IT뱅크 JAVA교육 정지민
프로그래밍 실무중심 교육, 기초~심화, 국비지원무료 취업반, 취업연계 100%
www.kgitbank-jm.co.kr
  서울게임아카데미
추천자바, 2017년 한국 소비자만족지수 1위, 고용노동부국비지원, 수강료조회
www.seoulgame.co.kr
신청하기


4장 제한자
4.1  소개
자바의 제한자(Modifier)에는 접근 범위를 제한하기 위해 사용하는 접근 제한자(Access Modifier)와 속성을 정의하기 위한 형 제한자(Type Modifier)가 있다. 접근 제한자에는 public, protected, private 제한자와 어떤 것도 선언하지 않은 default 제한자가 있으며 형 제한자에는 static, final 등이 있다. 이 장에서는 이러한 제한자의 특징에 대해서 살펴보도록 하겠다.


4.2  접근 제한자(Access Modifier)
접근 제한자는 클래스, 메소드, 변수에 선언하여 접근 범위를 설정하고자 할 경우에 사용하는 제한자이다. 접근 제한자에는 public, protected, private 제한자와 접근 제한자를 선언하지 않았을 경우를 말하는 default 제한자가 있다.

public 제한자는 모든 패키지에서 접근할 수 있다. protected 제한자는 같은 패키지에서는 상속 여부와 상관 없이 접근할 수 있으며 다른 패키지에서는 해당 클래스를 상속한 하위 클래스에서만 접근할 수 있다. 그리고 private 제한자는 다른 클래스에서는 절대 접근할 수 없다. 마지막으로 default 제한자는 같은 패키지에서만 접근할 수 있다. 이러한 접근 범위를 이해하기 쉽게 그림으로 살펴보면 다음과 같다.

그림 4-2-1 같은 패키지에서의 접근 제한자 
4-2-1.jpg

PACKAGE_A 에는 CLASS_A 와 CLASS_B 그리고 CLASS_A 를 상속하는 SUBCLASS 가 선언되어 있다. 이 그림을 통해 같은 패키지에서는 CLASS_B 와 SUBCLASS 모두 CLASS_A 의 private 제한자를 가진 int 형 변수 d 를 제외한 모든 변수에 접근할 수 있다는 것을 알 수 있다. private 제한자를 가진 변수 d 는 CLASS_A 에서만 접근할 수 있다.

그림 4-2-2 다른 패키지에서의 접근 제한자  
4-2-2.png

PACKAGE_A 에는 CLASS_A 가 선언되어 있고 PACKAGE_B 에는 CLASS_B 가 선언되어 있다. 그리고 PACKAGE_C 에는 CLASS_A 를 상속하는 SUBCLASS 가 선언되어 있다. 이 그림을 통해 CLASS_A 를 상속하지 않은 CLASS_B 에서는 public 제한자를 가진 변수 a 에만 접근할 수 있으며 SUBCLASS 에서는 public 제한자를 가진 변수 a 와 protected 제한자를 가진 변수 c 에 접근할 수 있다는 것을 알 수 있다.


지금까지 살펴본 접근 제한자를 정리하면 다음과 같다. 

4-2-3.PNG


4.3  final 제한자(final Modifier)
final 제한자는 최초의 의미를 변경할 수 없도록 하기 위해 사용하는 제한자로서 변수, 메소드, 클래스에 사용할 수 있다. 

1) final 변수
변수에 final 제한자를 선언하면 해당 변수가 초기화된 이후에는 그 값을 절대 수정할 수 없다. 이렇게 선언된 변수를 일반적으로 상수라 부른다.

코드) 사용 예제
final intname1 = "java";
public final intname2 = "java2";
final public intname3 = "java3";

 
2) final 메소드
메소드에 final 제한자를 선언하면 해당 메소드를 하위 클래스에서 오버라이딩(Overriding)해서 사용할 수 없다. 그래서 하위 클래스에서 상위 클래스의 특정 메소드를 오버라이딩할 수 없도록 강제하고 싶은 경우에 final 제한자를 메소드에 선언한다.

코드) 사용 예제
class Test {
    public finalString getName1() {
        // ...
    }
    final publicString getName2() {
        // ...
    }
}

3) final 클래스
클래스에 final 제한자를 선언하면 해당 클래스를 다른 클래스에서 상속해서 사용할 수 없다. 그래서 특정 클래스가 하위 클래스에 의해서 변경되는 것을 막고 싶은 경우에 final 제한자를 클래스에 선언한다.

코드) 사용 예제
final class Test {
    // ...
}
 
public final class Test2 {
    // ...
}

마지막으로 final 제한자와 관련된 특징들을 정리하면 다음과 같다.
 
정리) final 제한자

1. final 메소드가 정의되어 있지 않아도 final 클래스로 선언할 수 있다.

2. final 메소드가 한 개라도 선언되어 있더라도 final 클래스로 선언하지 않아도 된다.

3. final 클래스는 상속할 수 없다.

4. final 메소드는 오버라이딩 할 수 없다.

5. final 변수는 초기화된 이후에는 수정할 수 없다.



4.4  abstract 제한자(abstract Modifier)
abstract 제한자는 메소드나 클래스가 완벽하지 않다는 것을 하위 클래스에게 알려 부족한 부분을 채울 수 있도록 강제하기 위한 제한자이다. 이 제한자는 메소드나 클래스에 선언할 수 있다.

1) abstract 메소드
특정 메소드를 현재 클래스가 아닌 하위 클래스에서 정의하도록 강제하고 싶은 경우에 메소드에 abstract 제한자를 선언한다. 이렇게 선언된 메소드를 추상 메소드라고 부른다. 

코드) 사용 예제
public abstract String getName1();
abstract public String getName2();
 

2) abstract 클래스
특정 클래스를 반드시 상속해서만 사용할 수 있도록 강제하고 싶은 경우에는 클래스에 abstract 제한자를 선언한다. 이렇게 선언된 클래스를 추상 클래스라고 하며 이 클래스는 자체적으로 객체를 생성할 수 없기 때문에 반드시 상속해서만 사용할 수 있다.

이 제한자를 사용하는데 있어서 주의할 점이 있는데 그것은 추상 메소드가 해당 클래스에 한 개라도 선언되어 있을 경우에는 해당 클래스를 abstract 제한자로 반드시 선언해야 한다는 것이다. 반대로 추상 메소드가 한 개도 선언되어 있지 않을 경우에는 abstract 제한자를 클래스에 선언할 수도 있고 선언하지 않을 수도 있다.

코드) 사용 예제
public abstract class Test1 {
    public abstract String getName1();
    String getName2() {
        // ...
    }
}
 
public abstract class Test2 {
    public String getName1() {
        // ...
    }
    String getName2() {
        // ...
    }
}

다음 예제 코드는 추상 클래스의 객체를 생성하는 것을 보여준다. 첫 번째 클래스인 MyTest1 은 추상 클래스인 Test1 를 상속하여 구현하지 않았기 때문에 Test1 의 객체를 생성할 때 에러가 발생한다. 하지만 MyTest2 에서는 Test1 를 상속하고 있으며 추상 메소드인 getName1() 메소드를 구현하고 있기 때문에 객체 생성시 에러가 발생하지 않는다.

코드) 사용 예제
public classMyTest1 {
    public static voidmain(String[] args) {
        Test1 t = new Test1(); // 에러발생
    }
}
 
public classMyTest2 extends Test1 {
    publicString getName1() { // 추상 메소드 구현
        // ...
    }
 
    public static voidmain(String[] args) {
        MyTest2 t = new MyTest2();
    }
} 

마지막으로 abstract 제한자와 관련된 특징들을 정리하면 다음과 같다.

정리) abstract 제한자

1. 추상 메소드가 선언되어 있지 않아도 추상 클래스로 선언할 수 있다.

2. 추상 메소드가 한 개라도 선언되어 있다면 반드시 추상 클래스로 선언해야 한다.

3. 추상 클래스는 반드시 상속해서 사용해야 한다. 


4.5  static 제한자(static Modifier)
static 제한자는 특정 변수나 메소드를 객체 생성 이전에 메모리에 로딩하고 싶을 때 선언하는 제한자이다. 객체 생성 이전에 메모리에 변수나 메소드가 로딩되어 있다는 것은 클래스의 객체를 생성하지 않고도 바로 접근해서 사용할 수 있다는 것을 의미한다. 

1) static 변수
static 제한자가 선언되어 있는 변수는 클래스 로딩시 자동적으로 메모리에 올라가게 되기 때문에 static 변수를 사용하기 위해 객체를 생성할 필요가 없다.

코드) 사용 예제
class Test1 {
    public static String name = "java";
}
 
class Test2 {
    public static voidmain(String[] args) {
        System.out.println(Test1.name);
 
        /*
        //Test1 클래스의 name 변수가static 제한자로 선언되어 있지 않을 경우
        Test1 t1 = new Test1();
        System.out.println(t1.name);
        */
    }
}
 
예제 코드에는 Test1 클래스와 Test2 클래스가 선언되어 있다. Test2 클래스에서 Test1 클래스의 name 변수의 값을 화면에 출력하는 경우에 name 변수가 static 제한자로 선언되어 있을 경우와 그렇지 않을 경우의 코드가 달라진다. static 제한자가 선언되어 있을 경우에는 Test1 클래스의 name 변수가 메모리에 이미 로딩되어 있기 때문에 Test1 클래스의 객체를 생성하지 않고 Test1.name 으로 바로 접근할 수 있지만 static 제한자로 선언되어 있지 않을 경우에는 반드시 Test1 클래스의 객체를 생성한 후 name 변수에 접근해야 한다.


2) static 메소드
static 변수와 마찬가지로 static 제한자를 메소드에 선언하면 해당 메소드는 클래스 로딩시 메모리에 로딩된다. 그렇기 때문에 static 메소드를 선언한 클래스의 객체 생성 없이 메소드를 바로 호출해서 사용할 수 있다.

코드) 사용 예제
class Test1 {
    private staticString name = "java";
 
    public staticString getName() {
        return name;
    }
}
 
class Test2 {
    public static voidmain(String[] args) {
        System.out.println(Test1.getName());
 
        /*
        //Test1 클래스의 getName() 메소드와 name 변수가 static 제한자로 선언되어 있지 않을 경우
        Test1 t1 = new Test1();
        System.out.println(t1.getName());
        */
    }
}
 
위 소스 코드는 static 변수에서 살펴본 소스 코드와 매우 유사하다. 다만 달라진 부분은 name 변수에 접근하기 위한 getName() 메소드가 추가 되어 있다는 것이다. 그리고 이 코드에서 한가지 유의해서 봐야 할 부분이 있는데 그것은 getName() 메소드이다. 왜냐하면 이 메소드에서 반환하고 있는 name 변수가 static 제한자로 선언되어 있지 않다면 getName() 메소드에서 name 변수에 접근할 수 없기 때문이다. 다시 말하면 static 메소드에서 외부의 변수에 접근하기 위해서는 해당 변수가 static으로 선언되어 있어야 한다. 이를 확인하고 싶다면 Test1 클래스의 name 변수에 선언된 static 제한자를 제거하고 실행하면 된다.


마지막으로 static 제한자와 관련된 특징들을 정리하면 다음과 같다.

정리) static 제한자
1. static 제한자가 선언된 변수나 메소드는 객체 생성 없이 접근할 수 있다.

2. static 제한자는 클래스에 선언할 수 없다.

3. static 제한자는 지역 변수에 선언할 수 없다.



4.6  native 제한자(native Modifier)
native 제한자는 자바를 사용해서는 제공할 수 없는 기능을 C 언어와 같은 다른 언어를 이용해서 제공하기 위해 사용하는 제한자이다. 이 제한자를 사용해서 다른 언어의 메소드를 호출하기 위해서는 다음 예제의 sayHello() 메소드와 같이 메소드의 몸체는 구현하지 않고 선언만 하면 된다. 그리고 이 메소드를 통해 호출하기 위한 sayHello() 메소드가 정의되어 있는 라이브러리를 로딩하면 된다. 

다음 예제에서는 Hello 라는 라이브러리를 로딩하여 Hello 라이브러리에 포함되어 있는sayHello() 메소드를 호출하도록 되어 있다. 여기서 로딩되는 Hello 라이브러리에는 실제 sayHello() 메소드가 정의되어 있다. 그리고 이 라이브러리의 파일 이름은 윈도우 시스템에서는 Hello.dll 이 될 것이고 솔라리스라면 libHello.so 가 될 것이다.

코드) 사용 예제
public classTest {
    static {
        System.loadLibrary("Hello");
    }
    public native voidsayHello();
   
    public static voidmain(String[] args) {
        Test t = new Test();
        t.sayHello();
    }
}


4.7  transient 제한자(transient Modifier)
transient 제한자는 객체가 직렬화될 때 특정 변수는 직렬화의 대상이 되지 않도록 하기 위해서 사용하는 제한자로서 멤버 변수에만 선언할 수 있다. 여기서 말하는 직렬화는 메모리상에 생성된 객체를 파일로 저장하거나 네트워크로 전송하기 위해 객체를 바이트 형태로 변환하는 것을 말하며 이를 가능하게 하기 위해서는 해당 클래스는 반드시 Serializable 인터페이스를 구현하고 있어야 한다. 

코드) 사용 예제
public classTest implements Serializable {
    publicString name = "java";
    public transient intage = 20;
 
    publicString getName() {
        return name;
    }
}
 
위의 소스 코드의 Test 클래스를 직렬화하면 transient 제한자가 선언된 age 변수는 직렬화 대상에서 제외된다. 또한 직렬화는 변수를 대상으로만 하기 때문에 생성자와 메소드도 직렬화되지 않는다.


4.8  synchronized 제한자(synchronized Modifier)
synchronized 제한자는 스레드 프로그래밍을 할 경우 자주 사용하는 제한자로서 스레드간에 동기화 처리를 하여 특정 데이터가 여러 스레드에 의해 예측될 수 없는 상태로 변경되는 것을 막기 위해서 사용한다. 이 제한자가 선언된 블록이나 메소드는 한 번에 하나의 스레드만이 접근하여 해당 코드를 실행할 수 있다. 또한 이 제한자는 코드를 동기화하기 위해서 제공되는 제한자이기 때문에 변수에는 선언할 수 없다.

코드) 사용 예제
public classTest {
    public int cnt = 0;
 
    public synchronized voidadd1() {
        cnt++;
    }
 
    public voidadd2() {
        synchronized(this) {
            cnt++;
        }
    }
} 


4.9  volatile 제한자(volatile Modifier)
volatile 제한자는 멀티 스레드 환경에서 synchronized 제한자처럼 동기화를 제공하기 위해 사용하는 제한자로서 synchronized 제한자와는 다르게 변수에만 선언할 수 있다. 이 제한자가 선언된 변수는 여러 스레드가 동시에 변경할 수 없기 때문에 멀티 스레드 환경에서도 데이터 무결성을 보장할 수 있다.

[TIP&TECH]
데이터 무결성(data integrity)은 데이터를 인가되지 않은 방법으로 변경할 수 없도록 하는 성질을 말한다.

코드) 사용 예제
public classTest {
    public volatile int cnt = 0;
 
    public voidadd() {
        cnt++;
    }
}


4.10  제한자 선언 위치
제한자들을 선언할 수 있는 위치는 정해져 있다. 예를 들어, abstract 제한자는 변수에 선언할 수 없으며 생성자에도 선언할 수 없다. 이러한 선언 위치를 정리하면 아래와 같다.

4-10-1.PNG


4.11  제한자 TIP
아래 표는 지금까지 살펴본 제한자들의 주요 특징을 정리한 것이다.

정리) 제한자 주요 특징
1. 메소드에는 접근 제한자 public, protected, private 중 하나만 선언할 수 있다.
2. 클래스에는 abstract와 final를 함께 선언할 수 없다.
3. abstract 메소드에는 private, static, final, native, strictfp, synchronized를 선언할 수 없다.
4. abstract와 native 메소드는 몸체를 가질 수 없다.
5. abstract 메소드를 포함한 클래스는 반드시 abstract로 선언해야 한다.
6. final 메소드를 포함한 클래스를 반드시 final로 선언할 필요는 없다.
7. final 필드는 volatile로 선언할 수 없다.
8. 메소드에는 native와 strictfp를 함께 선언할 수 없다.
이 글은 무단전제나 무단배포가 금지된 글입니다. 공유하고자 한다면 제목과 링크만 공유하기 바랍니다.


로그인 창이 있는 "정보 수정"에서
서명 이쁘게 등록해보세요 ^^

glaxy 2014-01-30 (목) 19:44
이것도 해봐야죠~
감사해요~
댓글주소
jjinuri 2014-02-19 (수) 14:18
잘 보고 있습니다 ㅋ
감사합니다. ^^
댓글주소
퍼플덕 2014-03-11 (화) 15:58
아 조금씩 어려워 지네요. ㅜㅜ
댓글주소
YGFree 2014-08-08 (금) 14:14
잘 봤습니다~
댓글주소
필연 2015-03-04 (수) 15:44
잘 봤습니다~
댓글주소
플룩스 2015-03-24 (화) 15:40
역시 두몽님이시다.
댓글주소
공부좀 2015-06-26 (금) 23:23
최고 의 명강의
댓글주소
대학생예비창… 2015-07-01 (수) 10:33
최고임
댓글주소
잘반10세 2015-10-05 (월) 17:55
정말 핵심만 집고 가는 기분이에요
댓글주소
indist 2016-10-03 (월) 03:55
알겠어요
댓글주소
후후빠 2016-10-14 (금) 08:06
thanks
댓글주소
이전글  다음글  목록 글쓰기

총 게시물 25건, 최근 0 건 안내 RSS
번호 분류 제목 추천 조회
25 0.소개  0.1 머리말 37 29 9860
24 0.소개  0.2 목차 16 10 6655
23 1.기본 지식편  0장 기본 지식편 27 30 10149
22 1.기본 지식편  1장 객체지향 프로그래밍 33 25 13749
21 2.코드 지식편  1장 0. 변수, 데이터형 20 15 7254
20 2.코드 지식편  1장 1. 가장 빠른 변수는 지역 변수이다. 19 14 7496
19 2.코드 지식편  1장 2. 멤버 변수를 중복 초기화하지 않는다. 17 11 7434
18 2.코드 지식편  1장 3. 멤버 변수의 디폴트 값에 대해 알아야 한다. 17 7 7632
17 2.코드 지식편  1장 4. 블록 내에서 사용할 변수는 지역 변수로 선언해야 한다. 16 12 6595
16 2.코드 지식편  1장 5. 자동 변수를 사용할 때는 항상 초기값을 설정해야 한다. 19 10 7225
15 2.코드 지식편  1장 6. 상수는 되도록 기본 데이터형을 사용해야 한다. 16 11 6885
14 2.코드 지식편  1장 7. 상수는 사용시 주의해야 한다. 20 11 6557
13 2.코드 지식편  1장 8. 변수는 되도록 사용 시점에 선언해야 한다. 15 7 5443
12 2.코드 지식편  1장 9. 객체보다는 기본 데이터형을 사용해야 한다. 13 7 5702
11 1.기본 지식편  1장 객체지향 프로그래밍 체크 포인트 17 9 6046
10 1.기본 지식편  2장 소스 코드 구성 28 15 9956
9 1.기본 지식편  2장 소스 코드 구성 체크 포인트 8 8 5472
8 1.기본 지식편  3장 클래스 구성 22 10 9648
7 1.기본 지식편  3장 클래스 구성 체크 포인트 6 4 5195
6 1.기본 지식편  4장 제한자 11 6 7084
5 1.기본 지식편  4장 제한자 체크 포인트 4 3 4887
4 1.기본 지식편  5장 연산자 11 7 9567
3 1.기본 지식편  5장 연산자 체크 포인트 4 5 5610
2 0.소개  스피드 자바의 오프라인 서적의 평. 11 8 6374
 


Copyright ⓒ www.androidside.com. All rights reserved.
채팅 권한: 글쓰기 1개
2레벨 이상만 대화 가능
공개 채팅: 평일 !(9시 ~ 17시),토,일
안사2 변경사항 보러가기 챗방이 잘 안보이면 크롬에서 접속해주세요
챗방 숨기기 |  챗방 보이기