자바의 내부 클래스

내부 클래스 의미
이름 상태로,다른 클래스 내부의 클래스는 내부 클래스라고합니다.
내부 클래스는 외부 클래스의 모든 멤버(심지어private사람)에 액세스 할 수 있다는 점에서 포함하는 클래스와 특별한 관계를 공유합니다.
이는 내부 클래스가 다른 필드 및 메서드와 마찬가지로 외부 클래스의 멤버이기 때문입니다.
내부 클래스는 다른 클래스 내부의 클래스이므로 중첩 클래스라고도 할 수 있습니다.
내부 클래스의 유형
내부 클래스는 다음과 같은 유형이 될 수 있습니다.

  1. 일반 또는 일반 또는 중첩 된 내부 클래스(일반적으로 내부 클래스라고 함)
  2. 메소드 로컬 내부 클래스.
  3. 익명 내부 클래스.
  4. 정적 중첩 클래스

1. 중첩 된 내부 클래스
이 섹션에서는 내부 클래스의 모든 세부 사항을 파헤칩니다. 단순화를 위해 다음 클래스를 고려하십시오

class Outer { private String outerField = "Outer"; class Inner { private String innerField = "Inner"; }}

여기서 바깥 쪽은 바깥 쪽 클래스이고 안쪽은 바깥 쪽 내부에 포함 된 안쪽 클래스입니다.

내부 클래스의 개체 만들기
내부 클래스가 다른 클래스 안에 있습니다. 포함하는 클래스를 외부 클래스라고합니다. 따라서 내부 클래스는 외부 클래스 없이는 존재할 수 없으며 해당 객체(또는 인스턴스)에도 동일하게 적용됩니다.
내부 클래스의 객체는 외부 클래스의 객체 없이는 존재할 수 없습니다.
즉,내부 클래스의 인스턴스를 만들려면 외부 클래스의 인스턴스가 필요합니다.
따라서,내부 클래스의 객체는 아래 주어진 방법에 의해 생성 될 수있다.

// first, create object of outer classOuter outerObject = new Outer();// create object of inner classInner innerObject = outerObject.new Inner();

예제에서 명확한 바와 같이,내부 클래스의 객체를 만들려면,외부 클래스의 객체가 필요하다.
내부 클래스 개체를 만드는 짧은 손 방법도 있습니다.

Inner innerObject = new Outer().new Inner();

이 메서드에는 외부 클래스 객체도 필요합니다.
그냥 Remember….An 내부 클래스의 객체는 포함(또는 외부 클래스)의 객체 없이는 만들 수 없습니다.

외부 클래스 내에서 내부 클래스 개체 만들기
이전 예에서는 외부 클래스 외부에서 내부 클래스를 인스턴스화하고 있다고 가정합니다.
그러나 대부분의 경우 외부 클래스가 내부 클래스를 사용하기 때문에 외부 클래스 내부에서만 내부 클래스의 객체가 필요합니다.
그렇다면 외부 클래스 내부에서 내부 클래스의 객체를 어떻게 생성합니까?
아래의 수정 된 샘플 클래스를 고려하십시오.

class Outer { private String outerField = "Outer"; public void createInnerClassObject() { // create an object of inner class Inner innerObject = new Inner(); } class Inner { private String innerField = "Outer"; }}

Inner innerObject = new Inner();줄을 확인하십시오.
이전에는 외부 클래스의 객체 없이는 내부 클래스 객체를 만들 수 없지만 위의 코드 스 니펫이이를 수행하고 있다고 명시되었습니다. 혼란!!!!
위의 구문은 외부 클래스의 메서드 안에 작성되기 때문에 유효합니다.
이 코드가 실행 중일 때 이미 메서드를 실행하는 외부 클래스의 인스턴스가 있습니다.

항상 내부 클래스의 객체를 생성(또는 액세스)하기 위해,기억,외부 클래스의 인스턴스가 있어야한다.

요약,

