💡 제한자란?
public | protected | default | private | |
---|---|---|---|---|
클래스 | O | X | O | X |
생성자 | O | O | O | O |
멤버변수* | O | O | O | O |
멤버메소드 | O | O | O | O |
지역변수* | X | X | X | X |
클래스, 인스턴스, 지역변수 예제
- 클래스 변수: 클래스 영역에 위치한 변수 중 static 키워드를 가지는 변수
- 인스턴스 변수 : 클래스 영역에 위치한 변수 중 static 키워드를 가지지 않는 변수
- 지역 변수 : 메소드나 생성자, 초기화 블록 내에 위치한 변수
멤버변수 : 클래스 변수 + 인스턴스 변수
class Field {
static int classVar = 10; // 클래스 변수 선언
int instanceVar = 20; // 인스턴스 변수 선언
}
public class Member01 {
public static void main(String[] args) {
int var = 30; // 지역 변수 선언
System.out.println(var + "\n"); // 지역 변수 참조
Field myField1 = new Field(); // 인스턴스 생성
Field myField2 = new Field(); // 인스턴스 생성
System.out.println(Field.classVar); // 클래스 변수 참조
System.out.println(myField1.classVar);
System.out.println(myField2.classVar + "\n");
myField1.classVar = 100; // 클래스 변수의 값을 변경
System.out.println(Field.classVar); // 클래스 변수 참조
System.out.println(myField1.classVar);
System.out.println(myField2.classVar + "\n");
System.out.println(myField1.instanceVar); // 인스턴스 변수 참조
System.out.println(myField2.instanceVar + "\n");
myField1.instanceVar = 200; // 인스턴스 변수의 값을 변경
System.out.println(myField1.instanceVar); // 인스턴스 변수 참조
System.out.println(myField2.instanceVar);
}
}
결과
3010
10
10100
100
10020
20200
20
위에서 밝힌 것처럼 자바는 접근제한자를 통해 타 객체로부터의 접근을 제한한다. 이를 **은닉화**
라고 한다. 아래 캡슐화 예제에서 같이 살펴보겠다.
은닉한 멤버는 **캡슐화**
를 통해 사용한다.
**캡슐화**
란 관련이 있는 데이터 그리고 동작들을 하나로 묶여 요약하고, 사용자에게는 내부적인 접근을 허용하지 않는 대신 사용의 편의성을 제공한다. 아래 예제를 통해 자세히 설명한다.
- 데이터 보호의 장점 : 은닉화를 통해 데이터의 접근을 제어할 수 있음
- 유지 보수성의 장점 : 객체에 대한 수정 작업으로 인해 객체 활용도에 문제가 발생한다면, 제품 하나에 대한 수정이 부담스러울 것이나, 자바에서는 각 기능을 하나의 모듈(부품)처럼 활용하여 객체간의 이식성이 높고 독립적인 면을 유지하는 장점이 있음
- 사용자 편의성의 장점 : 원리를 파악할 필요 없이 사용법만 익혀서 사용
public class Variable {
private int a = 10; // 은닉화
// 생성자
public Variable() {
System.out.println("private 멤버 a 값: " + this.a);
}
// 캡슐화 메소드
public void setA(int n){
a = n;
}
public int getA() {
return a;
}
}
public class MethodTest {
public static void main(String[] args) {
Variable v = new Variable();
// System.out.println(v.a); // 은닉화된 멤버 a 호출 불가
v.setA(100); // 캡슐화로 a 접근 가능
System.out.println(v.getA());
Variable v1 = new Variable();
}
}
결과
private 멤버 a값 : 10
100
private 멤버 a값 : 10
👉🏻 static 변수/메소드는 클래스가 메모리에 로드될 때 자동으로 생성(즉, 인스턴스 생성이 불필요)
👉🏻 static 멤버변수는 클래스변수로서 모든 인스턴스가 공유함
👉🏻 static 메소드에서는 인스턴스 멤버를 직접 사용할 수 없음
👉🏻 final 변수는 값을 변경할 수 없는 상수 (상수는 대문자로 선언, 대부분 상수는 선언 & 초기화)
👉🏻 final 클래스는 부모 클래스가 될 수 없음 (확장 불가능)
👉🏻 final 메소드는 변경될 수 없는 (오버라이딩 불가능) 메소드 (자식 클래스에서 이 메소드 재정의 x)
static과 final의 차이점?
**static**
은 따로 인스턴스 생성이 불필요하며, 메모리에 로드될 때 자동적으로 생성된다.
**final**
은 따로 변수 선언을 해야 하며, 고정된 값을 지닌다.🎈 홍길동이라는 사람은 태어나기 이전(객체가 생성되기 이전)에 이미 ‘홍’이라는 성을 지닌다.
→static
특징
(static의 값은 변할 수 있지만 되도록 변경하지 않음. 값이 변하더라도 개념이나 의미는 변하지 않음)🎈 출생신고를 하게 되면 고유한 주민등록번호를 발급받을 것잉고, 바뀌지 않는 고정된 값이다.
🎈 수학공식 PI값은 3.141592… 이다.
→final
특징
(선언 시 변경이 불가)
왜 static final을 같이 쓰는가?
**static**
은 의미를 고정하는 역할을 수행한다.(값도 대부분 고정)
**final**
은 선언하게 되면 값이 바뀔 수 없다.따라서 클래스에서 사용할 해당 멤버변수의 데이터와 의미 등을 고정하기 위해 대부분의 경우에 함께 사용한다.
👉🏻 abstract 클래스는 객체 생성을 할 수 없다. 상속을 통해 자식 클래스에 의해 완성이 가능하다.
👉🏻 abstract 메소드는 선언부만 작성하고, 구현부는 작성하지 않은 채로 남겨둔다. 이 또한 상속을 통해 자식 클래스에서 구현하여 완성한다.
👉🏻 동기화에 사용함. 여러 스레드가 동시에 접근하는 것을 금지함.
👉🏻 메소드에 사용하거나 코드블럭을 설정하여 사용 가능
synchronized void increase() {
count++;
System.out.println(count);
}
void increase() {
synchronized(this) {
count++;
}
System.out.println(count);
}
static | final | abstract | |
---|---|---|---|
클래스 | △ (내부 클래스 가능) | O | O |
생성자 | X | X | X |
멤버변수 | O | O | X |
멤버메소드 | O | O | O |
지역변수 | X | O | X |
https://gyrfalcon.tistory.com/entry/JAVA-접근-제한자
https://hongong.hanbit.co.kr/자바-접근-제한자의-종류와-차이public-protected-private/
https://sthyeok.tistory.com/58
https://nowonbun.tistory.com/302
https://kadosholy.tistory.com/123