programing

Java의 스태틱네스트 클래스, 이유는?

javaba 2022. 8. 3. 22:59
반응형

Java의 스태틱네스트 클래스, 이유는?

LinkedList「」를 하고 있는 을 알 수 .Entry.

public class LinkedList<E> ... {
...

 private static class Entry<E> { ... }

}

일반 내부 클래스가 아닌 정적 중첩 클래스를 사용하는 이유는 무엇입니까?

유일하게 생각할 수 있는 이유는 엔트리에는 인스턴스 변수에 액세스할 수 없기 때문에 OOP 관점에서 캡슐화가 더 잘 되어 있기 때문입니다.

하지만 다른 이유가 있을지도 모른다고 생각했어요. 퍼포먼스.뭐가 있을까요?

주의. 용어를 맞췄으면 좋겠어요.정적인 이너 클래스라고 부르고 싶지만, 이것은 잘못된 것 같습니다.http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html

링크하는 Sun 페이지에는 다음 두 가지 주요 차이점이 있습니다.

네스트된 클래스는 둘러싸인 클래스의 멤버입니다.비정적 중첩 클래스(내부 클래스)는 프라이빗으로 선언된 경우에도 엔클로징 클래스의 다른 멤버에 액세스할 수 있습니다.스태틱 네스트클래스는 인클로징클래스의 다른 멤버에 액세스할 수 없습니다.

주의: 정적 중첩 클래스는 다른 최상위 클래스와 마찬가지로 외부 클래스(및 다른 클래스)의 인스턴스 멤버와 상호 작용합니다.실제로 스태틱네스트 클래스는 동작상으로는 패키징 편의를 위해 다른 최상위 클래스에 네스트된 최상위 클래스입니다.