  1. 내부 클래스의 객체가 외부 클래스 내에서 생성 될 때Inner innerObject = new Inner();으로 직접 생성 될 수 있습니다.
  2. 외부 클래스의 외부에서 내부 클래스의 개체를 만들 때Inner innerObject = new Outer().new Inner();으로 만들어야 합니다.

외부 및 내부 클래스의 객체를 인쇄 할 때 생성되는 출력은 다음과 같습니다:

외부 클래스 인스턴스는 다음과 같습니다. : 내부 클래스
에서 외부 클래스 인스턴스,필드 및 메서드 참조 내부 클래스는 다른 필드 및 메서드와 마찬가지로 포함 클래스의 멤버이기도합니다.
따라서,다른 필드 및 메소드가 서로 직접 액세스하는 것과 동일한 방식으로 외부 클래스의 다른 필드 및 메소드에 액세스 할 수있다.
이것은 내부 클래스에서 외부 클래스 필드 및 메소드에 액세스 할 때 적용됩니다.

그러나 외부 클래스의 인스턴스를 참조 할 때 차이가 있습니다. 클래스의 현재 인스턴스를 참조하기 위해this키워드가 사용됩니다.
내부 클래스의 경우 내부 클래스 내부에서this를 사용하면 외부 클래스가 아닌 내부 클래스의 현재 인스턴스를 나타냅니다.
내부 클래스에서 외부 클래스의 인스턴스를 참조하려면this키워드에 클래스 이름을 추가해야합니다.

따라서 내부 클래스에서 외부 클래스 인스턴스를 참조하려면Outer.this구문을 사용하십시오.
이해를 위해 아래 예를 참조하십시오.

class Outer { private String outerField = "Outer"; public void createInnerClassObject() { // create an object of inner class Inner innerObject = new Inner(); } class Inner { private String innerField = "Outer"; public innerClassMethod() { // access outer class field System.out.println("Outer field : " + outerField); // access inner class instance System.out.println("Inner instance : " + this); // access outer class instance System.out.println("Outer instance : " + Outer.this); } }}

출력

외부 필드:외부
내부 인스턴스:
외부 인스턴스:

2. 메소드 로컬 내부 클래스
이름에서 알 수 있듯이,메소드 내부에 정의 된 클래스는 메소드 로컬 내부 클래스입니다.
네,가능합니다.
아래와 같이 메서드 내부에 클래스를 정의할 수 있습니다.

// outer classclass Outer { // outer class method public void createClass() { // class inside a method class Inner { // inner class method public void innerMethod() { System.out.println("Method local inner class"); } } // inner class ends } // method ends}

위의 코드에는 메서드를 포함하는 클래스 외부가 있습니다.
이 메서드는 메서드 본문 안에 있는 클래스를 정의하므로 메서드 로컬 내부 클래스라고 합니다.
내부 클래스에는 자체 메서드 정의도 있습니다.

메서드 인스턴스화 로컬 내부 클래스
이전 코드는 메서드 로컬 내부 클래스를 선언하지만 내부 클래스의 개체를 만들지 않습니다.
이제 문제는 방법 로컬 내부 클래스의 객체를 생성하는 방법을 발생한다.
메소드 로컬 내부 클래스는 메소드 내부에 정의되어 있기 때문에 해당 메소드 내부에서만 볼 수 있으며 해당 메소드 내부에서만 객체를 만들 수도 있습니다.
아래 코드는 메소드 로컬 내부 클래스의 객체를 생성하고 해당 메소드를 호출합니다.

// outer classpublic class Outer { // outer class method public void createClass() { // class inside a method class Inner { // inner class method public void innerMethod() { System.out.println("Method local inner class method called"); } } // inner class ends // create inner class object Inner innerObject = new Inner(); // call inner class method innerObject.innerMethod(); } // outer class method ends // Main method public static void main(String args) { // create object of outer class Outer outerObject = new Outer(); // call outer class method outerObject.createClass(); }}

위의 코드가 실행될 때,다음은 출력

이 외부 클래스 메소드가 호출 될 때,내부 클래스의 객체를 생성하고 내부 클래스 메소드를 호출하는 것을 보여준다.

메소드 로컬 내부 클래스:포인트는
메소드 로컬 내부 클래스의 객체를 생성 문은 클래스 본체 외부에 작성해야합니다 기억합니다.
따라서 라인Inner innerObject = new Inner();은 로컬 클래스가 끝난 후에 와야합니다.

