중첩클래스의 접근제한

중첩클래스의 접근 제한

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

public class A {
int field1;

void method1( ) { }

static int field2;
static void method2( ) { }

class B {
void method ( ) {
field1 = 10;
method1( );

field2 = 10;
method2( );
}
}

static class C {
void method( ) {
//filed1 = 10; //접근 불가
//method1( ); //접근 불가

field2 = 10;
method2( );
}
}
}

로컬클래스(메소드 안에 클래스 생성)에서 사용 가능한 것은 final로 선언된 매개 변수와 로컬 변수뿐이다. 자바 7 이전에는 final이 붙어있지 않은 매개변수 혹은 변수를 로컬 클래스안에서 사용하고자 하면 컴파일 에러가 발생하였다. 하지만 자바 8부터는 컴파일 에러가 발생하지 않는다. 즉 내부적으로는 final의 특성(값을 변경할 수 없는)을 갖으며 final의 유무로 로컬클래스 내 복사 위치가 결정된다.(복사위치에 대해선 아래 설명)
다음은 7,8버전의 final 유무에 따른 접근관련 이슈이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Outter {
//자바7 이전
public void method1(final int arg) {
final int localVariable = 1;
//arg = 100; //불가능
//localVariable = 100 //불가능
class Inner {
public void method( ) {
int result = arg + localVariable;
}
}
}


//자바8 이후
public void method2(int arg) {
int localVariable = 1;
//arg = 100; //불가능
//localVariable = 100 //불가능
class Inner {
public void method( ) {
int result = arg + localVariable;
}
}
}
}

위의 코드와 같이 final이 없더라도 값 변경은 허용하지 않는다는것이다.

※ final의 유무로 로컬클래스 내 복사 위치가 결정된다?
먼저 다음과 같은 코드가 있다고 가정하자.

1
2
3
4
5
6
7
8
9
10
11
12
void outMethod(final int arg1, int arg2) {
final int var1 = 1;
int var2 = 2;

class LocalClass {
void method() {
int result = arg1+arg2+var1+var2;
}

}
}

위의 LocalClass에 복사된 변수를 보면 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
class LocalClass {
int arg2 = 매개값; //final이 붙지 않아 필드로 복사
int var2 = 2; //final이 붙지 않아 필드로 복사

void method( ) {
int arg1 = 매개값; //final이 붙은것은 로컬 변수로 복사
int var1 = 1; //final이 붙은것은 로컬 변수로 복사
int result = arg1 + arg2+ var1+ var2;
}

}

복사된 영역을 신경쓸 필요는 없으나 알고 있는것이 좋겠다!

중첩클래스에서 바깥 클래스 참조 얻기

중첩 클래스 내부에서 this키워드를 사용하면 어떻게 될까? 말 그대로 중첩클래스가 this가 되게된다. 그렇다면 바깥 클래스를 가르키기 위해선 어떻게 해야될까.
정답은 바깥클래스.this 를 활용하면 된다. 아래를 참고하자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Outter {
String field = "Outter-filed";

void method( ) {
System.out.println("Outter-method");
}

class Nested {
String field = "Nested-field";
void method() {
System.out.println("Nested-method");
}
}

void print( ) {
System.out.println(this.field); //중첩객체 참조
this.method( ); //중첩객체 참조

System.out.println(Outter.this.field); //바깥객체 참조
Outter.this.method( ); //바깥객체 참조
}
}
}


public class OutterExample {
public static void main(String[] args) {
Outter outter = new Outter( );
outter.Nested nested = outter.new Nested( );
nested.print( );
}
}
Share