Java에서는 한 클래스를 다른 클래스 내에 정의할 수 있는데, 이를 클래스 중첩이라고 합니다. 클래스 중첩에는 두 가지 유형이 있는데, 정적 클래스는 정적 중첩 클래스라고 하고, 비정적 클래스는 내부 클래스라고 합니다.
중첩 클래스를 사용하는 이유:
한 곳에서만 사용되는 클래스를 합리적으로 결합할 수 있습니다. 한 클래스는 다른 클래스에만 유용할 수 있습니다. 이 경우 전자와 후자를 결합하면 패키지가 더 간결해질 수 있습니다.
캡슐화를 강화하세요. 두 개의 클래스 A와 B가 있는 경우 클래스 B는 클래스 A의 멤버를 사용해야 하며 이 멤버는 클래스 내에서만 표시됩니다. B가 A의 중첩 클래스로 정의된 경우 B는 클래스 A의 모든 멤버를 사용할 수 있습니다. A. , B 는 외부적으로 보이지 않게 선언될 수도 있습니다.
코드를 더 읽기 쉽고 유지 관리하기 쉽게 만들 수 있습니다. 중첩된 클래스 코드는 최상위 클래스보다 사용 위치에 더 가깝기 때문에 보기가 더 쉽습니다.
중첩 클래스도 클래스의 멤버이므로 클래스 멤버의 가시적 범위 제어 수정자를 사용할 수도 있습니다. 내부 클래스는 자신이 위치한 클래스의 다른 클래스 멤버를 사용할 수 있지만 정적 중첩 클래스는 사용할 수 없습니다. 수업의 다른 수업 구성원을 사용하십시오.
정적 중첩 클래스
정적 메서드 및 정적 필드와 유사하게 정적 중첩 클래스는 자신이 위치한 클래스와 관련됩니다. 정적 중첩 클래스는 인스턴스 변수나 인스턴스 필드를 직접 사용할 수 없으며 객체를 통해서만 참조할 수 있습니다. 정적 중첩 클래스는 다른 최상위 클래스와 동일하게 간주될 수 있지만 패키징을 용이하게 하기 위해 다른 클래스에 포함됩니다.
정적 중첩 클래스의 사용법은 클래스의 다른 클래스 멤버와 유사합니다. 정적 중첩 클래스 객체를 만드는 방법을 보여드리겠습니다.
//StaticNestedClass为OuterClass的一个嵌套类OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
내부 클래스(비정적 중첩 클래스)
내부 클래스는 자신이 위치한 클래스의 인스턴스와 관련되어 있으므로 인스턴스 객체의 메서드와 필드를 직접 사용할 수 있습니다. 정적 멤버를 정의합니다.
내부 클래스 객체를 생성하려면 먼저 아래와 같이 내부 클래스가 위치한 클래스의 객체를 생성해야 합니다.
//1创建内部类所在类的对象OuterClass outerObject=new OuterClass();//2创建内部类对象 //注意与静态嵌套类的构造器使用方法的差异OuterClass.InnerClass innerObject = outerObject.new InnerClass();
중첩 클래스의 음영 처리
유형을 선언할 때 해당 이름에 현재 코드 블록(예: 메소드 내부)이 있는 코드 블록(예: 클래스 내부)에 있는 다른 유형의 선언과 동일한 이름이 포함되어 있는 경우 이 현상을 마스킹이라고 합니다. 마스크된 유형을 사용해야 하는 경우 다음 예와 같이 해당 이름을 직접 참조할 수 없습니다.
public class ShadowTest { public int x = 0; //嵌套类 class FirstLevel { //以下声明会遮蔽其所在类的名称为x的字段 public int x = 1; //以下方法的声明会遮蔽其所在类的名称为x的字段 void methodInFirstLevel(int x) { System.out.println("x = " + x); System.out.println("this.x = " + this.x); System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);//注意this关键词的使用方法 } } public static void main(String... args) { ShadowTest st = new ShadowTest(); ShadowTest.FirstLevel fl = st.new FirstLevel(); fl.methodInFirstLevel(23); } }
위 코드의 출력은 다음과 같습니다.
x = 23
this.x = 1
ShadowTest.this.x = 0
직렬화, 튜토리얼에서는 내부 클래스를 직렬화하지 말 것을 강력히 권장합니다. 여기에 질문을 남겨주세요.
비정적 중첩 클래스 외에도 내부 클래스에는 두 가지 유형이 있는데, 하나는 로컬 클래스이고 다른 하나는 익명 클래스입니다.
부분 클래스
로컬 클래스는 모든 코드 블록(중괄호 내)에서 정의할 수 있으며 일반적으로 메서드에서 사용됩니다.
로컬 클래스는 자신이 위치한 최상위 클래스의 클래스 멤버를 사용할 수 있습니다. 또한 로컬 클래스도 로컬 변수를 사용할 수 있습니다. 단, 사용하는 로컬 클래스는 final 키워드로 수정해야 합니다. 즉, 불변 변수입니다. Java SE8에서 로컬 클래스는 본질적으로 변경되지 않은 로컬 변수를 사용할 수 있습니다. 즉, 로컬 변수가 final 키워드로 수정되지 않더라도 초기화 이후 해당 값은 변경되지 않습니다.
java8부터 로컬 클래스도 해당 메소드의 매개변수를 사용할 수 있습니다.
내부 클래스와 마찬가지로 로컬 클래스는 정적 멤버를 정의할 수 없으며 정적 메서드에 정의된 로컬 클래스는 인스턴스 멤버를 사용할 수 없습니다.
인터페이스는 본질적으로 정적이기 때문에 코드 블록에서 정의할 수 없습니다. Excuse 멤버는 로컬 클래스에서 정의할 수 없지만 상수 변수는 로컬 클래스에서 정의할 수 있습니다(final로 수정하고 유형은 기본 데이터 유형 또는 문자열이며 컴파일 타임에 초기화됩니다).
익명 클래스
익명 클래스는 이름이 필요하지 않고 한 단계로 선언하고 인스턴스화할 수 있어 코드를 더욱 간결하게 만들 수 있습니다.
익명 클래스의 선언은 클래스를 정의하는 코드 블록이 뒤에 따른다는 점을 제외하면 생성자를 호출하는 것과 같은 표현식입니다.
익명 클래스 정의 표현식에는 다음과 같은 부분이 포함됩니다.
새 키워드
익명 클래스가 구현해야 하는 변명 또는 상속받은 부모의 이름 class
인터페이스를 포함한 괄호 한 쌍. 인터페이스 구현 시 매개변수 부분은 비워두세요
익명 클래스 몸체, 클래스 몸체와 유사하게 메소드를 정의할 수 있습니다
익명 클래스 사용할 수 있는 타입은 로컬 클래스와 동일합니다.
자신이 위치한 클래스의 클래스 멤버를 사용할 수 있습니다.
로컬 변수를 다음과 같이 사용할 수 있습니다. 위치한 코드 블록의 최종 수정자 또는 더 이상 초기화 이후 할당된 지역 변수(java8)
그림자 유형의 경우 이름으로 직접 참조할 수 없습니다
마찬가지로 익명 클래스 정적 멤버나 인터페이스는 선언할 수 없지만 익명 클래스에서는 상수 변수를 선언할 수 있습니다. 클래스 본문에서는 인스턴스 필드, 인스턴스 메서드, 인스턴스 초기화 코드 블록 및 로컬 클래스를 선언할 수 있습니다.