  1. 메서드 로컬 내부 클래스는 선언된 메서드 내부에서만 인스턴스화할 수 있습니다.
    메서드 클래스는 메서드 내부에서만 볼 수 있으므로 메서드 내부에서만 개체를 만들 수 있기 때문에 의미가 있습니다.
  2. 메소드 로컬 내부 클래스는이 선언되는 메소드의 로컬 변수에 액세스 할 수 없습니다.
    액세스해야 하는 경우final로 표시해야 합니다.
    이것은 자바 8 전에 적용 가능하다.
  3. 메소드 로컬 내부 클래스 내의 메소드 로컬 변수에 액세스 한 다음 다시 할당 할 수 없습니다. 이것은 컴파일러 오류가 될 것입니다.
    이것은 자바 8 에서 적용 할 수 있기 때문에 자바 8 이전의 버전은 내부 클래스 내부의 메소드 지역 변수에 액세스 할 수 없습니다.
  4. 메소드 로컬 내부 클래스는 내부 클래스를 포함하는 메소드가 속한 클래스의 필드 및 기타 메소드에 액세스 할 수 있습니다.
  5. 메서드 로컬 내부 클래스는 포함 메서드가static인 경우에만 내부 클래스를 포함하는 메서드가 속한 클래스의static필드 및 기타static메서드에 액세스할 수 있습니다.

3. 익명 내부 클래스
익명 이름이 알려져 있지 않음을 의미합니다. 자바의 맥락에서 익명 클래스는 이름이 없는 클래스입니다.
익명 클래스라는 용어는 외부 클래스에 이름이 있어야하므로 내부 클래스에만 적용됩니다.
익명 클래스는 항상 다른 클래스 안에 정의되기 때문에 내부 클래스입니다.

자바
의 익명 클래스 유형 실제로 익명 클래스는 이미 존재하는 클래스 또는 다른 곳에 기록 된 인터페이스의 구현이지만 필요에 따라 다른 클래스 내에서 다시 정의됩니다.
이것은 혼란스럽게 들릴 수 있지만 그 다음에 나오는 예들은 개념을 명확히 할 것이다.

익명 클래스가 클래스 또는 인터페이스의 구현인지 여부에 따라 다음 두 범주에 속할 수 있습니다. 클래스의 하위 클래스
의 첫 번째 예부터 시작하자

// Already existing classclass Website {public void printName() {System.out.println("No website till now");}}class SearchEngine { // Notice the syntax Website w = new WebSite() { public void printName() { System.out.println("Website is codippa.com"); } };}

위의 예에서,이미 생성 된 클래스라는 이름의 웹 사이트가있다.
다른 클래스 검색 엔진은이 클래스를 재정의하고,그 메소드를 구현하고,실제 클래스와 동일한 유형의 참조 변수에 할당한다.
이 참조 변수를 사용하여 새로 구현 된 메소드를 호출 할 수도 있습니다.

새로 구현된 익명 클래스는 실제 클래스의 하위 클래스임을 기억하십시오.
그것은 다형성을 따르고 그 객체는 웹 사이트 클래스의 객체가 예상되는 곳 어디에서나 전달 될 수 있습니다.
아래 예제를 통해 설명하십시오.

class Website { public void printName() { System.out.println("No website till now"); }}class SearchEngine { // Notice the syntax Website w = new WebSite() { public void printName() { System.out.println("Website is codippa.com"); } }; // Expects an instance of Website class public void getWebsite(Website web) { // call the method of Website class web.printName(); } // Main method public static void main(String args) { // create an object of this class SearchEngine obj = new SearchEngine(); // call its method and pass instance of Website class obj.getWebsite(obj.w); }}

웹 사이트 클래스의 구현을 미리 정의하는 대신 필요한 경우 정의 할 수 있습니다.
따라서 주 메소드는

public static void main(String args) { SearchEngine obj = new SearchEngine(); // Notice the implementation of Website class as argument obj.getWebsite(new Website() { public void print() { System.out.println("Dynamic implementation"); } });}

로 수정할 수 있습니다 위의 구현은 참조 변수에 할당되지 않으며 이름이 없으므로 이름이 익명입니다.

두 클래스가 동일한 파일이나 패키지에 있을 필요는 없습니다. 그들은 서로 상대적인 곳에 위치 할 수 있습니다.

인터페이스 구현자
익명 클래스는 인터페이스의 구현자로 정의할 수도 있습니다.
이 경우 인터페이스에 선언 된 메소드의 구현을 정의하고 인터페이스의 객체가 예상되는 모든 곳에서 전달할 수 있습니다.
아래 예제를 참조하여 명확히 하십시오.

interface WebInterface { // interface method declaration public void print();}class SearchEngine { // Notice the syntax WebInterface w = new WebInterface() { // Interface method implementation public void printName() { System.out.println("Website is codippa.com"); } }; // Expects an instance of WebInterface interface public void getWebsite(WebInterface web) { // call the method of WebInterface web.printName(); } // Main method public static void main(String args) { // create an object of this class SearchEngine obj = new SearchEngine(); // call its method and pass instance of WebInterface obj.getWebsite(obj.w); }}

이전과 마찬가지로 아래 그림과 같이 필요한 경우 익명 클래스로서의 인터페이스 구현을 만들 수 있습니다.

public static void main(String args) { SearchEngine obj = new SearchEngine(); // Notice the implementation of WebInterface as argument obj.getWebsite(new WebInterface() { public void print() { System.out.println("Dynamic implementation"); } });}
인터페이스 이름 앞에new키워드를 사용합니다. 익명 클래스는 가능한 유일한 장소입니다.

다형성 익명 클래스에서
앞에서 언급했듯이 익명 클래스는 다형성을 따릅니다.
그것들은 서브 클래스이기 때문에 다형성을 따라야합니다. 이 섹션은 방법을 자세히 설명합니다.
아래의 클래스를 고려하십시오.

class Metal { public void printThickness() { System.out.println("Thick enough"); }}class MetalDriver { // Anonymous class definition Metal metal = new Metal() { public void printThickness() { System.out.println("Thick enough"); } // new method public boolean hasLustre() { return false; } }; public void printMetalDetail(Metal m) { // call method present in actual class definition. No problem!!! m.printThickness(); // call newly defined method in Anonymous class. Compiler Error!!! m.hasLustre(); }}

위의 코드는 단일 메서드로 클래스 금속을 정의합니다.
이 클래스는 다른 클래스 금속 드라이버에서 익명으로 다시 구현되며 실제 클래스에는 없는 새로운 메서드가 정의에 추가됩니다.

이제이 새로운 메서드가 호출 될 때 컴파일러는 오류

이 메서드는 금속 유형에 대해 정의되지 않았습니다.

이는 익명 클래스가 하위 클래스이고 참조가 실제 클래스(부모)이기 때문입니다.
컴파일러가 부모 클래스에서 새 메서드를 찾을 수 없으며 오류를 플래그합니다.

따라서 오류는 두 가지 사실을 설정합니다:
(1)익명 클래스는 실제 클래스의 하위 클래스이고
(2)익명 클래스 정의는 다형성을 따릅니다.

익명 클래스 사용
인터페이스인 형식의 인수를 사용하는 메서드를 호출해야 한다고 가정합니다.
이제 이 인터페이스는 일부 외부 라이브러리에 속하며이 인터페이스를 구현하는 클래스가 없습니다.
이 방법을 어떻게 호출합니까? null을 통과하면 런타임 예외가 발생할 위험이 있습니다.
구조에 익명 클래스.
이제 이 인터페이스를 구현하는 익명 클래스를 만들고 필요에 따라 메서드의 구현을 제공하는 메서드 위에 전달할 수 있습니다.
예는 다음과 같습니다.

// Interface from external Libraryinterface External { public void interfaceMethod();}class CalledClass { // Method to called. Takes an argument of interface type public void toBeCalled(External e) { e.interfaceMethod(); }}

위의 코드에는 단일 메서드와 코드에서 메서드를 호출해야하는 클래스가있는 인터페이스가 있습니다.

이 클래스의 메서드는 인터페이스 형식의 인수를 사용하지만이 인터페이스를 구현하는 클래스가 없습니다.
메서드 인수에null을 전달하면 바로java.lang.NullPointerException가 발생합니다.
익명 클래스를 사용하여 이 메서드를 어떻게 호출할 수 있는지 살펴봅니다.

class CallingClass { // Main method public static void main(String args) { CalledClass obj = new CalledClass(); // call method using Anonymous class obj.toBeCalled(new External() { public void interfaceMethod() { // your code } }); }}

익명 인터페이스 구현을 사용하여 메서드를 호출합니다.
이것은 익명 클래스의 가장 큰 이점입니다.
4. 정적 중첩 클래스
다른 클래스 내에 정의된 정적 클래스는 정적 중첩 클래스입니다. 그것은 정적 키워드 앞에 일반 클래스 처럼 정의 됩니다.
정적 클래스로 아무것도 없다는 것을 기억,정적 중첩 클래스는 외부 클래스의 정적 멤버입니다.
정적 멤버이므로 정적 중첩 클래스에 적용됩니다.

  1. 외부 클래스에서 해당 인스턴스를 사용하지 않고 직접 액세스 할 수 있습니다.
  2. 외부 클래스의 정적 멤버에만 액세스 할 수 있지만 인스턴스 변수 또는 메서드는 액세스 할 수 없습니다.

정적 중첩 클래스 예제

public class Outer { // static nested class static class Inner { public void innerMethod() { System.out.println("Method of static nested class"); } } public void outerMethod() { System.out.println("Method of outer class"); } public static void main(String args) { // access inner class directly Inner inner = new Inner(); // call nested class method inner.innerMethod(); }}

위의 예에서 볼 수 있듯이 정적 중첩 클래스에 액세스하려면 외부 클래스의 인스턴스가 필요하지 않으며 직접 액세스 할 수 있습니다.
정적 중첩 클래스의 객체는 외부 클래스의 비 정적 멤버에 액세스 할 수 없습니다. 위의 예에서 중첩 클래스 인스턴스는 외부 클래스의outerMethod를 호출 할 수 없습니다.

  1. 내부 클래스가 포함 된 클래스가 컴파일되면
    하나는 외부 클래스 용이고 하나는 내부 클래스 용입니다.
    예,외부.클래스 및 외부$내부.각각 외부 클래스 외부 및 내부 클래스 내부 클래스..
  2. 내부 클래스의 클래스 파일을 직접 자바 명령을 사용하여 실행할 수 없습니다.
  3. 일반 내부 클래스는static데이터 멤버 또는 메서드를 가질 수 없습니다.
  4. 내부 클래스는 생성자를 가질 수 있습니다.
  5. 메서드 로컬 클래스는 메서드가 정의된 메서드 내부에서만 인스턴스화할 수 있습니다.
  6. static메서드에 정의된 메서드 로컬 클래스는 바깥쪽 클래스의static멤버만 액세스할 수 있습니다.
  7. 인터페이스를 구현하는 익명 클래스는 많은 인터페이스를 구현할 수있는 일반 클래스와 달리 하나의 인터페이스 만 구현할 수 있습니다.
  8. 익명 클래스는 클래스를 확장하고 일반 클래스가 할 수있는 동시에 인터페이스를 구현할 수 없습니다.
  9. 익명 클래스 정의는};(세미콜론을 확인하십시오).
  10. 메서드를 호출하는 동안 인수로 정의되는 익명 클래스는});(세미콜론을 확인합니다).
  11. 실제 클래스에 없는 익명 클래스 참조에서 메서드를 호출할 수 없습니다.
  12. 앞에static가 있는 내부 클래스를 내부 클래스가 아닌 중첩 클래스라고 합니다.

Leave a Reply