다음은 접근 제어자를 달지 않은 Speaker 클래스이다.
요구사항은 다음과 같다.
- Speaker의 볼륨은 절대로 100이 넘어가지 말게 설계해주세요.
public class Speaker {
int volume;
Speaker(int volume){
this.volume = volume;
}
void volumeUp(){
if(volume >=100){
System.out.println("음량을 증가할 수 없습니다. 최대 음량입니다.");
} else{
volume += 10;
System.out.println("음량을 10 증가합니다. ");
}
}
void showVolume(){
System.out.println("현재 음량 : " + volume);
}
}
요구사항에 맞게 설계했기 때문에 해당 볼륨은 100 이상이 넘어가지 않는다!
Speaker speaker = new Speaker(90);
speaker.showVolume();
speaker.volumeUp();
speaker.showVolume();
speaker.volumeUp();
speaker.showVolume();
그러나 다음과 같이 다른 개발자가 해당 요구사항을 못보고 필드에 직접 접근해버린다면 어떻게 할까?
//필드에 직접 접근
System.out.println("volume 필드 직접 접근 수정");
speaker.volume = 200;
speaker.showVolume();
요구사항이 무색하게 음량이 변해버린다.
다음과 같이 private
접근제어자를 필드에 선언함으로서 이러한 위험을 방지할 수 있다.
public class Speaker {
private int volume; //private 사용 -> 스피커 클래스 내에서만 접근 가능
종류
private
: 본인 클래스를 제외한 모든 외부 접근 차단
default
: 같은 패키지를 제외한 외부 접근 차단
protected
: 같은 패키지 + 상속을 제외한 외부 접근 차단
public
: 차단 X사용 위치
클래스
,필드
,생성자
,메서드
❗ 필드와 지역변수는 다르다는 것을 명심하자! 지역변수에는 쓸 수 없다!
종류
public
: 같은 자바파일에 public 클래스는 한 개만 만들 수 있다.
default
: 같은 자바파일에 default 클래스는 무한개 만들 수 있다.❗ 자바규칙 : public 클래스는 반드시 .java파일명이랑 같아야한다.!
1) 캡슐화는 데이터와 기능을 한 클래스 안에 묶어서 사용하는 것이다.
2) 더 나아가서 필요한 정보(메서드)만 외부에 노출시켜 사용하게 하는 것이다.잘 지켜진 캡슐화
1) 데이터는 모두 숨겨라
2) 메서드는 꼭 필요한 메서드만 노출시키고 나머지는 숨겨라.
자바의 메모리 구조는 크게 메서드 영역, 스택 영역, 힙 영역 3개로 나눌 수 있다.
메서드 영역: 클래스 정보를 보관한다. 이 클래스 정보가 붕어빵 틀이다.
스택 영역: 실제 프로그램이 실행되는 영역이다. 메서드를 실행할 때 마다 하나씩 쌓인다.
힙 영역: 객체(인스턴스)가 생성되는 영역이다. new 명령어를 사용하면 이 영역을 사용한다. 쉽게 이야기해서 붕
어빵 틀로부터 생성된 붕어빵이 존재하는 공간이다. 참고로 배열도 이 영역에 생성된다.
방금 설명한 내용은 쉽게 비유로 한 것이고 실제는 다음과 같다
메서드 영역(Method Area): 메서드 영역은 프로그램을 실행하는데 필요한 공통 데이터를 관리한다. 이 영역은
프로그램의 모든 영역에서 공유한다.
클래스 정보: 클래스의 실행 코드(바이트 코드), 필드, 메서드와 생성자 코드등 모든 실행 코드가 존재한다.
static 영역: static 변수들을 보관한다. 뒤에서 자세히 설명한다.
런타임 상수 풀: 프로그램을 실행하는데 필요한 공통 리터럴 상수를 보관한다. 예를 들어서 프로그램에
"hello" 라는 리터럴 문자가 있으면 이런 문자를 공통으로 묶어서 관리한다. 이 외에도 프로그램을 효율
적으로 관리하기 위한 상수들을 관리한다.
스택 영역(Stack Area): 자바 실행 시, 하나의 실행 스택이 생성된다. 각 스택 프레임은 지역 변수, 중간 연산 결
과, 메서드 호출 정보 등을 포함한다.
스택 프레임: 스택 영역에 쌓이는 네모 박스가 하나의 스택 프레임이다. 메서드를 호출할 때 마다 하나의 스
택 프레임이 쌓이고, 메서드가 종료되면 해당 스택 프레임이 제거된다.
힙 영역(Heap Area): 객체(인스턴스)와 배열이 생성되는 영역이다. 가비지 컬렉션(GC)이 이루어지는 주요 영
역이며, 더 이상 참조되지 않는 객체는 GC에 의해 제거된다.
class Bread{ String name; int price; void MethodA(){ } void MethodB(){ } ...C,D,E... }
대충이런 클래스가 있다고 하자!
Bread A = new Bread();
Bread B = new Bread();
라는 인스턴스를 생성하면, Bread 내부에 메서드도 모두 각자 생성되고 메모리를 잡아먹을까?답은 No!
메서드는 모두 같은 역할을 하고 있으므로,인스턴스 변수에는 메모리가 할당
되지만,메서드에 대한 새로운 메모리 할당은 없다
.메서드는 메서드 영역에서 공통으로 관리
되고 실행된다.
힙 영역 : 인스턴스 관리
스택 영역 : 지역변수 관리
메서드 영역 : 그럼 메서드 영역은?
static 은
정적 변수
,static변수
,클래스 변수
다양하게 불리운다.
static
은메서드 영역 안에 있는 static영역에서 관리
된다.변수에다가 static을 선언한 순간, 클래스 내부의 변수에 직접 접근이 가능하다.
public class Data3 { public String name; public static int count; //static public Data3(String name) { this.name = name; count++; } }
public class DataCountMain3 { public static void main(String[] args) { Data3 data1 = new Data3("A"); System.out.println("A count = " + Data3.count); //data3.count가 아닌 클래스접근 Data3 data2 = new Data3("B"); System.out.println("B count = " + Data3.count); Data3 data3 = new Data3("C"); System.out.println("C count = "+ Data3.count); } }
static 영역 안에서는 인스턴스 변수,인스턴스 메서드 호출이 불가능하다.
반대로 인스턴스 영역 안에서는 static 변수, static 메서드 호출이 가능하다.