public class Main {
static int x = 10;
public static void main(String[] args) {
int x = x + 1;
System.out.println(x);
}
}
static int x = 10;
int x = x + 1;
variable x might not have been initialized
public class Main {
int a = 1;
public void test() {
int a = a + 1;
System.out.println(a);
}
public static void main(String[] args) {
new Main().test();
}
}
int a = 1;
int a = a + 1;
public class Main {
int a = 1;
public void test() {
int a = this.a + 1; // ✅ 멤버 변수 a를 명시적으로 사용
System.out.println(a);
}
public static void main(String[] args) {
new Main().test();
}
}
a 선언하려는데 오른쪽 a는 지역 스코프의 a를 참조하려 함this.a를 써야 했음variable a might not have been initialized
public class Main {
public static void main(String[] args) {
int num = 3;
{
int num = num + 1;
System.out.println(num);
}
}
}
int num = 3;
{
int num = num + 1;
System.out.println(num);
}
int num = num + 1; → 선언 중인 변수 num을 자기 자신으로 초기화하려는 코드variable num might not have been initialized
public class Main {
public static void main(String[] args) {
int i = 0;
for (int i = 0; i < 3; i++) {
System.out.println(i);
}
}
}
int i = 0;
for (int i = 0; i < 3; i++) {
System.out.println(i);
}
int i = 0; → 먼저 선언됨 (main 내부)for (int i = ... → 같은 이름으로 또 선언하려 함 (블록 안이지만 같은 스코프로 인식됨)variable i is already defined in method main(String[])
public class Main {
public static void main(String[] args) {
int val = 10;
class Local {
void print() {
System.out.println(val);
}
}
new Local().print();
}
}
val은 이후 변경되지 않기 때문에 "사실상 final"로 간주됨10public class Main {
public static void main(String[] args) {
int val = 10;
class Local {
void modify() {
val = 20;
}
}
new Local().modify();
System.out.println(val);
}
}
int val = 10;
class Local {
void modify() {
val = 20;
}
}
Local variable val defined in an enclosing scope must be final or effectively final
public class Main {
static {
System.out.println("x = " + x);
}
static int x = 5;
public static void main(String[] args) {
System.out.println("main x = " + x);
}
}
static {
System.out.println("x = " + x);
}
static int x = 5;
x가 아직 선언 전 → 기본값 사용int는 초기화 전에는 0이 기본값임x = 0
main x = 5
| 문제 | 정답 | 설명 요약 |
|---|---|---|
| 1 | 컴파일 오류 | 지역 변수 선언 전에 자기 자신 참조 → 초기화 불가 |
| 2 | 컴파일 오류 | 지역 변수 선언 시 인스턴스 변수 가림 → this 필요 |
| 3 | 컴파일 오류 | 선언 중인 변수로 초기화 시도 |
| 4 | 컴파일 오류 | 같은 스코프에 i 중복 선언 |
| 5 | 10 | 지역 클래스가 사실상 final인 val을 참조 |
| 6 | 컴파일 오류 | 지역 클래스 내부에서 지역 변수 val 수정 불가 |
| 7 | x = 0, main x = 5 | static 초기화 순서 주의 |
변수 스코프란: "이 변수가 어디까지 살아서 쓸 수 있는가?" 를 정하는 범위
| 구분 | 선언 위치 | 스코프 범위 | 예시 |
|---|---|---|---|
| 클래스 변수 | static 필드 | 클래스 전체 (정적) | static int x; |
| 인스턴스 변수 | 클래스의 필드 | 인스턴스 전체 (비정적) | int x; |
| 지역 변수 | 메서드 내부 | 선언된 블록 내부 | int x = 3; |
| 파라미터 변수 | 메서드의 매개변수 | 메서드 내 | void f(int x) |
| 지역 클래스 변수 | 지역 클래스 내부 | 선언된 지역 클래스 내부 | class Local {} |
| 블록 변수 | if, for 등 내부 | 그 블록 내부만 | for (int i...) |
final 변수란?final int x = 10;
final이 붙은 변수는 "한 번만" 값을 가질 수 있어void method() {
class Local {
void hello() {
System.out.println("hi");
}
}
}
void method() {
int a = 10;
class Local {
void run() {
System.out.println(a); // ✅ 가능!
}
}
}
🔸 이때
a는 바깥 메서드의 지역 변수인데 어떻게 접근 가능할까?
✔ 자바 8 이상에서는 다음 조건이 충족되면 지역 변수 사용 가능:
final로 간주함void method() {
int a = 10;
a = 20; // ❌
class Local {
void run() {
System.out.println(a);
}
}
}
Local variable a defined in an enclosing scope must be final or effectively final
👉 이유: a는 값이 변경되었기 때문에 final이 아님
지역 클래스는 내부적으로 복사본을 갖는다
즉, 지역 변수 자체에 대한 참조를 저장하는 게 아니라, 복사값을 저장함
그런데 지역 변수가 중간에 바뀌면? → 복사본과 실제값이 불일치 → 혼란
그래서 자바는 지역 클래스 내부에서 접근하는 지역 변수는 final만 허용함
| 변수 위치 | 접근 가능 여부 | 수정 가능 여부 | 예시 |
|---|---|---|---|
| 클래스 필드 | ✅ | ✅ | Main.this.val |
| 지역 변수 (final) | ✅ | ❌ | final int x = 5; |
| 지역 변수 (변경됨) | ❌ | ❌ | int x = 5; x = 10; |
public class Main {
public static void main(String[] args) {
int num = 10; // 사실상 final
int notFinal = 20;
notFinal = 30; // 변경 → notFinal은 더 이상 final 아님
class Local {
void run() {
System.out.println(num); // ✅ 가능
// System.out.println(notFinal); // ❌ 에러!
}
}
}
}
| 키워드 | 의미 |
|---|---|
final 지역 변수 | 한 번만 초기화 가능, 이후 수정 불가 |
| 지역 클래스 | 메서드 안에서 정의된 클래스 |
| 스코프 | 선언된 블록 내에서만 유효 |
| 지역 클래스에서 접근 가능 변수 | final 혹은 사실상 final 변수만 접근 가능 |
| 접근 가능 이유 | 자바는 지역 클래스가 감싸는 지역 변수의 "복사본"을 내부에 저장 |