[Java] 제어자(접근 지정자, static 제어자)

sobam·2022년 11월 7일
0

자바

목록 보기
18/18
post-thumbnail

📔 학습한 내용을 정리하기 위해 작성하는 게시글입니다.

제어자(modifier)란?


제어자(modifier)란 클래스와 클래스 멤버의 선언 시 사용하여 부가적인 의미를 부여하는 키워드를 의미한다.

  • 자바에서 제어자는 접근 지정자(access modifier)와 기타 제어자로 구분된다.
  • 기타 제어자는 여러 개를 함께 사용할 수 있지만, 접근 제어자를 두 개 이상 같이 사용할 수 없다.
  • 접근 제어자와 기타 제어자는 함께 사용할 수 있다.
  • 기타 제어자 : static, final, abstract, natvie, transient, synchronized, vloatile, strictfp



접근 지정자(access modifier, =접근 제한자)란?


객체 지향에서 정보 은닉(data hiding)이란 사용자가 굳이 알 필요가 없는 정보는 사용자로부터 숨겨야 한다는 개념이다.

그렇게 함으로써 사용자는 언제나 최소한의 정보만으로 프로그램을 손쉽게 사용할 수 있게 된다.

자바에서는 이러한 정보 은닉을 위해 접근 제어자(access modifier)라는 기능을 제공하고 있다.

접근 지정자는 1) 클래스 자체 또는 2) 클래스의 내부 구성 요소(멤버와 생성자) 앞에 위치하며, 말 그대로 각 요소의 접근 범위를 지정하는 제어자이다.

  • 접근 지정자를 붙이는 곳

    1. 클래스
      : 해당 클래스를 import 할 수 있는지 여부를 결정한다.
    2. 생성자
      : 해당 생성자를 호출해서 객체를 생성할 수 있는지 여부를 결정한다.
    3. 필드
      : 해당 필드를 참조할 수 있는지 여부를 결정한다.
    4. 메서드
      : 해당 메서드를 호출할 수 있는지 여부를 결정한다.

클래스의 접근 지정자는 public or default 2가지만 가능하다.



접근 지정자 종류


1. 멤버 및 생성자의 접근 지정자

멤버 및 생성자에는 다음과 같은 네 가지의 접근 지정자를 사용할 수 있다.

  1. public
  2. protected
  3. default(또는 package)
    → 아무것도 작성하지 않으면 default 접근 지정자가 자동으로 설정된다.
  4. private
class Test {
	public int a;
    protected int b;
    int c; //default 접근 지정자 자동 설정
    private int d;
    public void abc() {}
    protected void bcd() {}
    void cde() {} //default 접근 지정자 자동 설정
    private void def() {}
}

2. 클래스의 접근 지정자

클래스에서는 public, default 접근 지정자만 사용할 수 있다.

쉽게 말해, class 키워드 앞에 public이 붙어 있거나 붙어 있지 않거나(default)이다.

  • 클래스에 생성자가 없을 때 컴파일러는 기본 생성자를 자동으로 추가하는데, 이떄 자동으로 추가되는 생성자의 접근 지정자는 클래스의 접근 지정자에 따라 결정된다. (직접 생성자를 정의할 때 클래스와 다르게 지정할 수 있다.)

클래스를 default로 정의하면 다른 패키지에서 임포트가 불가능해 사용할 수 없다.



접근 지정자의 접근 범위


  • private는 자신의 클래스 내부에서만 사용할 수 있다. (즉, 같은 멤버끼리만 사용 가능 / 외부 클래스에서 사용 불가능)
  • default는 같은 패키지 안의 모든 클래스에서 사용할 수 있다.
  • protected는 같은 패키지의 모든 클래스, 다른 패키지의 자식 클래스 안에서 사용할 수 있다.
  • public은 동일 패키지의 모든 클래스, 다른 패키지의 모든 클래스에서 사용할 수 있다.

접근 범위는 public > protected > default > private 순이다.

다른 클래스의 필드를 사용하기 위해서는 객체를 먼저 생성한 후에 사용해야 한다.



static 제어자


static 제어자는 클래스의 멤버(필드, 메서드, 내부 클래스)에 사용하는 제어자이다. static은 클래스의 또는 공통적인이라는 의미이다.

클래스 멤버를 다른 클래스 내에서 사용하기 위해서는 가장 먼저 클래스의 객체를 생성해야 한다. 객체 안에 있을 때 사용할 수 있는 상태가 되는 멤버를 인스턴스 멤버(instance member)라고 한다.

인스턴스 멤버는 멤버 앞에 static이 붙어 있지 않는 멤버를 말한다. 반면,static이 붙어 있는 멤버를 정적 멤버(static member)라고 한다.

  • 정적 멤버의 가장 큰 특징은 객체의 생성 없이 클래스명.멤버명만으로 바로 사용할 수 있다는 것이다.
  • 초기화 블록에도 사용할 수 있다.
  • static 제어자를 변수에 사용하면 해당 변수를 클래스 변수로 만들어 주고, 메서드에 사용하면 해당 메서드를 클래스 메서드로 만들어 준다.
  • 정적 필드는 객체 간 공유 변수의 성질이 있다. (해당 클래스의 모든 인스턴스가 공유한다.)
  • 프로그램 시작시 최초에 단 한 번만 생성되고 초기화된다.
  • 인스턴스를 생성하지 않고도 바로 사용할 수 있게 된다.

