본문 바로가기
멀티캠퍼스 풀스택 과정/Java의 정석

자바의 정석3-4 제어자(static, final, abstract, 접근제어자)

by 이쟝 2022. 1. 1.

제어자(modifier)

클래스와 클래스의 멤버(멤버 변수, 메서드)에 부가적인 의미 부여

 

제어자의 분류

 

접근 제어자 public, protected, (default), private
그 외 static, final, abstract, native, transient, synchronized, volatile, strictfp

 

-> default는 아무것도 안 붙이는 것을 의미함

- 하나의 대상에 여러 제어자를 같이 사용가능(접근 제어자는 하나만 네 개 중 하나!)

 

 

-> 순서는 상관없지만 보통 접근제어자를 제일 왼쪽에 작성

-> class 앞에는 접근제어자만 가능 나머지는 상관없음

 


static – 클래스의, 공통적인

 

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

 

class StaticTest {
	static int width = 200;    // 클래스 변수(static변수, cv)-간단초기화
	static int height = 120;   // 클래스 변수(static변수, cv)-간단초기화
	
	static {                   // 클래스 초기화 블럭(초기화 수행하는 문장 넣음)
		 // static변수의 복잡한 초기화 수행
	}
	
	static int max(int a, int b) { // 클래스 메서드(static메서드)-iv,im 사용불가
		return a > b ? a : b;
	}
}

 

 

final – 마지막의, 변경될 수 없는

 

제어자 대상 의미
final

클래스 변경될 수 없는 클래스, 확장될 수 없는 클래스가 된다.(String, Math)
그래서 final로 지정된 클래스는 다른 클래스의 조상이 될 수 없다.
메서드 변경될 수 없는 메서드, final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다.
멤버변수 변수 앞에 final이 붙으면, 값을 변경할 수 없는 상수가 된다.

지역변수

 

final class FinalTest {       // 조상이 될 수 없는 클래스
	final int MAX_SIZE = 10;  // 값을 변경할 수 없는 멤버변수(상수) 

	final int getMaxSize() {
		final int LV = MAX_SIZE;   // 오버라이딩할 수 없는 메서드(변경불가)
		return MAX_SIZE;           // 값을 변경할 수 없는 지역변수(상수)
	}
}

 

abstract – 추상의, 미완성의

 

제어자 대상 의미
abstract 클래스 클래스 내에 추상 메서드가 선언되어 있음을 의미한다.(미완성 클래스)
-> 미완성 설계도(클래스)라서 제품(객체) 생성 불가
메서드 선언부만 작성하고 구현부는 작성하지 않는 추상 메서드임을 알린다. (미완성 메서드)

 

abstract class AbstractTest {   // 추상 클래스(추상 메서드를 포함한 클래스)
	abstract void move();       // 추상 메서드(구현부가 없는 메서드)
}

AbstractTest a = new AbstractTest;  // 에러! 추상 클래스의 인스턴스 생성불가

 

-> 추상클래스를 상속받아서 완전한 클래스(구상 클래스)를 만든 후에 객체 생성 가능!!!


접근 제어자(access modifier): 네 개 중 한 개만 사용 가능

 

private 같은 클래스 내에서만 접근이 가능하다.
(default) 같은 패키지(폴더) 에서만 접근이 가능하다.(접근제어자를 아무것도 안 붙이는 것)
protected 같은 패키지(폴더) 에서, 그리고 다른 패키지의 자손클래스에서 접근이 가능하다.
public 접근 제한이 전혀 없다.

 

public(접근제한없음) > protected(같은 패키지 + 다른 패키지 자손) > (default) (같은 패키지) > private(같은 클래스)

- class 앞에는 public아니면 (default)만 올 수 있다.

- 멤버들에는 네 개 다 붙일 수 있다.

 

예제1 

pkg1 패키지 안에 MyParent클래스+ MyParentTest 클래스 / pkg2 패키지 안에 MyParent을 상속 받는 MyChild 클래스 + MyParentTest2 클래스

 

package pkg1; //pkg1폴더 안에 MyParent.class와 MyParentTest.class가 있음

public class MyParent {   
	private   int prv;  // 같은 클래스
	          int dft;  // 같은 패키지
	protected int prt;  // 같은 패키지 + 자손(다른 패키지)
	public    int pub;  // 접근제한없음.

	public void printMembers() {
		System.out.println(prv);  // OK
		System.out.println(dft);  // OK
		System.out.println(prt);  // OK
		System.out.println(pub);  // OK
	}	
}

class MyParentTest {

	public static void main(String[] args) {
		MyParent p = new MyParent();
//		System.out.println(p.prv);  // 에러!(다른 클래스여서)
		System.out.println(p.dft);  // OK
		System.out.println(p.prt);  // OK
		System.out.println(p.pub);  // OK

	}

}


package pkg2; //pkg2 폴더안에 Mychild.class와 MyParentTest2.class가 있음

import pkg1.MyParent;  // ctrl+shift+O

class MyChild extends MyParent {  // MyParent의 자손
	public void printMembers() {
//		System.out.println(prv);  // 에러
//		System.out.println(dft);  // 에러
		System.out.println(prt);  // OK(다른 패키지이지만 My Parent의 자손이어서)
		System.out.println(pub);  // OK 
	}	
}
public class MyParentTest2 {
	public static void main(String[] args) {
		MyParent p = new MyParent();
//		System.out.println(p.prv); // 에러
//		System.out.println(p.dft); // 에러
//		System.out.println(p.prt); // 에러(다른 패키지이고, parent의 자손도 아니기 떄문)
		System.out.println(p.pub); // OK

	}
}