[JAVA] 내부 클래스, 스태틱 클래스와 익명 클래스

김민기·2021년 3월 2일
0

Java

목록 보기
14/20
post-thumbnail

내부 클래스(이너 클래스, Nested Class)

내부 클래스는 클래스 내에 선언되는 클래스입니다. 내부의 클래스가 외부 클래스와 연관관계가 깊으며, 다른 클래스에서 사용되지 않을 때 내부클래스를 사용하게됩니다.

내부 클래스 선언

내부 클래스의 구분은 변수의 선언에 따른 구분과 비슷하게 이루어집니다. 인스턴스 변수와 같이 선언하면 인스턴스 클래스, 스태틱 변수처럼 선언하면 스태틱 클래스, 블록 내에 선언하면 로컬 클래스입니다.

내부 클래스 제어자 및 접근

내부 클래스도 abstractfinal, 그리고 private, protected와 같은 접근 제어자를 사용할 수 있습니다. 다만 static 멤버는 스태틱 클래스만 가질 수 있습니다. 다만 finalstatic 이 모두 사용된 상수는 모든 내부 클래스에서 정의가 가능합니다.또한 내부 클래스와 외부클래스는 서로의 멤버가 private 제어자로 선언되어 있어도 접근이 가능합니다.

멤버 변수의 메서드 접근처럼, 스태틱 클래스는 인스턴스 멤버에 접근할 수 없습니다. 또 스태틱 클래스는 외부 클래스의 인스턴스 없이 직접 객체를 선언할 수 있습니다. 이와 같은 규칙들은 모두 클래스 - 스태틱 멤버 간의 규칙을 따릅니다.

class OuterClass{
	private static int oStaticInt;
	private int oInt;
	public OuterClass() {
		System.out.println("I'm O");
		
		//각각의 이너클래스의 private에 접근가능
		//이너클래스의 스태틱 멤버접근 가능
		A.aStaticInt = oStaticInt;
		
		// 인스턴스가 없는 A 클래스멤버 접근 불가
		oInt = A.aInt;
		
	}
	static class A {
		private static int aStaticInt;
		private int aInt; 
		public A() {
			System.out.println("I'm A");
			oStaticInt = aStaticInt;
			
			//인스턴스가 생성되지 않은 OuterClass의 멤버에 접근 불가 
			oInt = aInt;
		}
	}
	class B{
		private int bInt;
		//Non-Static 클래스에 static 멤버 선언 불가
		private static int bStaticInt;
		public B() {
			A.aStaticInt = bInt;
			oInt = bInt;
		}
	}
}
public class InnerStaticClassTest {
	public static void main(String[] args) {
		OuterClass o = new OuterClass();
		//외부 클래스 인스턴스 없이 접근 가능
		OuterClass.A a = new OuterClass.A();
		//외부 클래스의 인스턴스를 통해서만 접근 가능
		OuterClass.B b = o.new B();
	}
}

내부 클래스 종류

인스턴스 클래스

  • 외부 클래스의 속성 선언 위치에 선언
  • 외부 클래스의 인스턴스 멤버처럼 취급
  • 외부 클래스의 멤버 및 메서드에 모두 접근 가능
    • JDK 1.8 부터 final이 없는 인스턴스 멤버에도 접근이 가능
  • 외부 클래스의 인스턴스가 있어야만 접근 가능

스태틱 클래스

  • 외부 클래스의 속성 선언 위치에 선언
  • static 멤버처럼 다루어지며 static 메서드 및 static 멤버에서 사용
  • 외부 클래스의 인스턴스 없이 접근 가능

** 자바에서 스태틱 키워드가 의미하는 바를 정확히 이해해야 합니다. 스태틱 메서드, 변수, 클래스 모두 상위에 존재하는 클래스의 인스턴스를 필요로 하지 않습니다. 스태틱 클래스는 인스턴스를 만들 수 있느냐 없느냐가 아닌 스태틱 키워드 관점에서 클래스 로딩 시점에 접근할 수 있는 지 없는 지를 판단하는 것입니다. **

로컬 클래스

  • 메서드 및 초기화 블럭과 같은 블럭 내에 선언
  • 해당 블럭 내에서만 접근할 때 사용

익명클래스

  • 클래스의 선언과 동시에 객체 생성
  • 이름이 없는 한 번 사용하고 버려지는 클래스
  • 클래스 명이 존재하지 않기 때문에 상속하여 재정의해서 사용

내부 클래스를 사용하는 이유

외부 클래스의 메서드가 기능이 많아 기능별로 분류하거나, 선언하려는 클래스가 외부 클래스에 종속적일경우 사용합니다.

내부클래스는 대부분 외부클래스에 종속적으로 사용되므로 외부에서는 접근할 수 없도록 private 제어자를 사용하고 내부클래스의 인스턴스를 생성할 필요가 없을 경우 static 제어자를 사용합니다.

내부 클래스 사용 이점

어떤 클래스가 다른 클래스에 종속적이라면 각각 선언했을 때 캡슐화된 클래스들 간의 멤버 변수 접근 간에 gettersetter 를 사용해야하며 각각은 서로에 의존적일 수 있습니다. 이럴경우 내부클래스로 선언하여 종속적인 클래스에 대해서 캡슐화를 할 수 있습니다. 이 경우 내부 클래스와 외부 클래스는 서로의 멤버 접근에 자유로우므로 gettersetter 를 사용하지 않고도 서로의 멤버에 접근하게 할 수 있습니다.

익명 클래스(anonymous class)

익명클래스는 이름이 없는 클래스입니다. 즉 클래스의 선언과 생성을 단 한번하고 사라지게 됩니다. 생성자도 존재하지 않으며 클래스 상속 또는 인터페이스 구현체의 메서드를 재정의한 인스턴스를 단 한번 사용하기 위해 선언합니다.

new SuperClass(){
	@Override
	public method(){}
}
new Interface(){
	@Override
	public method(){}
}

이름이 없으므로 슈퍼클래스 혹은 인터페이스의 이름으로 객체를 생성합니다. 오버라이딩할 메서드를 생성과 동시에 재정의해서 사용합니다.

  • 생성된 익명클래스는 다시사용되지 않기 때문에 GC 에 의해서 수집
  • 어댑터 클래스의 대부분이 익명클래스를 통해 사용

JDK 1.8 이후로는 람다식이 추가되어 익명클래스 대신에 람다식을 통해 구현할 수 있습니다.


참고 : 자바의 정석 1권
내부 정적 클래스 참고 : https://stackoverflow.com/questions/7486012/static-classes-in-java

profile
민기1

0개의 댓글