자바를 배우다 보면 변수를 만들었는데 사용할 수 없거나, 숫자를 계산했는데 예상과 다른 결과가 나올 때가 있습니다. 이때 자주 만나는 개념이 스코프와 형변환입니다.
스코프는 변수를 사용할 수 있는 범위입니다. 형변환은 값을 다른 타입으로 바꾸는 과정입니다.
앞에서 변수와 연산자가 아직 헷갈린다면 자바 변수 완전 정리 — 이름표 붙은 보관함으로 이해하기, 자바 연산자 한 번에 정리 — 산술부터 대입까지를 먼저 보고 오는 편이 좋습니다.
1. 스코프란?
스코프는 변수를 사용할 수 있는 범위입니다. 쉽게 말하면 변수가 살아 있는 구역입니다.
자바에서는 중괄호 {}가 스코프를 나누는 중요한 기준이 됩니다.
public class ScopeExample {
public static void main(String[] args) {
int outside = 10;
if (outside > 0) {
int inside = 20;
System.out.println(outside);
System.out.println(inside);
}
System.out.println(outside);
}
}
outside는 main 메서드 안에서 만들어졌기 때문에 main 안에서 사용할 수 있습니다.
inside는 if 블록 안에서 만들어졌기 때문에 if 블록 안에서만 사용할 수 있습니다.
2. 블록 안에서 만든 변수는 밖에서 사용할 수 없습니다
아래 코드는 오류가 납니다.
public class ScopeErrorExample {
public static void main(String[] args) {
if (true) {
int count = 3;
}
System.out.println(count); // 오류
}
}
count는 if 블록 안에서 만들어졌습니다.
그래서 if 블록이 끝난 뒤에는 사용할 수 없습니다.
이런 구조를 그림으로 보면 다음과 같습니다.
main 블록
├─ if 블록
│ └─ count 사용 가능
└─ if 블록 밖
└─ count 사용 불가
변수는 자신이 선언된 중괄호 안에서만 살아 있습니다. 중괄호를 벗어나면 그 변수는 더 이상 사용할 수 없습니다.
3. 변수를 필요한 범위에 선언하기
변수는 너무 넓은 범위에 만들기보다, 필요한 곳에 가깝게 선언하는 편이 좋습니다.
public class ScopeGoodExample {
public static void main(String[] args) {
int score = 85;
if (score >= 80) {
String message = "합격입니다.";
System.out.println(message);
}
}
}
message는 합격일 때만 필요합니다.
그래서 if 블록 안에 선언해도 충분합니다.
반대로 여러 블록에서 함께 써야 하는 값이라면 바깥에 선언해야 합니다.
public class ScopeSharedExample {
public static void main(String[] args) {
int score = 85;
String result;
if (score >= 80) {
result = "합격";
} else {
result = "불합격";
}
System.out.println(result);
}
}
result는 if, else가 끝난 뒤에도 출력해야 합니다.
그래서 if 바깥에 먼저 선언했습니다.
4. 같은 이름의 변수를 다시 만들 수 있을까?
같은 스코프 안에서는 같은 이름의 변수를 다시 선언할 수 없습니다.
int age = 20;
int age = 30; // 오류
이미 age라는 변수가 같은 범위에 있기 때문입니다.
값을 바꾸고 싶다면 다시 선언하는 것이 아니라 대입해야 합니다.
int age = 20;
age = 30;
처음 줄은 변수를 만드는 선언입니다. 두 번째 줄은 이미 있는 변수에 새 값을 넣는 대입입니다.
5. 형변환이란?
형변환은 값을 다른 타입으로 바꾸는 것입니다. 자바에서는 타입이 맞지 않으면 값을 바로 넣을 수 없는 경우가 있습니다.
int count = 10;
double countDouble = count;
위 코드는 가능합니다.
int 값인 10을 double 변수에 넣으면 10.0처럼 더 넓은 타입으로 바뀝니다.
형변환은 크게 두 가지로 볼 수 있습니다.
| 구분 | 의미 | 예시 |
|---|---|---|
| 자동 형변환 | 자바가 자동으로 타입을 바꿈 | int에서 double |
| 명시적 형변환 | 개발자가 직접 타입 변환을 지시 | double에서 int |
6. 자동 형변환
자동 형변환은 작은 범위의 타입을 큰 범위의 타입에 넣을 때 일어납니다. 값이 손실될 가능성이 낮기 때문에 자바가 자동으로 처리합니다.
int intValue = 10;
long longValue = intValue;
double doubleValue = intValue;
System.out.println(longValue); // 10
System.out.println(doubleValue); // 10.0
int보다 long이 더 큰 정수 범위를 가집니다.
double은 소수까지 표현할 수 있습니다.
그래서 int 값을 long이나 double에 넣는 것은 자연스럽게 허용됩니다.
int → long → double
이 방향은 더 넓은 그릇으로 옮기는 느낌입니다. 작은 컵의 물을 큰 컵에 옮기는 것과 비슷합니다.
7. 명시적 형변환
반대로 큰 범위의 타입을 작은 범위의 타입에 넣을 때는 자바가 자동으로 처리하지 않습니다. 값이 잘릴 수 있기 때문입니다.
double temperature = 32.8;
int roundedDown = temperature; // 오류
double에는 소수점이 있습니다.
하지만 int는 정수만 저장할 수 있습니다.
이때는 개발자가 직접 형변환을 지시해야 합니다.
double temperature = 32.8;
int roundedDown = (int) temperature;
System.out.println(roundedDown); // 32
(int)는 이 값을 int로 바꾸겠다는 뜻입니다.
다만 소수점 아래 값은 반올림되지 않고 버려집니다.
double value = 9.99;
int result = (int) value;
System.out.println(result); // 9
명시적 형변환은 가능하지만, 값이 손실될 수 있다는 점을 항상 생각해야 합니다.
8. 계산 중 타입은 어떻게 바뀔까
서로 다른 타입끼리 계산하면 더 넓은 타입으로 맞춰지는 경우가 많습니다.
int count = 3;
double price = 2.5;
double total = count * price;
System.out.println(total); // 7.5
count는 int이고 price는 double입니다.
계산할 때 int 값이 double 쪽으로 맞춰져서 결과도 double이 됩니다.
정수끼리 계산하면 결과도 정수입니다.
int total = 5;
int people = 2;
System.out.println(total / people); // 2
소수점까지 보고 싶다면 둘 중 하나를 double로 바꿔야 합니다.
int total = 5;
int people = 2;
System.out.println((double) total / people); // 2.5
(double) total로 먼저 바꿨기 때문에 전체 계산 결과도 double이 됩니다.
9. 형변환에서 실수하기 쉬운 부분
형변환은 편리하지만, 값을 잃을 수 있습니다. 특히 아래 상황을 조심해야 합니다.
소수점이 사라지는 경우
double weight = 1.8;
int intWeight = (int) weight;
System.out.println(intWeight); // 1
1.8이 1이 됩니다.
반올림이 아니라 소수점 아래를 버린다는 점이 중요합니다.
너무 큰 값을 작은 타입에 넣는 경우
int big = 1000;
byte small = (byte) big;
System.out.println(small);
byte는 담을 수 있는 범위가 작습니다.
범위를 넘어서는 값을 억지로 넣으면 예상하기 어려운 결과가 나올 수 있습니다.
입문 단계에서는 이런 변환을 일부러 많이 쓸 일은 적습니다. 하지만 작은 타입으로 강제 변환할 때는 값의 범위를 꼭 확인해야 합니다.
10. 직접 풀어볼 예시
스코프와 형변환은 직접 오류를 만나보면 더 빨리 이해됩니다. 아래 예시를 실행하거나 값을 바꿔보면서 확인해보면 좋습니다.
평균을 소수점까지 구하기
public class AverageCastingExample {
public static void main(String[] args) {
int korean = 80;
int english = 75;
int math = 90;
int sum = korean + english + math;
double average = (double) sum / 3;
System.out.println(sum); // 245
System.out.println(average); // 81.66666666666667
}
}
sum / 3만 쓰면 정수 나눗셈이 됩니다.
그래서 (double) sum으로 먼저 바꾼 뒤 나눴습니다.
블록 안 변수 확인하기
public class ScopePractice {
public static void main(String[] args) {
int level = 5;
if (level >= 5) {
String title = "초보 탈출";
System.out.println(title);
}
System.out.println(level);
}
}
level은 main 블록 안에서 사용할 수 있습니다.
title은 if 블록 안에서만 사용할 수 있습니다.
정리
스코프와 형변환은 자바 코드가 예상대로 동작하게 만드는 기본 개념입니다.
- 스코프는 변수를 사용할 수 있는 범위입니다.
- 중괄호
{}는 변수의 사용 범위를 나누는 기준이 됩니다. - 블록 안에서 만든 변수는 블록 밖에서 사용할 수 없습니다.
- 자동 형변환은 작은 타입에서 큰 타입으로 갈 때 주로 일어납니다.
- 명시적 형변환은 개발자가 직접
(타입)을 적어 변환하는 방식입니다. double을int로 바꾸면 소수점 아래가 버려집니다.- 정수끼리 나누면 결과도 정수입니다.
스코프를 이해하면 변수를 어디에 선언해야 하는지 판단하기 쉬워집니다. 형변환을 이해하면 숫자 계산 결과가 왜 예상과 달라지는지 더 빨리 찾을 수 있습니다.