자바의 변수에는 사용할 수 있는 범위(scope)가 있다.

 

코드를 작성하는 곳이 어디냐에 따라 사용할 수 있는 변수가 달라진다.

 

이게 좀 복잡하다. 절차적 언어인 C언어에서는 전역변수와 지역변수가 있었다.

 

 객체 지향 프로그래밍 언어(OOP)인 자바에서는 C언어와 다르다. 전역과 지역으로 나누기 보다는 객체 지향의 관점에서 분류된다. 변수의 유효범위에 대해 깊은 이해를 하기 위해서는 Stack, Heap 등 기본적인 메모리 구조에 대한 이해가 필요하다.

 

자바에는 다음 세 종류의 변수가 있다. 각자 유효범위가 다르다.

 

1) 지역 변수 (Local Variable)

 

2) 멤버 변수 (Instance Variable)

 

3) static 변수(Class Variable)

 

용어가 많다보니 헷갈리기 쉽다. 멤버 변수를 관점에 따라 field, attribute, variable 등 다양한 이름으로 부른다.

 

 

* field, variable,attribute 차이점

 

https://www.geeksforgeeks.org/what-is-the-difference-between-field-variable-attribute-and-property-in-java/

 

What is the difference between field, variable, attribute, and property in Java - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

1) 지역 변수

 

 먼저 지역 변수는 함수(메서드) 내부에 선언하며 함수 밖에서는 사용할 수 없다. 하나의 지역에 선언한 지역 변수는 그 지역을 벗어나면 사용할 수 없다. 함수를 호출하면 스택(Stack) 메모리에 생성된다. 함수가 종료하면 스택이 사라지고, 그 안에 있던 변수들은 사라진다.

 

 하나의 지역과 다른 지역의 변수이름이 같아도 각각 다른 변수로 인식한다. 선언한 지역이 다르고 값도 다르다. 자신들만의 메모리 영역을 차지하고 있다. 함수가 호출되서 실행을 마치고 값을 반환하면 (return 문) 그 지역의 메모리는 해제된다. 함수의 수행이 끝난 후에 지역 변수는 사용할 수 없다.

public class ScopeEx {
	int a = 25; // 멤버 변수

	public void f1() {
		int a = 10; // f1 지역
		System.out.println(a);
	}
	public void f2() {
		int a = 15; // f2 지역
		System.out.println(a);
	}
	public static void main(String[] args) {
		ScopeEx sc1 = new ScopeEx();
		sc1.f1(); // f1 지역변수 a
		sc1.f2(); // f2 지역변수 a
		int a = 20;
		System.out.println(a); // main 함수 지역변수 a
		System.out.println(sc1.a); // 멤버 변수 a
	}
}

 

지역변수

2) 멤버 변수


 멤버 변수는 new 키워드로 인스턴스를 생성해야 사용할 수 있다. 힙(Heap) 메모리에 생성되며 멤버 변수는 해당 클래스의 메서드에서 사용이 가능하다. 접근제어자가 public 이면 같은 패키지의 다른 클래스에도 사용 가능하다. 힙 메모리에 생성된 인스턴스는 자바의 쓰레기 수거반(Garbage Colllector 가비지 컬렉터)에 의하여 어느 시점에 수거된다. 

 

 멤버 변수를 private 으로 하면 다른 클래스에서는 접근이 제한된다. 다른 클래스에서 private 멤버 변수를 사용하려면 getter와 setter 처럼 그 클래스의 메서드를 통하는 방식으로 사용하므로 데이터의 보안성이 좋아진다.

 

멤버 변수는 클래스 안에 있지만 인스턴스를 생성하기 전에는 사용할 수 없다.

public class ScopeEx {

	private int e1; // 멤버 변수

	public static void main(String[] args) {	
		ScopeEx se1 = new ScopeEx(); // 인스턴스를 생성한다.
		se1.e1 = 10; // 사용할 수 있다.
	}
}


3) static 변수

 

 static 변수는 눈여겨 볼 필요가 있다. 전역 변수와 비슷한 느낌도 있다. static 변수는 프로그램 실행시 클래스를 메모리에 로드했을 때 부터 생성된다. 인스턴스를 new 로 생성하지 않아도 사용할 수 있다. 메모리에는 스택, 힙 그리고 데이터 영역이 있는데 static 은 데이터 영역에 생성된다. 미리 생성되있기에 속도는 빠르지만 프로그램이 종료될 때 까지 메모리에서 해제되지 않는다. static 변수를 많이 쓰면 시스템의 메모리가 그만큼 줄어드니 주의할 필요가 있다. 다른 변수들은 실행도중 메모리를 할당하고 해제 하지만 static은 그렇지 않다.

 

*순서 : 프로그램 실행 >> 클래스 로드 (static 생성) >> 인스턴스 생성

 

 에디터를 열고 main 함수에 소스코드를 작성하기 시작할 때 이미 메모리에 올라와 있는 변수들도 있다. java.lang 패키지에 있는 Math 같은 클래스 이다. (아래) public static final double PI 는 static 이다. main 함수에서 Math.PI 라고 사용하면 된다.

 

Math 클래스

public class ScopeEx {
	public static int b = 30;
	
	public static void main(String[] args) {
		System.out.println(ScopeEx.b); // static 변수
	}
}

 static 변수 그 단어 뜻 처럼 프로그램이 실행시부터 종료시까지 그대로 고정되어 있다. 그래서 static 변수를 정적 변수라고 한다. 한편 클래스에 하나밖에 없기 때문에 클래스 변수라고 해서 인스턴스 변수들과 구분한다.

 

 의미적으로는 변수를 인스턴스 변수(멤버 변수)로 만드는 것 보다 하나의 클래스 변수를 인스턴스들이 공유하는 것이 더 나을 법한 상황에 사용하는 변수이다. 그러니까 인스턴스가 100개 있다고 하자. 그 중에 항상 똑같은 값이 중복되는 멤버 변수가 있다면 데이터는 100개가 중복되는 것이다. 그러니까 100개 만들어서 메모리를 낭비할 바엔 속도도 빠르고 용량도 적은 static 변수로 변경하여 쓰는게 낫다.

 

 결국 OOP인 자바도 이해도의 깊이를 더하려면 컴퓨터 구조에 대해서 많은 것을 알아야 한다. 이 시점에서 C언어를 배우기 시작하는 것도 괜찮다. C언어에서는 프로그래머가 메모리에 직접 액세스한 후, 포인터를 써서 메모리의 할당과 해제를 직접해야한다. 자바에는 그 과정이 없으니까 메모리의 직접 조작까지는 알 수 없다. C언어를 배우고 어셈블리어를 조금 더 하면 좋다. 어셈블리어는 기계어를 하나의 명령단위(instruction)로 실행시키는 과정을 보여준다. 소프트웨어 관점에서 기계와 하드웨어에 대하여 이해할 수 있다.

 

 사실 컴퓨터는 배우는 사람의 의지에 많은 것이 달려있기에 몰라도 된다고 생각하면 그만이다. 어떤 프로그래머들은 컴퓨터구조에 대한 이해도가 낮은 프로그래머들을 무시하기도 한다. 뭐 어느쪽이나 이유는 있다고 생각한다. 결국 배우는 사람의 내면에서 일어나는 일이다. 바깥으로 드러나는 것은 실력일 것이고 어떤 프로그래머가 되느냐는 자신의 선택과 노력에 달려있다. 무시하는 것도 포기하는 것도 그 한 순간 일 뿐이다. 남들을 바라볼 필요가 없다.

공유하기

facebook twitter kakaoTalk kakaostory naver band