내부 클래스(Inner Class)는 클래스 내에 선언된 클래스 입니다. 주로 외부 클래스와 연관되어 있을 때 사용되며, 내부 클래스는 외부클래스의 멤버들을 쉽게 접근 할 수 있습니다.
class 외부클래스{
class 인스턴스내부클래스{ } static class 정적내부클래스{ } void 메서드(){ class 지역내부클래스{ } }
}
내부 클래스는 선언하는 위치나 예약어에 따라 크게 4가지 유형으로 나뉠 수 있습니다.
인스턴스 내부 클래스(instance inner class)
: 외부 클래스의 멤버변수 선언위치에 선언 : 외부 인스턴스 변수, 외부 전역 변수 사용 가능정적 내부 클래스(static inner class)
: 외부 클래스의 멤버변수 선언위치에 선언 : 외부 전역 변수 사용 가능지역 내부 크래스(local inner class)
: 외부 클래스의 메서드나 초기화블럭 안에 선언 : 외부 인스턴스 변수, 외부 전역 변수 사용 가능익명 내부 클래스(annonymouse inner class)
: 클래스 선언과 객체 생성을 동시에 하는 일회용 익명 클래스 : 외부 인스턴스 변수, 외부 전역 변수 사용 가능package JAVA_Collection;
class Outer{
private int num = 1; //인스턴스 변수
private static int sNum; //클래스 변수
private InClass inClass; //내부 클래스 변수
public Outer(){ //생성자
inClass = new InClass();
}
private class InClass{ //내부 클래스 선언
int inNum =10;
//private로 선언된 필드들에 쉽게 접근할 수 있습니다.
void Test(){
System.out.println("Outer num = " + num + "(외부 클래스의 인스턴스 변수)");
System.out.println("Outer sNum = " + sNum + "(외부 클래스의 정적 변수)");
}
}
public void testClass(){
inClass.Test(); //내부 클래스의 메서드 호출
}
}
public class InstanceInnerClass {
public static void main(String[] args) {
Outer outer = new Outer(); //외부 클래스의 인스턴스 생성
System.out.println("외부 클래스 사용하여 내부 클래스 기능 호출");
outer.testClass(); //외부 클래스의 메서드 -> 내부 클래스의 메서드
}
}
//Console
외부 클래스 사용하여 내부 클래스 기능 호출
Outer num = 1(외부 클래스의 인스턴스 변수)
Outer sNum = 0(외부 클래스의 정적 변수)
외부 클래스의 private로 선언된 멤버변수를 내부 클래스에서 사용 가능합니다, 단 인스턴스 내부 클래스는 외부 클래스의 인스턴스를 생성한 이후에 사용가능합니다. 인스턴스 내부 클래스 내에 정적 변수와 정적 메서드를 선언할 수 없습니다.
인스턴스 내부 클래스와 선언할 위치는 동일하지만 클래스 멤버와 마찬가지로 static
예약어를 사용하여 정적 내부 클래스임을 알립니다.
package JAVA_Collection;
class Outer2{
private int num = 3; //인스턴스 변수
private static int sNum = 4; //클래스 변수
void getPrint(){ //외부 클래스의 인스턴스 메서드
System.out.println("인스턴스 메서드");
}
static void getPrintStatic(){ //외부 클래스의 클래스 메서드
System.out.println("스태틱 메서드");
}
static class StaticInClass{
void test(){ //내부 클래스의 인스턴스 메서드 내부 클래스의 인스턴스화 필요
System.out.println("Outer num = " +sNum + "(외부 클래스의 정적 변수)");
getPrintStatic();
}
static void testStatic(){ //내부 클래스의 클래스 메서드, 내부 클래스의 인스턴스화 불필요
System.out.println("스태틱 클래스의 스태틱 메서드");
}
}
}
public class StaticInnerClass {
public static void main(String[] args) {
Outer2.StaticInClass a = new Outer2.StaticInClass(); //내부 클래스 생성
//스태틱 내부 클래스는 외부 인스턴스 없이 내부 인스턴스 생성 가능
a.test(); //내부 클래스의 인스턴스 메서드
Outer2.StaticInClass.testStatic(); //내부 클래스의 클래스 메서드
}
}
//Console
Outer num = 4(외부 클래스의 정적 변수)
스태틱 메서드
스태틱 클래스의 스태틱 메서드
지역 내부 클래스는 클래스의 멤버가 아니라 메서드 내에서 정의 되는 메서드입니다. 지역 변수 처럼 정의된 메서드 내부에서만 사용가능 하므로 선언 후 바로 객체를 생성해서 사용합니다. 또 정적 클래스로 지정할 수 없습니다.
package JAVA_Collection;
class Outer3{
int num = 3; //외부 클래스의 인스턴스 변수
void test() {
int num2 = 6; //지역 변수
class LocalInClass{ //지역 내부 클래스
void getPrint(){ //지역 내부 클래스의 인스턴스 메서드
System.out.println(num); //지역 변수
System.out.println(num2); //인스턴스 변수
}
}
LocalInClass localInClass = new LocalInClass(); //지역 객체
localInClass.getPrint(); //지역 내부 클래스의 인스턴스 메서드
}
}
public class LocalInnerClass {
public static void main(String[] args) {
Outer3 outer = new Outer3(); //외부 객체 생성
outer.test(); //외부 객체의 메서드 실행
}
}
//Console
3 //지역 변수
6 //인스턴스 변수
익명 내부 클래스는 이름을 알 수 없는 내부 클래스를 의미합니다. 클래스 선언과 객체의 생성을 동시에 하기 때문에 하나의 객체만을 생성할 수 있으며 일회용 입니다. 지역내부 클래스와 유사하지만 일회성이고 더 간결하게 작성할 수 있습니다.
package JAVA_Collection;
interface Name{
public static final String name = "코딩 자투리"; //상수
public abstract void getName(); //추상 메서드
}
class TestClass2 implements Name{ //인터페이스를 구현한 클래스
public void getName(){ //오버라이딩
System.out.println("내 이름은 " + name);
}
}
public class AnnonymousClass {
public static void main(String[] args) {
TestClass2 outer = new TestClass2(); //객체 생성
outer.getName(); //객체의 메서드 호출
new Name(){ //익명 클래스
public void getName(){ //오버라이딩
System.out.println("내 이름은 " + name);
}
}.getName(); //객체를 만들고 바로 실행
}
}
//Console
내 이름은 코딩 자투리 //객체의 메서드 호출
내 이름은 코딩 자투리 //익명 클래스의 메서드 호출
안드로이드를 공부하고 프로젝트를 진행할때 내부 클래스와 익명 클래스를 종종 자주 사용 하였었습니다. 스프링이라는 프레임 워크도 내부 클래스와 익명 클래스를 자주 사용한다는 소식을 들은 적이 있습니다. 오늘 학습을 잘 새겨두어 스프링 학습시 원할하도록 해야 겠습니다.
https://github.com/ds02168/CodeStates/tree/main/src/JAVA_Collection