남궁성님의 Java의 정석(3rd Edition)을 보고 정리한 글입니다.
1. 제어자
- 클래스, 변수, 메서드의 선언부에 사용되며, 부가적인 의미를 부여한다.
- 하나의 대상에 여러 개의 제어자를 조합해서 사용할 수 있다.(접근제어자는 하나만 사용 가능)
- 접근제어자와 그 외 제어자로 나눌 수 있다.
2. 접근제어자
- public: 접근제한이 없음.
- protected: 같은 패키지 내에서, 다른 패키지의 자식클래스에서 접근 가능
- default: 같은 패키지 내에서 접근 가능
- private: 같은 클래스 내에서 접근 가능
접근 제어자를 사용하는 이유는 외부로부터 데이터를 보호하며, 외부에는 불필요한, 내부적으로만 사용되는 부분을 감추기 위해 사용한다. ⇒ 캡슐화
3. 그 외 제어자(static, final, abstarct, native, transient, synchronized, volatle, strictfp)
a. static 제어자
- 클래스 멤버(변수, 메서드)라고도 한다.
- static 키워드를 사용하여 정적 변수와 정적 메서드를 선언한다.
- 정적메서드 내부에서는 정적 멤버만 사용할 수 있다.
- 멤버변수와 메서드에서만 static 제어자 사용 가능
- static 멤버들은 Heap영역이 아닌 Method Area영역에 할당된다.
- Method Area 영역에 할당된 메모리는 모든 객체가 공유하여 어디서든지 참조할 수 있다는 장점
- 프로그램 종료시까지 메모리 공간을 차지하고 있기 때문에 성능적인 부분에서 단점
static 선언
static int a = 3 // 정적 필드
static void examplMethode() { // 정적 메서드
// ...
}
static 필드와 static 메서드 예시
public class Class1 {
int total = 0;
static int grandTotal = 0; // 정적 필드를 선언하는 선언문
void accumulate(int amount) {
total += amount;
grandTotal += amount; // 정적 필드를 사용하는 명령문
}
static int getGrandTotal() { // 정적 메소드 선언
// grandTotal = total; // 정적 메서드 내부에는 정적 멤버만 사용가능하다.(일반 멤버는 인스턴스 소속이므로)
return grandTotal;
}
}
public class Class2 {
public static void main(String[] args) {
ClassEx8_static obj1 = new Class1();
ClassEx8_static obj2 = new Class1();
obj1.accumulate(10);
System.out.println("obj1.total = " + obj1.total);
System.out.println("obj1.grandTotal = " + Class1.grandTotal);
obj2.accumulate(20);
System.out.println("obj2.total = " + obj2.total);
System.out.println("obj2.grandTotal = " + Class1.grandTotal);
}
}
실행결과
obj1.total = 10
obj1.grandTotal = 10
obj2.total = 20
obj2.grandTotal = 30
b. final 제어자
final 키워드를 사용하는 3가지 경우
- 변수
- 프리미티브 타입
- 레퍼런스 타입
- 메서드 인자
- 정적필드 vs 일반필드
- 메서드
- 클래스
1. 변수
- a. 프리미티브 타입
- 프리미티브 타입 final을 선언할 경우 초기화 이후 변경할 수 없는 상수값이 된다.
final int a = 5;
a = 10 // 에러 발생
- b. 레퍼런스 타입
- 레퍼런스 타입에 final을 선언할 경우 그 변수에 객체(참조 값)을 변경할 수 없지만, 속성은 변경할 수 있다.
final Car car = new Car();
// car = new Car(); //객체를 변경할 수 없음
car.setColor("green"); //객체 필드는 변경할 수 있음
- c. 메서드 인자
- 매개변수에 final을 붙이면, 메서드 안에서 해당 변수를 변경할 수 없습니다.
public void setPrice(final int price) {
weight = 1; //final 인자는 메서드안에서 변경할 수 없음
}
- d. 정적필드 vs 일반필드
- 클래스 멤버변수가 static이냐 아니냐에 따라 초기화 시점이 달라진다.
- static 변수는 정적 초기화 블록에서 초기환 된다.
- 일반필드는 인스턴스 초기화 블록에서 초기화가 된다.
- 클래스 멤버변수가 static이냐 아니냐에 따라 초기화 시점이 달라진다.
public class class1 {
final static int a = 3;
// 값과 함께 선언시
// 정적 초기화 블록에서(클래스 로드시 딱 한번만 실행)
final int b = 10;
// 값과 함께 선언시
// 인스턴스 초기화 블록에서(인스턴스 생성할 때마다 블록이 실행 됨)
}
2. 메서드
- 메서드에 final을 붙일 경우에 오버라이딩이 금지된다.
public class Car {
public final void makewheel() {
System.out.println("4개");
}
}
public class Car extends Morning {
//final로된 메서드는 override할수 없음
public void makeSound() {
}
}
3. 클래스
- 클래스에 final을 붙일 경우 상속이 금지된다.
public final class Pet {
}
//Pet 클래스가 final 클래스로 선언되어 상속할 수 없음
public class Dog extends Pet {
}
그 외 제어자는 추후에 자세하게 정리하겠다.
c. abstarct
- 클래스와 메서드에 사용
- 추상 클래스, 추상 메서드를 지정할 때 사용(자세한 내용은 뒤에 설명)
d. native
- 메서드 선언에 사용
- 네이티브 메서드는 자바 코드에서 직접 구현되지 않고, 네이티브 라이브러리(일반적으로 C 또는 C++로 작성)에서 제공되는 메서드
- 이를 통해 자바 언어로 작성된 프로그램이 네이티브 코드와 상호 작용
e. transient
- 인스턴스 변수에 transient를 지정하면 해당 변수는 직렬화 프로세스에서 무시
- 변수의 상태를 영구적으로 저장하거나 전송할 때 해당 변수를 제외
f. synchronized
- 메서드 또는 블록에 사용
- 여러 스레드 간에 동시에 실행되지 않도록 보장
- 스레드 간의 동기화를 제어하여 공유 리소스에 대한 안전한 접근을 보장하는 데 사용
g. volatle
- 변수에 사용
- 항상 메인 메모리에서 읽고 쓰도록 보장
- 다중 스레드 환경에서 공유된 변수의 일관성을 유지하는 데 사용
h. strictfp
- 클래스, 인터페이스, 메서드에 사용
- 부동 소수점 연산이 항상 동일한 결과를 생성
'Programming > Java' 카테고리의 다른 글
[Java] 내부 클래스(inner class)란? (0) | 2023.10.16 |
---|---|
[Java] 다형성 (추상클래스 - 인터페이스) (0) | 2023.10.16 |
[Java] package와 import (0) | 2023.10.16 |
[Java] 상속관계와 포함관계 (0) | 2023.10.13 |
[Java] 생성자와 this / super (0) | 2023.10.13 |