< 중첩 클래스 >
① 분류
- 중첩 클래스는 클래스 내부에 선언되는 위치에 따라서 두가지로 분류
- 멤버 Inner 클래스 : 쿨래스의 멤버로서 선언되는 중첩 클래스
로컬 Inner 클래스 : 생성자 또는 메소드 내부에서 선언되는 중첩 클래스
선언 위치에 따른 분류 | 선언 위치 | 설명 | |
멤버 Inner 클래스 | 인스턴스 멤버 클래스 | class A { class B { ... } } |
A 객체를 생성해야만 사용할 수 있는 B클래스 |
정적 멤버 클래스 | class A { static class B { ... } } |
A 클래스로 바로 접근할 수 있는 B클래스 | |
로컬 Inner 클래스 | class A { void method(){ class B{ ... } } } |
method()가 실행할 때만 사용할 수 있는 B클래스 |
- 바이트 코드 파일 이름
· 멤버 클래스 : 바깥클래스 $ 멤버 클래스.class
· 로컬 클래스 : 바깥클래스 $1 로컬 클래스.class
② 인스턴스 멤버 클래스
- static 키워드 없이 중첩 선언된 클래스
- 정적필드와 메소드 선언할 수 없다
class A {
class B {
B(){} // 생성자
int field1; // 인스턴스 필드
// static int field2; 정적 필드 불가능
void method1(){} // 인스턴스 메소드
// static void method2(){} 정적 메소드 불가능
}
}
- 바깥 클래스 외부에서 이너 클래스 객체를 생성하려면 먼저 바깥 클래스 객체를 생성하고 이너 클래스 객체 생성해야 한다
(일반적으로 바깥 클래스 외부에서 이너 클래스 객체를 생성하는 일은 거의 없다.)
A a = new A(); // 바깥 클래스 객체 먼저 생성
A.B b = a.new B();
b.field1 = 3;
b.method1();
class A{
class B { ... }
void methodA(){
B b = new B();
b.field = 3;
b.method1();
}
}
③ 정적 멤버 클래스
- static 키워드로 선언된 클래스
- 모든 종류의 필드와 메소드 선언 가능
class A {
class C {
C(){} // 생성자
int field1; // 인스턴스 필드
static int field2; 정적 필드
void method1(){} // 인스턴스 메소드
static void method2(){} 정적 메소드
}
}
- 바깥 클래스 외부에서 정적 멤버 클래스 객체를 생성하기 위해서는 바깥 클래스 객체를 생성할 필요 없다
A.C c = new A.C();
c.field1 = 3;
c.method1();
A.C.field2 = 3;
A.C.method2();
④ 로컬 클래스
- 메소드 내에서 선언된 클래스
- 접근제한자 ( public, private ) 및 static 붙일 수 없다
void method(){
class D{
D(){ }
int field1;
// static int field2;
void method1() { }
// static void method2() { }
}
D d = new D();
d.field1 = 3;
d.method1();
}
- 메소드가 실행될 때 메소드 내에서 객체 생성하고 사용해야함
⑤ 멤버 클래스에서 사용 제한
- 인스턴스 멤버 클래스 안에서는 바깥 클래스의 모든 필드와 메소드 접근 가능
- 정적 멤버 클래스 안에서는 바깥 클래스의 정적 필드와 메소드에만 접근 가능
class A {
int field1;
void method1(){...}
static int field2;
static void method2() { ... }
class B {
void method(){
field1 = 10;
method1();
field2 = 10;
method2();
}
}
}
class A {
int field1;
void method1(){...}
static int field2;
static void method2() { ... }
static class C {
void method(){
// field1 = 10; 불가능
// method1(); 불가능
field2 = 10;
method2();
}
}
}
⑥ 로컬 클래스에서 사용 제한
public class Outer {
// 자바 7이전
public void method1(final int arg) {
final int localVariable = 1;
// final 상수 변경할 수 없다
// arg = 100;
// localVariable = 100;
class Inner{
public void method() {
int result = arg + localVariable;
}
}
}
// 자바 8 이후
public void method2(int arg) {
int localVariable= 1;
// final이 생략되어 있어도 값 변경 못함
// arg = 100;
// localVariable = 100;
class Inner{
public void method() {
int result = arg + localVariable;
}
}
}
}
- method() 안에서 선언된 지역변수는 상수인 경우에만 사용가능하다
public class Outer {
public void method1(final int arg) {
int a = 200;
class Inner{
public void method() {
a = a + 100; // method의 지역변수 사용불가능
}
}
}
}
- 자바 8버전 이후에는 final이 생략되어도 상수로 생각하고 이너클래스에서 사용가능하다
단, final이 생략되었다고 해서 그냥 변수가 아니기 때문에 값 변경은 여전히 안된다
⑦ 중첩 클래스에서 바깥 클래스 참조 얻기
- this 이용
public class Outter {
String field = "Outter-field";
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();
}
}
- field 변수가 동일이름으로 2개로 선언되어있지만 this 키워드를 사용하여 참조를 구분한다
- 중첩 클래스에서 this 키워드 사용하면 중첩 클래스 객체 참조( 더 가까운 것 )가 우선순위가 높다
- 바깥 클래스에 접근하기 위해선 '바깥 클래스.this'를 사용해준다
'자바 웹 개발자가 될거야 > JAVA' 카테고리의 다른 글
[JAVA] 필드 / 생성자 / 생성자 오버로딩 / this. 참조 / this() 다른생성자 호출 (0) | 2021.11.19 |
---|---|
이클립스 워크스페이스 기본 경로 변경 / 프로젝트 익스플로어 창 사라졌을 때 (0) | 2021.11.19 |
[JAVA] 메서드 / 리턴문 / 메서드 호출 / 메서드 오버로딩 (0) | 2021.11.03 |
[JAVA] 자료형 범위 / 데이터 형변환 / 연산자 / 상수 (0) | 2021.10.06 |
[JAVA] 자바 이클립스 시작/ 자바 변수명 규칙/ print와 println 차이/ 연결연산자 / 자바 데이터 타입 / 데이터 형 변환 (0) | 2021.10.01 |