1. 선언위치에 따른 변수의 종류
변수유형 | 선언 위치 | 사용 범위 | 메모리 | 생성과 소멸 |
---|
지역변수(로컬변수) | 함수 내부에 선언 | 함수 내부에서만 사용 | 스택 | 함수 호출 시 생성, 함수 끝나면 소멸 |
멤버 변수(인스턴스 변수) | 클래스 멤버 변수로 선언 | 클래스 내부에서 사용 private이 아니면 참조 변수로 다른 클래스에서 사용 가능 | 힙 | 인스턴스 생성 시 힙에 생성, 가비지 컬렉터가 메모리 수거할 때 소멸 |
static 변수(클래스 변수) | static 예약어를 사용하여 클래스 내부에서 선언 | 클래스 내부에서 사용하고 private이 아니면 클래스 이름으로 다른 클래스에서 사용 가능 | 데이터 영역 | 프로그램 시작 시 데이터 영역에 생성, 프로그램 끝나고 메모리 해제 시 소멸 |
2. 클래스변수와 인스턴스변수, 지역변수
- 지역 변수
- 함수나 메서드 내부에 선언, 함수 밖에서는 사용할 수 없음
- 지역 변수가 생성되는 메모리를 스택이라고 함
- 함수 호출 시 생성, 함수 반환 시 할당된 메모리 공간이 해제되면서 함께 없어짐
- 멤버 변수
- 인스턴스 변수라고도 함
- 클래스가 생성될 때 힙 메모리에 생성되는 변수
- 클래스의 어느 메소드에서나 사용
- 힙에 생성된 인스턴스가 가비지 컬렉터에 의해 수거되면 메모리에서 사라짐
- 클래스 내부 여러 메서드에서 사용할 변수는 멤버 변수로 선언하는게 좋음
- static 변수
- 사용자가 프로그램을 실행하면 메모리에 프로그램이 상주, 프로그램 영역 중 데이터 영역이 존재, 이 영역에 상수, 문자열, static 변수 생성
- 인스턴스 변수는 객체가 생성되는 new가 되어야 생성, static 변수는 클래스 생성과 상관없이 처음부터 데이터 영역 메모리에 생성
- 데이터 영역은 상수 영역, static 영역이라고 표현하는 경우 존재
- private만 아니라면 클래스 외부에서도 객체 생성과 무관하게 사용 가능
- 프로그램 실행이 끝난 뒤 메모리에서 내려가면 static변수도 소멸
- 계속 메모리에 상주하므로 크기가 너무 큰 변수는 static으로 선언하지 않는 것이 효율적
3. 메서드
- 함수의 한 종류
- 함수란?
- 하나의 기능을 수행하는 일련의 코드
- 어떤 기능을 수행하도록 미리 구현해 놓고 필요할 때마다 호출하여 사용
int num1 = 1;
int num2 = 2;
int num1AddNum2 = num1 + num2;
int grade1 = 90;
int grade2 = 100;
int grade1Addgrade2 = grade1 + grade2;
int num1 = 1;
int num2 = 2;
int num1AddNum2 = add(num1, num2);
int grade1 = 90;
int grade2 = 100;
int grade1Addgrade2 = add(grade1, grade2);
int add(int a, int b) {
return a + b;
}
- 함수의 장점
1. 기능을 나누어 코드를 효율적으로 구현(가독성)
2. 필요할 때마다 함수 호출(재사용, 코드 중복 제거)
3. 오류 난 기능만 찾아서 수정(유지보수가 쉬워짐)
4. 메서드의 선언과 구현
int add(int a, int b) {
return a + b;
}
- 선언
- 반환형 int
- 함수의 결과 값을 반환
- 반환값이 없는 경우 void로 작성
- 함수명 add
- 함수 기능과 관련 있는 이름으로 선언
- 소문자로 시작, 동사 사용, 대부분 카멜케이스 명명규칙 따름
- 매개변수 int a, int b
- 메서드의 지역변수
- 함수 호출 시 자료형에 맞게 함수에 전달, 없는 경우도 존재
- 구현
- 메서드 호출 시 실행시킬 코드 작성
- return 예약어로 결과값을 반환
5. 메서드의 호출
int num1 = 1;
int num2 = 2;
int num1AddNum2 = add(num1, num2);
int add(int a, int b) {
int result = a + b;
return result;
}
6. return문
- return 예약어는 결과값을 반환 한다는 의미, return 값은 반환형에 맞게 작성해야함
- 반환형이 void인 경우 함수 수행 종료
7. JVM의 메모리구조
- Method(=static=class) Area
- 가상 시스템 시작 시 생성
- 컴파일러가 컴파일한 바이트코드(.class)를 클래스 로더가 읽고 로드된 클래스, 변수, Method, static변수, 상수 정보 등이 저장되는 영역
- 논리적으로 힙영역의 일부 (크게 heap area / none-heap area로 나누기도 함)
- 명시적 null 선언 시 GC가 청소
- 모든 Thread가 공유
- Heap Area
- 런타임 시 결정되는 참조 자료형 저장
- 런타임 시 결정되어 동작 중에 문제가 발생할 코드임에도 컴파일 시 에러 안남
- new 연산자로 생성된 객체(인스턴스)가 저장되는 구역
- Garbage Collection 이슈는 이 영역에서 발생
- 객체가 더 이상 쓰이지 않거나 명시적 null 선언 시 GC가 청소
- 모든 Thread가 공유
- Stack Area
- 컴파일 시 결정되는 기본 자료형(&참조변수)이 저장됨
- 컴파일 시 결정됨에 따라 자료형의 범위를 초과한 값 할당 등의 코드가 컴파일 단계에서 검출
- Method 내에서 사용되는 값들(매개변수, 지역변수, 리턴값 등)이 저장되는 구역
- 메소드가 호출될때 FILO로 하나씩 생성되고, 메소드 실행이 완료되면 LIFO로 하나씩 삭제
- 각 Thread별로 하나씩 생성
- PC Register
- CPU의 Register와 역할이 비슷
- 스레드가 시작될 때마다 생성
- 현재 수행중인 JVM 명령의 주소값 저장
- 각 Thread별로 하나씩 생성
- Native Method Stack
- 바이트코드가 아닌 기계어로 작성된 코드 실행 공간
- 다른 언어(c/c++)로 작성된 코드 수행
- Java Native Interface를 통해 바이트 코드로 변환됨
- Java Native Interface : C, C++ 그리고 어샘블리 같은 다른 언어들로 작성된 라이브러리들을 호출하거나 반대로 호출되는 것을 가능하게 하는 프로그래밍 프레임워크
- Java Code를 수행하다 JNI 호출 시 Java Stack에서 Native Stack으로 동적 연결(Dynamic Linking)을 통해 확장됨
- 따라서 나뉘어졌다고는 하나 stack에서 연결할 수 있음
- JNI(Java Native Interface) 호출 시 생성
- 각 Thread별로 하나씩 생성
8. 기본형 매개변수와 참조형 매개변수
- 기본형 매개변수 : 변수의 값 읽기만 가능 (read only)
- 함수 호출시 생성, 함수 끝나면 소멸
- 값을 전달
- 해당 메서드에서 전달받은 값을 다룸
- 참조형 매개변수 : 변수의 값 읽고 저장 가능 (read&write)
- 객체의 주소를 전달
- 해당 메서드에서 전달받은 주소가 가리키는 객체를 다룸
9. 참조형 반환타입
10. 재귀호출(recursive call)
- 자기 자신을 호출하는 메서드를 재쉬 메서드라 함
- 코드는 간결하지만 가독성이 떨어짐
- 반복문 처럼 재귀메서드도 종료지점을 제대로 구현하지 않으면 스택오버플로우가 발생
11. 클래스 메서드(static메서드)와 인스턴스 메서드
- 클래스 메서드(static메서드) : 메서드 앞에 static이 붙은 것
- 인스턴스 멤버와 관련없는 작업을 하는 메서드
- 메서드 내에서 인스턴스 변수 사용 불가
- 객체생성없이 호출이 가능한 메서드, 클래스명.메서드명()으로 메서드 호출
- 인스턴스 메서드 : static이 붙지 않은 메서드
- 인스턴스 멤버와 관련된 작업을 하는 메서드
- 메서드 내에서 인스턴스 변수 사용 가능
- 객체 생성 후, 참조변수.메서드명()으로 메서드 호출
class Math {
long a,b;
long add() { return a + b };
static long add(long a, long b) { return a + b }
}
12. 클래스 멤버와 인스턴스 멤버간의 참조와 호출
- 클래스 메서드는 클래스 변수 사용 가능, 인스턴스 변수 사용 불가
- 클래스 메서드가 호출될 때 인스턴스 변수를 사용할 객체가 있다는 보장을 할 수 없음, 생성 시점이 다름
- 클래스 메서드는 클래스 메서드 호출 가능, 인스턴스 메서드 호출 불가
- 인스턴스 변수 사용할 수 없는 것과 같은 이유
- 인스턴스 메서드는 인스턴스 변수, 클래스 변수 사용 가능
- 인스턴스 메서드는 인스턴스 메서드, 클래스 메서드 호출 가능
참고
- 신용권, ⌜혼자공부하는자바⌟, 한빛미디어, 2019
- 박은종, ⌜Do it! 자바 프로그래밍 입문⌟, 이지스퍼블리싱, 2019
- 티스토리, "Java 런타임 데이터 영역", https://8iggy.tistory.com/229, (2021.10.21)
- 티스토리, "[JVM Internal] JVM 메모리 구조, https://12bme.tistory.com/382
- 티스토리, "기본형매개변수", https://mgyo.tistory.com/271?category=916693