객체지향 프로그래밍에 대해 이어서 알아보도록 하겠습니다.
이번 글에서는 변수의 위치에따른 종류와 메서드에 대해서 알아보겠습니다.
위치에 따른 변수의 종류
자바에서 변수는 해당 변수를 어느 위치에 선언하느냐에 따라
클래스변수, 인스턴스변수, 지역변수의 세 종류로 나뉩니다.
인스턴스변수(instance variable)
인스턴스변수는 클래스 영역에 선언되며, 해당 클래스의 인스턴스를 생성할 때 만들어집니다.
때문에 인스턴스변수를 사용하려면 당연히 인스턴스를 먼저 생성해야 합니다.
또한 인스턴스는 여러 개 생성할 수 있고, 각 인스턴스의 인스턴스변수는 서로 독립적입니다.
각 인스턴스마다 독립적인 데이터를 저장해야 할 때, 인스턴스변수를 사용합니다.
클래스변수(calss variable)
클래스변수는 선언되는 위치는 인스턴스변수와 똑같습니다.
다른 점은 클래스변수는 각각 인스턴스에서 독립적이지 않고, 모든 인스턴스가 하나의 클래스변수를 공유한다는 점입니다.
클래스변수를 선언하는 방법은 인스턴스변수의 앞에 static만 붙여주시면 되고,
이러한 특성 때문에 클래스변수는 공유변수(shared variable)라고도 합니다.
모든 인스턴스가 공통적인 데이터를 공유해야 하는 경우 클래스 변수로 선언해서 사용합니다.
또한 인스턴스변수는 인스턴스를 생성해야 사용 가능하지만,
클래스변수는 인스턴스를 생성하지 않고도 사용할 수 있으며 클래스명.클래스변수와 같이 사용합니다.
이때 인스턴스변수의 경우 인스터스가 생성될 때 메모리 공간에 인스턴스변수를 위한 공간이 마련되고,
클래스변수의 경우 프로그램 시작시에 클래스변수를 위한 공간이 마련됩니다.
또한 이 메모리 공간은 프로그램이 종료될 때까지 유지됩니다.
이 클래스변수의 앞에 public을 붙이면 '전역변수(global variable)'이 되어 프로그램 내 어디서나 접근할 수 있게 됩니다.
지역변수(local variable)
메서드 내에 선언되어 메서드 내에서만 사용 가능하며, 메서드가 종료되면 소멸되어 사용할 수 없게 됩니다.
우리가 지금까지 for문에서 int i와 같은 형태로 선언한 변수 또한 지역변수라고 할 수 있으며
for문 내에서만 이 변수를 사용할 수 있다는 사실은 이미 알고 계실 겁니다.
이렇듯 메서드뿐만 아니라 for문, while문, 중괄호 등으로 지역을 나눠 지역변수를 선언할 수 있습니다.
메서드
메서드는 어떤 특정한 작업을 수행하기 위한 명령문, 코드들의 집합입니다.
메서드는 실행되면 독립적인 작업을 수행하고 종료되기도 하고, 특정한 값을 전달받아 다시 특정한 값을 반환할 수 있습니다.
이러한 메서드를 사용하는 이유는 반복적으로 사용되는 코드를 줄이기 위해서입니다.
자신이 자주 사용할 내용의 코드를 메서드로 작성해 놓고 필요한 곳에서 호출만 하면 편리하게 사용할 수 있습니다.
또한 해당 코드의 변경이 필요할 때 메서드 부분만 고치면 되기 때문에 유지보수가 편리합니다.
우리가 지금까지 코드를 작성해왔던 main또한 메서드이며, main함수는 프로그램 내에 하나만 존재할 수 있고
프로그램이 시작되면 자동으로 실행됩니다.
메서드를 작성하는 방법은 다음과 같습니다.
public class example{
리턴타입 메서드이름(타입 변수명, 타입 변수명, ....){
수행할 코드
}
int add(int a, int b){
int res = a + b;
return res;
}
public static void main(String[] args){
int res;
res = add(10, 10);
}
}
메서드는 크게 선언부와 구현부로 나뉘어 있는데, 선언부에서는 리턴타입, 메서드이름, 그리고 괄호 안에 매개변수를 선언합니다.
이때 반드시 값을 return해야하며, 값을 return하고 싶지 않다면, 리턴타입을 void로 지정해주시면 됩니다.
매개변수는 위의 int a, int b와 같이 해당 메서드를 호출하는 메서드에서 넘겨주는 데이터를 저장할 변수입니다.
이때 add(10, 10)에서 두 10은 전달인자라고 하며, 전달인자와 매개변수의 자료형은 동일해야 합니다.
메서드의 경우 특이하게도 두 메서드의 이름이 서로 같아도 매개변수가 다르면 둘은 서로 다른 메서드로 인식됩니다.
구현부는 메서드에서 실행할 코드를 적어 넣는 곳입니다.
위의 코드의 경우 두 int형 변수를 전달인자로 받아서 두 수를 더한 값을 다시 main함수에 반환하는 함수입니다.
메서드가 정상적으로 종료되는 경우는 메서드의 블럭 내의 마지막 문장까지 수행하거나,
메서드내에서 return을 만났을 경우의 두 가지가 있습니다.
또한 위의 코드를 실행하려고 하면 오류가 발생하는 것을 볼 수 있습니다.
왜냐하면 클래스메서드인 main은 같은 클래스 내의 인스턴스메서드인 add를 호출할 수 없기 때문입니다.
때문에 add메서드를 클래스메서드로 만들어 주어야 코드를 실행할 수 있습니다.
또는 새로 클래스를 정의한 뒤 그 클래스 내에 add메서드를 정의하고, main함수에서 해당 클래스의
인스턴스를 생성한 뒤, 그 인스턴스를 통해 add메서드를 실행시키는 방법을 사용할 수 있습니다.
클래스메서드와 인스턴스메서드는 기본적으로 클래스변수, 인스턴스변수와 같다고 보시면 됩니다.
또한 클래스메서드 내에서는 인스턴스 변수를 사용할 수 없으니 주의하시길 바랍니다.
JVM의 메모리 구조
프로그램이 실행되면 JVM은 시스템으로부터 프로그램을 수행하는데 필요한 메모리를 할당받고, JVM은 이 메모리를
용도에 따라 여러 영역으로 나누어 관리합니다.
그 중 세가지 주요영역(method area, 호출스택, heap)에 대해서 알아보도록 합시다.
1. 메서드영역(method area)
-프로그램 실행 중 어떤 클래스가 사용되면, JVM은 해당 클래스의 클래스파일을 읽어서 분석하여,
클래스에 대한 정보를 이곳에 저장합니다. 이때, 그 클래스의 클래스변수도 이 영역에 함께 생성됩니다.
2. 힙(heap)
-인스턴스가 생성되는 공간으로서, 프로그램 실행 중 생성되는 인스턴스는 모두 이곳에 생성됩니다.
즉 인스턴스변수들이 생성되는 공간입니다.
3. 호출스택(call stack 또는 execution stack)
-호출스택은 메서드의 작업에 필요한 공간을 제공합니다. 메서드가 호출되면, 호출스택에 호출된 메서드를 위한 메모리가 할당되며,
이 메모리는 메서드가 작업을 수행하는 동안 지역변수들과 연산의 중간결과 등을 저장하는데 사용됩니다.
그리고 메서드가 작업을 마치면 할당되었던 메모리공간은 반환되어 비워집니다. 각 메서드를 위한 메모리공간은 서로 구별됩니다.
기본형 매개변수와 참조형 매개변수
자바에서는 메서드를 호출할 때 매개변수로 지정한 값을 메서드의 매개변수에 복사해서 넘겨줍니다.
매개변수의 타입이 기본형일 때는 기본형 값이 복사되겠지만, 참조형이면 인스턴스의 주소가 복사됩니다.
때문에 기본형의 경우 전달인자로 변수를 넘기고, 그 값을 호출한 메서드에서 변경해도 기존 메서드에서의 값은 달라지지 않습니다.
반면 참조형의 경우 기존 변수의 값도 호출한 메서드에서 바꿀 수 있습니다.
public class example{
public static void main(String[] args){
int[] arr1 = {0, 1, 2, 3, 4, 5};
int[] arr2 = {10, 20, 30, 40, 50};
printArr(arr1, arr2);
}
static void printArr(int[] arr1, int[] arr2){
arr1 = arr2;
for(int i = 0; i < arr1.length; i++){
System.out.print(arr1[i] + " ");
}
}
}
재귀호출
메서드의 사용법 중 메서드가 자기 자신을 다시 호출하는 것을 재귀호출 이라고 합니다.
반복적인 작업을 해야하는 메서드의 경우 반복문을 사용하거나, 재귀호출을 통한 코드를 선택해서 작성할 수 있습니다.
하지만, 재귀호출은 반복문과 비교해 다소 효율이 떨어진다는 단점이 있는데, 메서드를 호출할 때 추가적인 비용이 발생하기 때문입니다.
대표적인 재귀호출 예제는 팩토리얼을 구하는 예제인데, 팩토리얼이란 예를 들어 5팩토리얼을 구하라고 하면
1*2*3*4*5의 값을 구하는 것입니다. 실제로 코드를 작성해서 사용법을 알아보도록 합시다.
public class example{
public static void main(String[] args){
System.out.println(factorial(5));
}
static long factorial(int n){
long result = 0;
if (n == 1){
result = 1;
}else{
result = n * factorial(n-1);
}
return result;
}
}
위의 값을 직접 계산해보면 정상적으로 5팩토리얼이 계산된 것을 알 수 있습니다.
이번 글은 여기까지 하고 마치도록 하고, 다음 글에서 이어서 설명하도록 하겠습니다.
감사합니다.
'프로그래밍 언어 > 자바' 카테고리의 다른 글
자바 15. 생성자(Constructor) (0) | 2020.08.28 |
---|---|
자바 14. 메서드 오버로딩 (0) | 2020.08.27 |
자바 12. 클래스와 객체 (0) | 2020.08.25 |
자바 11. 배열-2 (0) | 2020.08.24 |
자바 10. 배열-1 (0) | 2020.08.14 |