는 없다LinkedList.Entry최상급이다LinkedList 클래스( 「」 「」 「」 「」라고 하는 이름의 스태틱네스트 .Entry 「」, 「」등입니다.Map.Entry(일부러)또한 Linked List 멤버에 접근할 필요가 없기 때문에 정적인 것은 당연합니다.이것은 훨씬 깔끔한 접근법입니다.

Jon Sket이 지적한 바와 같이, 네스트 클래스를 사용하는 경우에는 우선 정적인 클래스에서 시작하여 사용법에 따라 정적인 클래스가 필요한지 여부를 결정하는 것이 좋다고 생각합니다.

내 생각에, 질문은 당신이 내적 계층을 볼 때마다 그 반대여야 한다. - 그것은 정말로 내적 계층이어야 하며, 추가적인 복잡성과 포함 클래스의 예에 대한 암묵적 참조(명료하고 명확한 것이 아니라 IMO)가 있어야 하는가?

C# 팬으로서 편견이 있습니다.C#에는 네스트 타입이 있습니다만, 내부 클래스에는 대응하지 않습니다.아직 내부 수업에 빠졌다고는 말할 수 없습니다. :)

여기서 고려해야 할 명백한 메모리 보유 문제가 있습니다.비정적 내부 클래스는 해당 '외부' 클래스에 대한 암묵적인 참조를 유지하므로 내부 클래스의 인스턴스가 강하게 참조되면 외부 인스턴스도 강하게 참조됩니다.이로 인해 외부 클래스가 가비지 수집되지 않은 경우 참조하는 클래스가 없는 것처럼 보여도 헤드 스크래치가 발생할 수 있습니다.

스태틱 내부 클래스는 빌더 패턴에서 사용됩니다.정적 내부 클래스는 전용 생성자만 있는 외부 클래스를 인스턴스화할 수 있습니다.내부 클래스에 액세스하기 전에 외부 클래스의 개체를 만들어야 하므로 내부 클래스에 대해 동일한 작업을 수행할 수 없습니다.

class OuterClass {
    private OuterClass(int x) {
        System.out.println("x: " + x);
    }
    
    static class InnerClass {
        public static void test() {
            OuterClass outer = new OuterClass(1);
        }
    }
}

public class Test {
    public static void main(String[] args) {
        OuterClass.InnerClass.test();
        // OuterClass outer = new OuterClass(1); // It is not possible to create outer instance from outside.
    }
}

x:1 출력됩니다.

static nested 클래스는 외부 클래스 멤버에 액세스할 수 없기 때문에 다른 외부 클래스와 동일합니다.

패키징 편의성을 위해 정적 중첩 클래스를 읽기 쉽게 하나의 외부 클래스로 묶을 수 있습니다.이것 말고는 스태틱네스트 클래스의 다른 사용 예는 없습니다.

이러한 사용 방법의 예는 Android R.java(리소스) 파일에서 찾을 수 있습니다.Android의 Res 폴더에는 레이아웃(화면 디자인 포함), 그리기 가능 폴더(프로젝트에 사용되는 이미지 포함), 값 폴더(문자열 상수 포함) 등이 포함됩니다.

모든 폴더가 Res 폴더의 일부이므로, Android 도구는 각 내부 폴더에 대해 내부적으로 많은 정적 중첩 클래스가 포함된 R.java(리소스) 파일을 생성합니다.

다음은 Android에서 생성된 R.java 파일의 모양과 느낌입니다.여기에서는 포장의 편리성만을 목적으로 하고 있습니다.

/* AUTO-GENERATED FILE.  DO NOT MODIFY.
 *
 * This class was automatically generated by the
 * aapt tool from the resource data it found.  It
 * should not be modified by hand.
 */

package com.techpalle.b17_testthird;

public final class R {
    public static final class drawable {
        public static final int ic_launcher=0x7f020000;
    }
    public static final class layout {
        public static final int activity_main=0x7f030000;
    }
    public static final class menu {
        public static final int main=0x7f070000;
    }
    public static final class string {
        public static final int action_settings=0x7f050001;
        public static final int app_name=0x7f050000;
        public static final int hello_world=0x7f050002;
    }
}

우선, 비정적 내부 클래스에는 외부 클래스의 인스턴스를 가리키는 추가 숨겨진 필드가 있습니다.따라서 Entry 클래스가 정적이지 않은 경우 필요하지 않은 액세스 권한이 있는 것 외에 3개의 포인터가 아닌 4개의 포인터를 가지고 다닐 수 있습니다.

원칙적으로 데이터 멤버의 집합으로서 기능하는 클래스를 정의하는 경우는, 예를 들면 C의 「구조」와 같이, 정적인 것을 고려해 주세요.

http://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html 에서 :

둘러싸인 인스턴스의 비공용 필드 및 메서드에 대한 액세스가 필요한 경우 비정적 중첩 클래스(또는 내부 클래스)를 사용하십시오.이 액세스가 필요하지 않은 경우 정적 중첩 클래스를 사용하십시오.

간단한 예:

package test;

public class UpperClass {
public static class StaticInnerClass {}

public class InnerClass {}

public static void main(String[] args) {
    // works
    StaticInnerClass stat = new StaticInnerClass();
    // doesn't compile
    InnerClass inner = new InnerClass();
}
}

non-static인 경우 상위 클래스의 인스턴스에서 클래스를 인스턴스화할 수 없습니다(따라서 main이 정적 함수인 예에서는 제외).

스태틱과 노멀의 이유 중 하나는 클래스 로드와 관련이 있습니다.상위 클래스의 생성자에서 내부 클래스를 인스턴스화할 수 없습니다.

PS: 저는 항상 '내적'과 '내적'은 서로 교환할 수 있다는 것을 알고 있습니다.용어에는 미묘한 뉘앙스가 있을 수 있지만 대부분의 자바 개발자들은 둘 다 이해할 것이다.

정적 내부 클래스가 아닌 경우 메모리 누수가 발생할 수 있으며 정적 내부 클래스는 메모리 누수를 방지합니다.외부 클래스가 대량의 데이터를 보유하고 있으면 응용 프로그램의 성능을 저하시킬 수 있습니다.

  1. JVM이 중첩된 클래스를 알지 못합니다.둥지는 단지 통사적인 설탕일 뿐이다.

    아래 이미지는 Java 파일을 보여줍니다.

    여기에 이미지 설명 입력

    다음 이미지는 Java 파일의 클래스 파일을 나타내고 있습니다.

    여기에 이미지 설명 입력

    2개의 클래스 파일이 생성됩니다.하나는 부모용이고 다른 하나는 중첩된 클래스용입니다.

  2. Non-static nested class' 개체는 둘러싸인 범위에 액세스할 수 있습니다.엔클로저 스코프에 대한 액세스는 엔클로저 스코프 객체에 대한 암묵적인 참조를 네스트된 객체에 보유함으로써 유지됩니다.

  3. 중첩 클래스는 중첩된 클래스 유형이 상위 클래스의 구성 요소를 나타내는 의도를 나타내는 방법입니다.

    public class Message {
    
    private MessageType messageType; // component of parent class
    
    public enum MessageType {
        SENT, RECEIVE;
    }
    }
    
    
    
    class Otherclass {
    
    public boolean isSent(Message message) {
        if (message.getMessageType() == MessageType.SENT) { // accessible at other places as well
            return true;
        }
        return false;
    }
    }
    
  4. private static nested class는 Point #3을 나타냅니다.네스트된 유형은 부모 클래스의 서브컴포넌트일 수 있습니다.따로 사용할 수 없습니다.

    public class Message {
    
     private Content content; // Component of message class
    
     private static class Content { // can only be a component of message class
    
      private String body;
      private int sentBy;
    
      public String getBody() {
         return body;
      }
    
      public int getSentBy() {
         return sentBy;
      }
    
    }
    }
    
    class Message2 {
      private Message.Content content; // Not possible
    }
    
  5. 자세한 것은 이쪽.

성능 차이는 모르겠지만 말씀하신 것처럼 스태틱네스트 클래스는 엔클로징 클래스의 인스턴스가 아닙니다.내부 클래스가 필요하지 않는 한 정적 중첩 클래스를 만드는 것이 더 쉬워 보입니다.

제가 항상 Java에서 최종 변수를 만드는 것과 비슷합니다. 최종 변수가 아니라면, 뭔가 재미있는 일이 벌어지고 있다는 것을 알고 있습니다.스태틱 네스트클래스 대신 inner 클래스를 사용하는 경우 충분한 이유가 있습니다.

스태틱 클래스가 아닌 스태틱네스트 클래스를 사용하면 공간을 절약할 수 있습니다.를 들어, 「」의 : 「」Comparator수업 중에, 학생이라고 합니다.

public class Student {
  public static final Comparator<Student> BY_NAME = new ByName();
  private final String name;
  ...
  private static class ByName implements Comparator<Student> {
    public int compare() {...}
  }
}

'하다'는staticStudent 클래스는 새 학생 인스턴스를 만들 때마다 새 비교기를 인스턴스화하는 대신 하나의 비교기만 가집니다.

내적 계급의 격언...

  1. 일회용
  2. 캡슐화를 지원 및 개선합니다.
  3. 가독성
  4. 개인 필드 액세스

외부 클래스의 내부 클래스가 존재하지 않으면 존재하지 않습니다.

class car{
    class wheel{

    }
}

이너 클래스에는 네 가지 유형이 있습니다.

  1. 정상 내부 계급
  2. 메서드 로컬 내부 클래스
  3. 익명 내부 클래스
  4. 정적 내부 클래스

포인트 ---

  1. static inner 클래스에서는 outer 클래스의 static 멤버에만 접근할 수 있습니다.
  2. 내부 클래스에서는 static member를 선언할 수 없습니다.
  3. 외부 클래스의 정적 영역에서 일반 내부 클래스를 호출하기 위해.

    Outer 0=new Outer(); Outer.Inner i= O.new Inner();

  4. 외부 클래스의 인스턴스 영역에서 일반 내부 클래스를 호출하기 위해 사용합니다.

    Inner i=new Inner();

  5. 외부 클래스 외부에서 일반 내부 클래스를 호출하기 위해.

    Outer 0=new Outer(); Outer.Inner i= O.new Inner();

  6. inside inner class 내부 클래스에 대한 포인터입니다.

    this.member-current inner class outerclassname.this--outer class

  7. inner 클래스의 적용 가능한 수식자는 --public, default,

    final,abstract,strictfp,+private,protected,static

  8. outer$class는 내부 클래스 이름입니다.

  9. inner class inside instance 메서드에서는 outer class의 static 및 instance 필드에 액세스할 수 있습니다.

10. static 메서드 내의 static class에 액세스 할 수 있는 것은, 다음의 static 필드뿐입니다.

외부 클래스

class outer{

    int x=10;
    static int y-20;

    public void m1() {
        int i=30;
        final j=40;

        class inner{

            public void m2() {
                // have accees x,y and j
            }
        }
    }
}

언급URL : https://stackoverflow.com/questions/253492/static-nested-class-in-java-why

반응형