문제

이 두 내부 클래스 선언의 차이점은 무엇입니까?장점/단점에 대해서도 언급하시겠습니까?

사례 A:수업 안의 수업.

public class Levels {   
  static public class Items {
    public String value;
    public String path;

    public String getValue() {
      return value;}
  }
}

사례 B:인터페이스 내의 클래스.

public interface Levels{

  public class Items {
    public String value;
    public String path;

    public String getValue() {
      return value;}
  }
}

수정됨:getvalue 메소드 배치.

추가 정보:인터페이스를 전혀 구현하지 않는 다른 클래스에서 A와 B 두 경우 모두 Items 클래스를 인스턴스화할 수 있습니다.

public class Z{//NOTE: NO INTERFACE IMPLEMENTED here!!!!
 Levels.Items items = new Levels.Items();
}

인터페이스가 인스턴스화되지 않기 때문에 인터페이스를 인스턴스화할 수 없기 때문에 인스턴스화되지 않은 LEVELS 인터페이스 없이 인터페이스 내부의 모든 요소에 점 표기법으로 액세스할 수 있습니다. 즉, 인터페이스 내부에 정의된 클래스를 정적 ​​참조에 투과 가능하게 만드는 것입니다.

따라서 B의 경우 Items 클래스가 정적이 아니라고 말하는 것은 의미가 없습니다.A와 B 사례 모두 동일한 방식으로 인스턴스화되므로 정적, 내부 또는 중첩에 대한 의미를 찾고 있지 않습니다.의미론에 대한 답변을 중단하세요.나는 컴파일러, 런타임 및 동작의 차이점/장점을 원합니다. 그렇지 않다면 그렇게 말하십시오.더 이상 의미론에 대한 답변이 없습니다!!!!!JVM 또는 .NET VM 사양 내부 전문가는 교과서 의미론자보다는 이 질문에 답변해 주시기 바랍니다.

도움이 되었습니까?

해결책

정적 내부 클래스는 내부 클래스가 모든 클래스에 액세스할 수 있다는 점을 제외하면 대부분 최상위 클래스와 유사합니다. 공전 둘러싸는 클래스의 변수 및 메소드.바깥쪽 클래스 이름은 내부 클래스의 패키지 네임스페이스에 효과적으로 추가됩니다.클래스를 정적 ​​내부 클래스로 선언함으로써 클래스가 바깥쪽 클래스의 컨텍스트와 불가분하게 연결되어 있음을 전달하는 것입니다.

비정적 내부 클래스는 덜 일반적입니다.주요 차이점은 비정적 내부 클래스의 인스턴스에는 바깥쪽 클래스의 인스턴스에 대한 암시적 참조가 포함되어 있으며 결과적으로 해당 바깥쪽 클래스 인스턴스의 인스턴스 변수 및 메서드에 액세스할 수 있다는 것입니다.이로 인해 이상하게 보이는 인스턴스화 관용구가 생성됩니다. 예를 들면 다음과 같습니다.

Levels levels = new Levels(); // first need an instance of the enclosing class

// The items object contains an implicit reference to the levels object
Levels.Items items  = levels.new Items(); 

비정적 내부 클래스는 정적 내부 클래스보다 바깥쪽 클래스에 훨씬 더 밀접하게 연결되어 있습니다.유효한 용도가 있습니다(예를 들어 반복자는 반복하는 데이터 구조의 클래스 내에서 정적이 아닌 내부 클래스로 구현되는 경우가 많습니다).

실제로 정적 내부 클래스 동작만 필요할 때 비정적 내부 클래스를 선언하는 것은 흔한 실수입니다.

다른 팁

static 내부 클래스는 중첩 클래스이고, 비정적 클래스는 내부 클래스라고 합니다.이상, 이봐.

그러나 나는 동일한 링크에서 발췌한 내용을 인용하고 싶습니다.

정적 중첩 클래스는 외부 인스턴스의 멤버 class (및 다른 클래스)는 다음과 같습니다. 다른 최상위 클래스.사실상, 정적 중첩 클래스는 동작적으로 중첩된 최상위 클래스 에 대한 다른 최상위 클래스에서 포장 편의성.

당신은 그 단어를 사용하지 않았습니다 static 두 번째 경우에는.그리고 당신은 그것이 암묵적으로 그럴 것이라고 생각합니다. static 인터페이스이기 때문이죠.당신이 그렇게 가정하는 것이 옳습니다.

정적 중첩 클래스처럼 인터페이스에서 내부 클래스를 인스턴스화할 수 있습니다. static 중첩 클래스.

Levels.Items hello = new Levels.Items();

따라서 위의 진술은 다음과 같습니다. 두 경우 모두 유효합니다.첫 번째 경우는 정적 중첩 클래스이고 두 번째 경우에는 지정하지 않았습니다. static, 그러나 인터페이스에 있기 때문에 정적 중첩 클래스가 됩니다. 따라서 하나는 클래스에 중첩되고 다른 하나는 인터페이스에 중첩된다는 사실 외에는 차이가 없습니다..