static 제어자를 사용할 수 있는 대상
1. 메서드
2. 필드
3. 초기화 블록


1. 인스턴스 필드와 정적 필드

인스턴스 변수는 하나의 클래스로 부터 생성되었더라도 각기 다른 값을 유지하지만, 클래스변수(static 멤버 변수)는 인스턴스에 관계 없이 같은 값을 갖는다. 하나의 변수를 모든 인스턴스가 공유하기 때문이다.

class A {
	int m = 3; //객체 생성 후 사용 가능
    static int n = 5; //객체 생성 없이 사용 가능
}

이러한 인스턴스 필드와 정적 필드는 각 필드 메모리의 저장 위치가 다르다.

인스턴스 필드는 스택 영역에 데이터의 위칫값을, 힙 영역에 실제 데이터 값을 저장한다. 반면, 정적 필드는 힙 영역에 데이터의 위치값을, 클래스 영역(메서드 영역)에 실제 데이터 값을 저장한다.

이러한 이유로 정적 필드는 객체 간 공유 변수의 성질을 가진다.

class A {
	int m = 3; //인스턴스 필드
	static int n  = 5; //정적 필드
}

public class StaticField_1 {
	public static void main(String[] args) {
		A a1 = new A();
		A a2 = new A();
		
		//인스턴스 필드
		a1.m = 5;
		a2.m = 6;
		System.out.println(a1.m);
		System.out.println(a2.m);
		
		//정적 필드
		a1.n = 7;
		a1.n = 8;
		System.out.println(a1.n);
		System.out.println(a2.n);
		
		A.n = 9;
		System.out.println(a1.n);
		System.out.println(a2.n);
	}
}

2. 인스턴스 메서드와 정적 메서드

인스턴스 메서드와 정적 메서드는 모두 메모리의 첫 번째 영역에 위치한다. (인스턴스 메서드는 인스턴스 메서드 영역, 정적 메ㅔ서드는 클래스 내부에 존재함)

class A {
	static void bcd() {
		System.out.println("static 메서드");
	}
}
//정적 메서드 활용1(권장)
A.bcd();
//정적 메서드 활용2(권장X)
A a = new A();
a.bcd();

static 멤버 변수와 static 메서드

대상의미
static 멤버변수- 모든 인스턴스에 공통으로 사용되는 클래스 변수
- 인스턴스를 생성하지 않고도 사용 가능
- 클래스가 메모리에 로드될 때 생성
static 메서드- 인스턴스를 생성하지 않고도 호출 가능
- 인스턴스 멤버들을 직접 사용할 수 없음

3. 정적 메서드 안에서 사용할 수 있는 필드와 메서드

정적 메서드 내에서는 정적 필드 또는 정적 메서드만 사용할 수 있다.

정적 멤버(정적 필드, 정적 메서드)는 객체 생성 없이 사용할 수 있는 반면, 인스턴스 멤버(인스턴스 필드, 인스턴스 메서드)는 반드시 객체를 생성한 후에 사용해야 한다.

만일 정적 메서드 내에 인스턴스 멤버를 사용하면 결국 정적 메서드도 객체를 생성해야 동작한다.

→ 정적 메서드 내부에는 객체 생성 없이 사용할 수 있는 요소인 정적 멤버만 올 수 있다.

  • 정적 메서드 내부에서는 클래스 내부에서 자신의 객체를 가리키는 this 키워드를 사용할 수 없다.
  • 인스턴스 메서드 내에서는 인스턴스 멤버와 정적 멤버 모두 사용 가능

4. 정적 초기화 블록

일반적으로 인스턴스 필드의 초기화는 객체가 만들어지는 시점에서 이루어진다. (생성자 내에서 초기화)
하지만 정적 필드는 객체 생성 이전에도 사용할 수 있어야 하므로 생성자에서는 정적 필드를 초기화할 수 없다.

자바에서는 정적 필드를 초기화하기 위한 문법인 정적 초기화 블록static{}을 제공한다.

static {
	//클래스가 메모리에 로딩될 떄 실행되는 내용
}
  • 정적 초기화 블록은 클래스가 메모리에 로딩될 때 가장 먼저 실행된다.
    → 블록에 정적 필드의 초기화 코드를 넣어두면 클래스가 로딩되는 시점에 초기화됨
class A {
	int a;
    static int b;
    
    static { //static 초기화 블록
		b = 5;
        System.out.println("클래스가 로딩될 때 static block 실행");
	}
    A() {
    	a = 3; //인스턴스 필드의 초기화 위치
    }
}

5. static main() 메서드

자바 가상 머신은 실행 클래스명.main()을 호출해 main() 메서드를 실행한다.
이를 가능하게 하는 것이 static 키워드이다.
만일 main() 메서드가 인스턴스 메서드라면 자바 가상 머신이 객체를 생성하고, 객체의 참조 변수를 이용해 main() 메서드를 호출해야 한다.




🔔 Reference

<Do it! 자바 완전 정복>
http://www.tcpschool.com/java/java_modifier_accessModifier
https://live-for-myself.tistory.com/92
https://kephilab.tistory.com/53
https://88240.tistory.com/447
https://gptjs409.github.io/java/2019/08/22/modifier.html
https://rorobong.tistory.com/125?category=905121

0개의 댓글

관련 채용 정보