이너 클래스(내부 클래스)
이너 클래스란?
1. 내부 클래스(inner class)란 하나의 클래스 내부에 선언된 또 다른 클래스를 의미합니다. 이러한 내부 클래스는 외부 클래스(outer class)에 대해 두 개의 클래스가 서로 긴밀한 관계를 맺고 있을 때 선언할 수 있습니다.
※ 일반적인 클래스
class A{
…
}
class B{
… // A를 사용하기 위해서는
} // A의 객체를 생성해야한다.
※ 내부 클래스가 포함된 형태
class A{ // B의 외부 클래스
…
class B{ // 내부 클래스
// 객체생성 없이도 A의 멤버접근가능
…
}
…
}
2. 내부클래스의 장점
- 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있다.
- 코드의 복잡성을 줄일 수 있다. (캡슐화)
이너 클래스의 특징
1. 외부 클래스의 인스턴스를 먼저 생성해야 인스턴스 클래스의 인스턴스를 생성가능하다
① class B에서 class A의 객체를 생성해야 사용 가능
② class A의 객체를 만들지 않아도 class B에서 class A의 객체를 쓸 수 있다.
③ BBB클래스에서 b객체를 사용하려면 또 AAA클래스에서 b객체를 만들어야 한다.
④ BBB클래스는 AAA안에서만 사용한다는 가정하에 inner class로 선언한 것
// Ex1)
class AAA{
int i = 100;
BBB b = new BBB();
}
class BBB{
void method(){
AAA a = new AAA(); // ①
System.out.println(a.i); // ①
}
}
class CCC{
BBB b = new BBB();
}
public class InnerTest{
public static void main(String args[]){
BBB b = new BBB();
b.method();
}
}
// Ex2)
class AAA{ // AAA는 BBB의 외부 클래스
int i = 100;
BBB b = new BBB(); // ③
class BBB{ // BBB는 AAA의 내부 클래스
void method(){
AAA a = new AAA();
System.out.println(a.i);
}
}
}
// BBB클래스가 내부 클래스로 선언 되었기 때문에 에러 발생
class CCC{
BBB b = new BBB();
}
// BBB클래스가 내부 클래스로 선언 되었기 때문에 에러 발생
public class InnerTest{
public static void main(String args[]){
BBB b = new BBB();
b.method();
}
}
// Ex3)
class AAA{ // AAA는 BBB의 외부 클래스
int i = 100;
BBB b = new BBB(); // ③
// BBB는 AAA의 내부 클래스
class BBB{ // ④
void method(){ // ④
// AAA a = new AAA(); // ④
// System.out.println(a.i); // ④
// 객체 생성없이 외부 클래스의 멤버 접근가능 // ④
System.out.println(i); // ②④
} // ④
} // ④
}
// BBB클래스가 내부 클래스가 되었기 때문에 CCC 에러 발생
class CCC{
BBB b = new BBB();
}
// BBB클래스가 내부 클래스가 되었기 때문에 에러 발생
public class InnerTest{
public static void main(String args[]){
BBB b = new BBB();
b.method();
}
}
// 여기서 main에서 내부클래스의 BBB 객체는 생성할수 없다.
// 내부클래스는 외부클래스를 먼저 생성한 다음에야 생성이 가능하기 때문
// BBB클래스는 AAA의 멤버처럼 다루어 진다.
이너 클래스의 종류와 특징
이너 클래스의 종류와 유효범위(scope)는 변수와 동일
// 변수인 경우
class Outer{
int iv = 0; // ①
static int cv = 0; // ②
void myMethod(){
int lv = 0; // ③
}
}
//내부 클래스인 경우
class Outer{
class InstanceInner{ … } // ①
static class StaticInner{ … } // ②
void myMethod(){
class LocalInner{ ... } // ③
}
}
이너 클래스 | 특징 |
인스턴스 클래스 (instance class) ① | 외부클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 인스턴스멤버처럼 다루어진다. 주로 외부 클래스의 인스턴스멤버들과 관련된 작업에 사용될 목적으로 선언된다. |
인스턴스 클래스 (instance class) ② | 외부 클래스의 멤버변수 선언위치에 선언하며, 외부클래스의 static멤버처럼 다루어진다. 주로 외부 클래스의 static멤버, 특히 static메서드에서 사용될 목적으로 선언된다. |
인스턴스 클래스 (instance class) ③ | 외부 클래스의 메서드나 초기화블럭 안에 선언하며, 선언된 영역 내부에서만 사용될 수 있다. |
익명 클래스 (anonymous class) | 클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스(일회용) |
이너 클래스의 제어자와 접근성
이너 클래스의 제어자는 변수에 사용 가능한 제어자와 동일
※ 원래 클래스의 접근제어자(modifier)에는 default와 public 밖에 안됐는데 이너 클래스의 접근제어자에는
public, default, private, protected 모두 사용가능
static 멤버란
객체 생성 없이 사용가능 한 것
이너 클래스를 작성하는데 static 멤버가 필요하다면?
이너 클래스도 static 이너 클래스가 되어야 한다.
// Ex4)
/* 다른 class는 객체를 만들어야만 변수를 사용하는데 그 class안에 static변수가
// 존재하는건 불가능하다
*/
class Ex7_12 {
// static클래스 이외에서는 static변수를 선언할수 없다
// final static은 상수이므로 허용
class InstanceInner {
int iv = 100;
// static int cv = 100;
final static int CONST = 100;
}
// static클래스만 static멤버를 정의할 수 있다.
// static class 안에서만 static int cv 같은 변수를 만들 수 있다.
static class StaticInner{
int iv = 200;
static int cv = 200;
}
// static클래스 이외에서는 static변수를 선언할수 없다
// final static은 상수이므로 허용
void myMethod(){
class LocalInner{
int iv = 300;
// static int cv = 300;
final static int CONST = 300;
}
}
}
※ static 내부 클래스에서는 외부 클래스의 인스턴스 멤버에 접근할 수 없다.
※ 다만 상수(final)인 경우에는 이너 클래스가 static 멤버를 가질 수 있다.
상수(상수≠변수)인 경우에는 inner class가 static 멤버를 가질수 있다.
※ 지역 내부 클래스는 메서드 내에서만 접근 가능하다.
method()안의 LocalInner class는 그 method() 안에서만 접근 가능하다.
// Ex5)
// Ex4) 이어서
public static void main(String args[]){
System.out.println(InstanceInner.CONST); // 가능
System.out.println(StaticInner.cv); // 가능
System.out.println(LocalInner.CONST); // 에러 지역 내부 클래스는 메서드 내에서만
}
// Ex6) 내부 클래스의 제어자와 접근성 예제
class Ex7_13 {
class InstanceInner{ …. }
static class StaticInner{ …. }
InstanceInner iv = new InstanceInner(); // instance 멤버끼리는 직접 접근 가능
static StaticInner cv = new StaticInner(); // static 멤버끼리는 직접 접근 가능
static void staticMethod(){ // static멤버는 instance멤버에 직접 접근 불가
// InstanceInner obj1 = new InstanceInner();
static StaticInner cv = new StaticInner();
// instance 클래스는 외부 클래스를 먼저 생성해야 생성가능
Ex7_13 outer = new Ex7_13();
InstanceInner obj1 = outer.new InstanceInner();
}
// instance메서드에서는 instance멤버와 static멤버 모두 접근 가능
void instanceMethod(){
InstanceInner obj1 = new InstanceInner();
static StaticInner cv = new StaticInner();
// 지역 내부 클래스는 외부에서 접근할 수 없다.
//localInner lv = new LocalInner();
}
void myMethod(){
class LocalInner{ …. }
LocalInner lv = new LocalInner();
}
}
// Ex7) 내부 클래스의 제어자와 접근성 예제
class Outer {
private int outerIv = 0;
static int outerCv = 0;
class InstanceInner{
// 외부 클래스의 private멤버도 접근가능하다.
int iiv = outerIv;
int iiv2 = outerCv;
}
static class StaticInner {
// static 클래스는 외부 클래스의 instance 멤버에 접근할 수 없다.
// int siv = outerIv;
static int scv = outerCv;
}
void myMethod(){
int lv = 0;
final int LV = 0; // JDK1.8 부터 final 생략 가능
class LocalInner{
int liv = outerIv;
int liv2 = outerCv;
// 외부 클래스의 지역변수는 final이 붙은 변수(상수)만 접근가능하다.
// int liv3 = lv; // 에러
int liv4 = LV; // Ok
}
}
}
※ 내부 클래스에서 private 멤버를 이용할 수 있다.
- private는 원래 다른 클래스에서는 사용할 수 없다.
- static 클래스 내에서는 여전히 안된다. instance 멤버이기 때문이다
※ 지역 내부 클래스에서는 변수는 이용할 수 없고 상수(final)만 이용할 수 있다.
- method() 내부의 변수는 지역변수이므로 method() 종료와 함께 소멸된다. method()는 한번 호출되면 종료와 함께 끝나기 때문이다.
- 내부 클래스의 객체가 더 오래 존재할 수 있다. 누구보다? 지역변수보다 method()가 종료되어도 상수니까 사용할 수 있다.
- 하지만 JDK1.8부터는 변수의 값을 설정하고 바꾸지만 않으면 에러가 나지 않는다.그래도 그냥 왠만하면 붙이는 것이 좋다.
외부 클래스와 내부 클래스의 변수 구분하기
class Outer3{
int value = 10; //Outer3.this.value
class Inner{
int value = 20; //this.value
void method1(){
int value = 30; // value
System.out.println(" value:" + value);
System.out.println(" this.value:" + this.value);
System.out.println("Outer3.this.value:" + Outer3.this.value);
}
}
}
class Ex7_16{
public static void main(String args[]){
Outer3 outer = new Outer3();
Outer3.Inner inner = outer.new Inner();
inner.method1();
}
}
[참고 자료]
'프로그래밍 공부 > Java' 카테고리의 다른 글
Java 기초 - 컬렉션 프레임워크 (3) [Stack과 Queue] (0) | 2022.05.04 |
---|---|
Java 기초 - 컬렉션 프레임워크 (2) [List 컬렉션 클래스] (0) | 2022.05.04 |
Java 기초 - 컬렉션 프레임워크 (1) [컬렉션 프레임워크(collection framework)] (0) | 2022.05.04 |
Java 기초 - 람다식 표현 (0) | 2022.05.04 |
Java 기초 - 익명 클래스 (0) | 2022.05.04 |