Java Scope
Java Scope: 자바 변수의 범위
- *변수의 범위(Scope)**는 변수가 유효한 영역을 나타내며, Java에서는 변수의 선언 위치에 따라 어디서 사용할 수 있는지가 결정됩니다. Java에서 변수의 범위는 주로 클래스 변수, 인스턴스 변수, 지역 변수로 나뉩니다. 변수의 수명과 접근성을 관리하는 것은 프로그램의 안전성과 효율성을 높이는 중요한 개념입니다.
이 가이드는 Java에서 **변수의 범위(Scope)**에 대한 개념과 클래스, 인스턴스, 지역 변수의 차이점을 설명합니다.
1. 변수의 범위(Scope) 종류
Java에서 변수는 선언된 위치에 따라 세 가지 범위로 나눌 수 있습니다:
- 클래스 변수 (Static Variables): 클래스 전체에서 접근 가능.
- 인스턴스 변수 (Instance Variables): 클래스의 인스턴스에서만 접근 가능.
- 지역 변수 (Local Variables): 메소드 내 또는 블록 내에서만 접근 가능.
2. 클래스 변수 (Static Variables)
클래스 변수는 static
키워드로 선언된 변수로, 클래스 레벨에서 공유됩니다. 즉, 모든
인스턴스가 같은 값을 공유하며, 클래스가 메모리에 로드될 때 한 번만 생성됩니다. 클래스 변수는 클래스 이름으로 직접
접근할 수 있습니다.
사용 예:
public class StaticVariableExample {
// 클래스 변수 선언 (모든 인스턴스가 공유)
static int counter = 0;
public StaticVariableExample() {
counter++; // 생성자에서 클래스 변수 증가
}
public static void main(String[] args) {
StaticVariableExample obj1 = new StaticVariableExample();
StaticVariableExample obj2 = new StaticVariableExample();
// 클래스 변수는 모든 인스턴스에서 공유됨
System.out.println("카운터 값: " + StaticVariableExample.counter); // 출력: 2
}
}
설명:
static int counter
: 클래스 변수로 선언된counter
는 모든 인스턴스에서 공유됩니다.counter++
: 생성자가 호출될 때마다 클래스 변수가 증가합니다.- 결과: 두 개의 객체를 생성했으므로
counter
는 2가 됩니다.
3. 인스턴스 변수 (Instance Variables)
인스턴스 변수는 클래스의 **객체(인스턴스)**가 생성될 때마다 각 인스턴스마다 개별적으로 생성되는 변수입니다. 인스턴스 변수는 클래스의 멤버로, 클래스 내에서 선언되지만 메소드 외부에서 선언됩니다. 각 인스턴스는 자신의 인스턴스 변수를 독립적으로 가집니다.
사용 예:
public class InstanceVariableExample {
// 인스턴스 변수 선언
int instanceCounter = 0;
public InstanceVariableExample() {
instanceCounter++; // 생성자에서 인스턴스 변수 증가
}
public static void main(String[] args) {
InstanceVariableExample obj1 = new InstanceVariableExample();
InstanceVariableExample obj2 = new InstanceVariableExample();
// 각 인스턴스의 인스턴스 변수 값 출력
System.out.println("obj1의 카운터 값: " + obj1.instanceCounter); // 출력: 1
System.out.println("obj2의 카운터 값: " + obj2.instanceCounter); // 출력: 1
}
}
설명:
int instanceCounter
: 각 인스턴스마다 독립적으로 생성되는 인스턴스 변수입니다.- 결과: 객체를 두 번 생성해도
instanceCounter
는 각각의 인스턴스에서 독립적으로 1이 됩니다.
4. 지역 변수 (Local Variables)
지역 변수는 메소드 또는 블록 내에서 선언된 변수로, 그 블록을 벗어나면 더 이상 유효하지 않습니다. 지역 변수는 메소드가 호출될 때 생성되고, 메소드가 종료되면 자동으로 메모리에서 해제됩니다.
사용 예:
public class LocalVariableExample {
public static void main(String[] args) {
// 지역 변수 선언
int localVar = 10;
// 지역 변수 출력
System.out.println("지역 변수 값: " + localVar); // 출력: 10
// 블록 내에서 선언된 변수 (블록을 벗어나면 유효하지 않음)
{
int blockVar = 20;
System.out.println("블록 내 변수 값: " + blockVar); // 출력: 20
}
// 블록을 벗어나면 blockVar는 유효하지 않음 (주석 처리된 코드는 컴파일 에러)
// System.out.println(blockVar); // 컴파일 에러
}
}
설명:
int localVar
: 메소드 내에서 선언된 지역 변수로, 해당 메소드에서만 유효합니다.- 블록 내 변수:
blockVar
는 블록 범위 내에서만 유효하며, 블록을 벗어나면 접근할 수 없습니다.
5. 변수의 범위와 우선순위
Java에서는 같은 이름의 변수가 다른 범위에서 선언될 수 있습니다. 하지만, 지역 변수가 인스턴스 변수나 클래스 변수와 이름이 같으면, 지역 변수가 우선됩니다.
사용 예:
public class VariableScopeExample {
// 인스턴스 변수
int num = 10;
public void printNum() {
// 지역 변수
int num = 20;
System.out.println("지역 변수 num: " + num); // 출력: 20
System.out.println("인스턴스 변수 num: " + this.num); // 출력: 10
}
public static void main(String[] args) {
VariableScopeExample obj = new VariableScopeExample();
obj.printNum();
}
}
설명:
int num = 20
: 메소드 내에서 선언된 지역 변수는 인스턴스 변수num
을 가립니다.this.num
:this
키워드를 사용하여 인스턴스 변수에 접근할 수 있습니다.
6. 블록 범위와 Shadowing
Shadowing은 같은 이름의 변수가 다른 범위에서 선언되어 기존 변수를 가리는 현상입니다. 일반적으로 블록 범위나 메소드 범위에서 더 좁은 범위의 변수가 우선되며, 이때 넓은 범위의 변수가 Shadowing될 수 있습니다.
사용 예:
public class ShadowingExample {
// 인스턴스 변수
int x = 5;
public void printX() {
// 블록 내 지역 변수
int x = 10; // 인스턴스 변수 x를 shadowing
System.out.println("지역 변수 x: " + x); // 출력: 10
System.out.println("인스턴스 변수 x: " + this.x); // 출력: 5
}
public static void main(String[] args) {
ShadowingExample obj = new ShadowingExample();
obj.printX();
}
}
설명:
int x = 10
: 지역 변수x
가 인스턴스 변수x
를 shadowing합니다.this.x
:this
키워드를 사용하여 shadowing된 인스턴스 변수에 접근할 수 있습니다.
7. 변수의 수명 (Lifetime)
- 클래스 변수: 프로그램이 시작될 때 클래스가 로드되면서 생성되며, 프로그램이 종료될 때까지 메모리에 유지됩니다.
- 인스턴스 변수: 객체가 생성될 때 생성되며, 객체가 더 이상 사용되지 않으면 가비지 컬렉션에 의해 제거됩니다.
- 지역 변수: 메소드 또는 블록이 실행될 때 생성되고, 메소드 종료 시 메모리에서 해제됩니다.
8. 전역 변수는 없는가?
Java에서는 전역 변수라는 개념이 존재하지 않습니다. 대신 클래스 변수(static 변수를 사용해 전역처럼 활용할 수 있습니다. 하지만 전역 변수처럼 프로그램 전체에서 공유되는 방식은 아니므로 클래스 스코프 안에서만 관리됩니다.
9. 변수의 범위 사용 예시
9.1. 학생의 성적 관리 (클래스 변수와 인스턴스 변수)
public class Student {
// 클래스 변수 (모든
학생의 총 학생 수)
static int totalStudents = 0;
// 인스턴스 변수 (각 학생의 이름과 성적)
String name;
int score;
// 생성자
public Student(String name, int score) {
this.name = name;
this.score = score;
totalStudents++; // 학생 생성 시 총 학생 수 증가
}
public void printStudentInfo() {
System.out.println("이름: " + name + ", 성적: " + score);
}
public static void main(String[] args) {
Student student1 = new Student("홍길동", 90);
Student student2 = new Student("이순신", 85);
student1.printStudentInfo();
student2.printStudentInfo();
// 클래스 변수 출력 (모든 학생의 총 학생 수)
System.out.println("총 학생 수: " + Student.totalStudents); // 출력: 2
}
}
9.2. 지역 변수와 인스턴스 변수의 혼합 사용
public class Counter {
// 인스턴스 변수
int counter = 0;
public void increment() {
// 지역 변수
int step = 2; // 증가 값 설정
counter += step;
}
public static void main(String[] args) {
Counter myCounter = new Counter();
myCounter.increment();
System.out.println("카운터 값: " + myCounter.counter); // 출력: 2
}
}
요약
Java에서 **변수의 범위(Scope)**는 변수가 선언된 위치에 따라 유효한 범위가 달라집니다. 클래스 변수는 모든 인스턴스에서 공유되며, 인스턴스 변수는 각 객체마다 독립적으로 존재합니다. 지역 변수는 메소드나 블록 내에서만 유효하며, 그 범위를 벗어나면 메모리에서 해제됩니다. Shadowing은 좁은 범위에서 선언된 변수가 넓은 범위의 변수를 가리는 현상을 말하며, 변수의 범위를 적절히 관리하는 것은 프로그램의 안정성과 효율성을 높이는 중요한 요소입니다.