일반적으로 클래스의 내부 클래스는 인터페이스에 없음, 아래와 같이 인스턴스화됩니다.

Levels levels = new Levels();
Levels.Items items = levels.new Items();

게다가 "비정적" 내부 클래스는 외부 클래스에 대한 암시적 참조를 갖습니다."정적" 중첩 클래스의 경우는 그렇지 않습니다.

인터페이스에서 중첩 클래스를 선언하면 항상 공공의 그리고 공전.그래서:

public interface Levels{
    class Items {
        public String value;
        public String path;

        public String getValue() {return value;}
    }
}

정확히 동일합니다

public interface Levels{
    public static class Items {
        public String value;
        public String path;

        public String getValue() {return value;}
    }
}

그리고 심지어

public interface Levels{
    static class Items {
        public String value;
        public String path;

        public String getValue() {return value;}
    }
}

나는 이것을 javap -verbose로 확인했고 모두 생성했습니다.

Compiled from "Levels.java"
public class Levels$Items extends java.lang.Object
  SourceFile: "Levels.java"
  InnerClass: 
   public #14= #3 of #23; //Items=class Levels$Items of class Levels
  minor version: 0
  major version: 50
  Constant pool:
const #1 = Method   #4.#21; //  java/lang/Object."<init>":()V
const #2 = Field    #3.#22; //  Levels$Items.value:Ljava/lang/String;
const #3 = class    #24;    //  Levels$Items
const #4 = class    #25;    //  java/lang/Object
const #5 = Asciz    value;
const #6 = Asciz    Ljava/lang/String;;
const #7 = Asciz    path;
const #8 = Asciz    <init>;
const #9 = Asciz    ()V;
const #10 = Asciz   Code;
const #11 = Asciz   LineNumberTable;
const #12 = Asciz   LocalVariableTable;
const #13 = Asciz   this;
const #14 = Asciz   Items;
const #15 = Asciz   InnerClasses;
const #16 = Asciz   LLevels$Items;;
const #17 = Asciz   getValue;
const #18 = Asciz   ()Ljava/lang/String;;
const #19 = Asciz   SourceFile;
const #20 = Asciz   Levels.java;
const #21 = NameAndType #8:#9;//  "<init>":()V
const #22 = NameAndType #5:#6;//  value:Ljava/lang/String;
const #23 = class   #26;    //  Levels
const #24 = Asciz   Levels$Items;
const #25 = Asciz   java/lang/Object;
const #26 = Asciz   Levels;

{
public java.lang.String value;

public java.lang.String path;

public Levels$Items();
  Code:
   Stack=1, Locals=1, Args_size=1
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return
  LineNumberTable: 
   line 2: 0

  LocalVariableTable: 
   Start  Length  Slot  Name   Signature
   0      5      0    this       LLevels$Items;


public java.lang.String getValue();
  Code:
   Stack=1, Locals=1, Args_size=1
   0:   aload_0
   1:   getfield    #2; //Field value:Ljava/lang/String;
   4:   areturn
  LineNumberTable: 
   line 7: 0

  LocalVariableTable: 
   Start  Length  Slot  Name   Signature
   0      5      0    this       LLevels$Items;


}

중첩/내부 클래스에 대한 예는 (IMO) 나쁜 예입니다.게다가 두 번째 예는 인터페이스가 (암시적으로) 추상 메소드만 선언할 수 있으므로 유효한 Java가 아닙니다.더 나은 예는 다음과 같습니다.

public interface Worker {

    public class Response {
        private final Status status;
        private final String message;
        public Response(Status status, String message) {
            this.status = status; this.message = message;
        }
        public Status getStatus() { return status; }
        public String getMessage() { return message; }
    }

    ...

    public Response doSomeOperation(...);
}

Response 클래스를 포함함으로써 우리는 이것이 다른 용도로 사용되지 않는 Worker API의 기본 부분임을 나타냅니다.

Map.Entry 클래스는 이 관용구의 잘 알려진 예입니다.

임호, 이점 사소한 경우 프로젝트 폴더를 어수선하게 만드는 클래스가 적다는 것입니다.그만큼 불리 요구사항 변화에 따라 내부 클래스가 성장할 때 유지관리 너의 악몽이 되어라.

나는 첫 번째 클래스가 Levels 클래스와 Items라는 정적 내부 클래스를 선언할 것이라고 생각했습니다.항목은 Levels.Items에 의해 참조될 수 있으며 정적입니다.

두 번째는 다음과 같이 Levels.Items를 사용하여 액세스할 수 있는 간단한 내부 클래스를 선언합니다.

Levels.Items hello = new Levels.Items();

편집하다:이것은 완전히 잘못된 내용입니다. 댓글과 다른 답변을 읽어보세요.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top