Java에서 클래스를 정적 ​​클래스로 선언 할 수없는 이유는 무엇입니까?


459

Java에서 클래스를 정적 ​​클래스로 선언 할 수없는 이유는 무엇입니까?


72
반대 질문 : 최상위 클래스를 다음과 같이 선언하면 어떤 효과가있을 것으로 예상 static됩니까?
Joachim Sauer

3
정적 내부 클래스를 제외하고는 할 수 없습니다. 그러나 그로 무엇을 달성하고 싶습니까?
manolowar

60
@Joachim Sauer : C #은 static클래스를로 해석 합니다 abstract final. 즉, 인스턴스화 할 수없고 확장 할 수 없습니다. 이는 정적 멤버 만 포함 할 수 있음을 의미하며 이는 도우미 메소드 만 포함하는 클래스에 유용합니다.
bcat

30
@bcat 이것은 C #에 해당하지만 Java 클래스는 추상적이거나 최종적 일 수 있습니다. 클래스가 인스턴스화되는 것을 방지하기 위해 개인 생성자를 선언 할 수 있습니다.
Lorenzo Polidori

7
@JoachimSauer 간단하게 클래스의 모든 멤버를 정적으로 만들고 싶습니다 (각 메서드 또는 속성에 대해 선언해야 할 수도 있음).
15:52에

답변:


475

중첩 클래스 만 정적 일 수 있습니다. 이렇게하면 외부 클래스의 인스턴스가 없어도 중첩 클래스를 사용할 수 있습니다.

class OuterClass{
    public static class StaticNestedClass{
    }

    public class InnerClass{
    }

    public InnerClass getAnInnerClass(){
        return new InnerClass();
    }

    //This method doesn't work
    public static InnerClass getAnInnerClassStatically(){
        return new InnerClass();
    }
}

class OtherClass{
    //Use of a static nested class:
    private OuterClass.StaticNestedClass staticNestedClass = new OuterClass.StaticNestedClass();

    //Doesn't work
    private OuterClass.InnerClass innerClass = new OuterClass.InnerClass();

    //Use of an inner class:
    private OuterClass outerclass= new OuterClass();
    private OuterClass.InnerClass innerClass2 = outerclass.getAnInnerClass();
    private OuterClass.InnerClass innerClass3 = outerclass.new InnerClass();
}

출처 :

같은 주제에서 :


3
첫 번째 문구가 정확하지는 않지만 +1입니다. 튜토리얼에서 "정적이 아닌 중첩 클래스를 내부 클래스"라고합니다. (JLS : "내부 클래스는 명시 적으로 또는 암시 적으로 정적으로 선언되지 않은 중첩 클래스입니다."
user85421

74
당신이 가장 옳습니다. 그러나 이것이 어떻게 질문에 대답하는지 모르겠습니다
Joeri Hendrickx

2
@Carlos Heuberger, 당신 말이 맞아요, 게시물을 업데이트했습니다. @Joeri Hendrickx, 문제는 "클래스를 정적 ​​..으로 선언 할 수없는 이유는 무엇입니까?"라는 질문입니다. 정적 클래스 사용법과 중첩 클래스 여야하는 이유에 대한 설명입니다.
콜린 헤 버트

1
여기에 주어진 해결책은 괜찮습니다 ...하지만 여전히 y ppl이 정적 클래스가 java .. 일부 OOPs 개념 설명이 정답이 아니라고 논리적으로 설명하지 않았다는 것을 궁금합니다. 기다리고 있습니다
Punith Raj

9
사실이지만, 당신이 생각하는 질문은 보통 "정적 클래스"가 무엇인지 스스로에게 물어볼 때 스스로 해결됩니다. Java에서 정적 요소는 포함하는 클래스의 인스턴스없이 액세스하거나 호출 할 수 있음을 의미합니다. 클래스 자체에 키워드를 적용하면 무슨 의미일까요? 당신의 의도는 무엇입니까? 무엇을 기대하십니까? 이제 당신은 그것이 무엇인지에 대한 아이디어를 얻었으므로, 그것이 "실제로 이해가되지 않을 것"이거나 "원격으로 가져올 것"이라고 확신합니다. 만들어졌다).
Colin Hebert

39

최상위 클래스는 기본적으로 정적입니다. 내부 클래스는 기본적으로 정적이지 않습니다. 내부 클래스를 정적으로 명시 적으로 표시하여 내부 클래스의 기본값을 변경할 수 있습니다. 최상위 수준이기 때문에 최상위 클래스는 참조 할 부모 클래스가 없기 때문에 정적이 아닌 의미를 가질 수 없습니다. 따라서 최상위 클래스의 기본값을 변경할 방법이 없습니다.


14
»최상위 레벨 클래스는 기본적으로 정적입니다.«이것이 가장 좋은 답변입니다. 그것들을 참조하기 위해 어떤 인스턴스도 필요하지 않기 때문에 정적입니다. 어디에서나 참조 할 수 있습니다. 그들은에있어 정적 스토리지 (C 스토리지 클래스에서와 같이). -다른 사람들이 지적했듯이 (다른 답변에 대한 의견에서 Iain Elder) 언어 디자이너는 static최상위 클래스 의 키워드가 정적 멤버 만 포함하고 인스턴스화되지 않을 수 있음을 표시하고 시행하도록 허용 할 수 있습니다. 그러나 static중첩 클래스에 대해 다른 의미를 갖는 것처럼 사람들을 혼란스럽게 만들 수 있습니다.
Lumi

35

그래서, 나는 파티에 늦게오고 있지만, 여기에는 철학적으로 콜린 헤 버트의 대답에 추가하는 2 센트가 있습니다.

높은 수준에서 질문은 객체와 유형의 차이를 처리합니다. 많은 자동차 (객체)가 있지만 Car 클래스 (유형)는 하나뿐입니다. 무언가를 정적으로 선언한다는 것은 "타입"공간에서 작업하고 있다는 것을 의미합니다. 하나만 있습니다. 최상위 클래스 키워드는 이미 "type"공간에서 유형을 정의합니다. 결과적으로 "공용 정적 클래스 Car"는 중복됩니다.


1
예. 달리 말하면 최상위 클래스는 기본적으로 정적이므로 키워드가 필요하지 않습니다.
Warren Dew

1
글쎄, 나는 워렌 듀가 말한 것에 덧붙였다. "정적 멤버에 접근 할 때 기본적으로 최상위 클래스는 정적이다".
Dexter

1
과소 평가. 새로운 키워드는 클래스의 모든 메소드를 정적으로 만들고 생성자 private을 사용하는 것이 좋습니다. 혼란 스럽기 때문에 정적으로 이름을 지정하지는 않습니다.
G_V

@G_V 자바는 그러한 괴물을 만들 수 있지만, 자바는 어리석은 일을 어렵게 만드는 방법을 거의 사용하지 않습니다. 정적은 일반적으로 나쁜 생각이며 정적 클래스는 끔찍합니다 (자체는 반 패턴으로 간주되는 싱글 톤보다 끔찍합니다). 많은 사람들이 이것을 이해하지 못하므로 키워드를 제공하는 것은 매우 나쁜 생각입니다. 대신 우리는 나쁜 일을 어렵게 만들고 그것을 그대로 두십시오. "Singleton"키워드도 없습니다. 속성 키워드가 없습니다. 이것들은 모두 잘못된 코드를 야기합니다 (사람들은 여전히 ​​자바를 지원할만큼 속성을 많이 사용하지만)
Bill K

29

개인 생성자가있는 클래스는 정적입니다.

다음과 같이 수업을 선언하십시오.

public class eOAuth {

    private eOAuth(){}

    public final static int    ECodeOauthInvalidGrant = 0x1;
    public final static int    ECodeOauthUnknown       = 0x10;
    public static GetSomeStuff(){}

}

초기화하지 않고 사용할 수 있습니다.

if (value == eOAuth.ECodeOauthInvalidGrant)
    eOAuth.GetSomeStuff();
...

3
정적이 아니지만 정적 속성을 포함합니다. public final int를 쓰면 ECodeOauthUnknown = 0x10; 더 이상 정적이 아닙니다.
user1883212

9
누군가 여기서 무슨 일이 일어나고 있는지 궁금해하는 경우 이것은 "정적 클래스"( msdn.microsoft.com/en-us/library/79b3xss3%28v=vs.90%29.aspx) 의 C # 정의와 일치합니다 . "정적 클래스"의 Java 정의가 주어지면, 내부가 아닌 모든 클래스는 정적입니다 (형제 답변 참조).
Calum

1
@ user1883212 외에도 옳은 말이지 만,이 답변은 독자가 개인 생성자가 여기에서 어떻게 든 중요하지만 실제로는 중요하지 않다는 것을 혼동한다고 말합니다.
tlwhitec

.NET 세계에서 클래스가 abstract와 final로 표시되면 ( static classC #에서 선언 의 영향 ) 컴파일러는 코드가 해당 유형의 변수를 선언하거나 일반 유형 매개 변수로 사용하도록 허용하지 않습니다. 인스턴스화되거나 상속 될 수있는 클래스에 액세스 가능한 생성자가 부족한 경우 해당 유형의 변수 선언이나 일반 유형 매개 변수로의 사용을 배제하지 않습니다.
supercat

이 답변은 완전히 틀 렸습니다. 개인 생성자는 그것과 아무 관련이 없습니다. 이 코드는 정적 속성과 메서드 만있는 클래스의 예일뿐입니다. 정적 클래스와는 아무런 관련이 없습니다.
Lorne의 후작

13

물론 내부 중첩 클래스 만 가능 합니다. 즉, 중첩 클래스의 인스턴스에는 외부 클래스의 엔 클로징 인스턴스가 필요하지 않습니다.

그러나 최상위 클래스의 경우 언어 디자이너는 키워드와 관련하여 유용한 것을 생각할 수 없으므로 허용되지 않습니다.


첫 번째 문구가 정확하지는 않지만 +1입니다. JLS가 말한 것처럼 : "내부 클래스는 명시 적으로 또는 암시 적으로 정적으로 선언되지 않은 중첩 클래스입니다." (단지 용어, 알고 있습니다 ...)
user85421

7
최상위 클래스를 선언 할 수는 없지만 static때로는 가능할 수도 있습니다. 예를 들어, 정적 헬퍼 메소드 만 포함하는 클래스는 인스턴스화하는 것이 의미가 없지만 Java 언어는이를 수행하지 못하게합니다. 기본 생성자를 선언하여 클래스를 인스턴스화 할 수없고 (실제로는 '정적') private만들 수 있습니다. 생성자가 보이지 않기 때문에 인스턴스화가 금지됩니다.
Iain Samuel McLean Elder

12

인스턴스없이 열거 형을 선언하여 인스턴스를 작성할 수없는 유틸리티 클래스를 작성할 수 있습니다. 즉, 인스턴스가 없다고 구체적으로 선언하고 있습니다.

public enum MyUtilities {;
   public static void myMethod();
}

25
유형으로서의 열거는 특정한 기대입니다. 열거 된 항목 세트입니다. "유틸리티 클래스"에이를 사용하면 개인 생성자가있는 클래스를 가질 수있을 때 의미 상 혼동됩니다.
비전 소프트웨어 솔루션

5
@VisionarySoftwareSolutions 나 에게이 특이성은이 클래스의 인스턴스를 간접적으로 만드는 것이 아니라 클래스의 인스턴스를 간접적으로 만드는 것이 아니라고 말합니다.
피터 로리

8
public class Outer {
   public static class Inner {}
}

... 멤버 클래스 인 한 정적로 선언 할 수 있습니다.

JLS에서 :

멤버 클래스는 정적 일 수 있으며이 경우 주변 클래스의 인스턴스 변수에 액세스 할 수 없습니다. 또는 내부 클래스 일 수 있습니다 (§8.1.3).

그리고 여기:

static 키워드는 내부 클래스가 아닌 클래스 T 본문 내에서 멤버 유형 C의 선언을 수정할 수 있습니다. 그 효과는 C가 내부 클래스가 아니라고 선언하는 것입니다. T의 정적 메소드에 본문에 현재 T의 인스턴스가없는 것처럼 C에도 현재 T의 인스턴스가 없으며 어휘 적으로 둘러싸인 인스턴스도 없습니다.

정적 키워드는 최상위 클래스에 엔 클로징 유형이 없기 때문에 최상위 클래스에는 의미가 없습니다.


내부가 아닌 경우 왜 전화 Inner합니까? Nested덜 혼란스러운 선택이었을 것입니다.
Lorne의 후작

5

위에서 설명한 것처럼 클래스는 다른 클래스의 멤버가 아닌 한 정적 일 수 없습니다.

"여러 인스턴스가있을 수없는"클래스를 디자인하려는 경우 "Singleton"디자인 패턴을 살펴볼 수 있습니다.

초보자 싱글 톤 정보는 여기 .

경고:

싱글 톤 패턴을 사용할 생각이라면 모든 힘을 다해 저항하십시오. 이해하기 가장 쉬운 DesignPatterns 중 하나이며, 아마도 가장 인기 있고, 가장 많이 남용되었을 것입니다. (출처 : 위에 링크 된 JavaRanch)


4

Java가 정적 내부 클래스를 정의하는 방법 외에도 C # 세계에 따라 다른 정적 클래스 정의가 있습니다 [1] . 정적 클래스는 정적 메서드 (함수) 만 가지고 있으며 절차 적 프로그래밍을 지원하기위한 클래스입니다. 이러한 클래스는 클래스의 사용자가 클래스의 인스턴스를 작성하는 것이 아니라 도우미 함수에만 관심이 있다는 점에서 실제로 클래스가 아닙니다. 정적 클래스는 C #에서 지원되지만 Java에는 이러한 직접 지원이 없습니다. 그러나 enum을 사용하여 Java에서 C # 정적 클래스를 모방하여 사용자가 주어진 클래스의 인스턴스를 만들 수 없도록 할 수 있습니다 (반사를 사용하여도) [2] :

public enum StaticClass2 {
    // Empty enum trick to avoid instance creation
    ; // this semi-colon is important

    public static boolean isEmpty(final String s) {
        return s == null || s.isEmpty();
    }
}

3

우리가 자바로 코딩하는 모든 것은 클래스로 들어갑니다. 우리가 클래스 JVM을 실행할 때마다 객체를 인스턴스화합니다. JVM은 여러 객체를 생성 할 수 있습니다. 정의에 따르면 정적이란 모든 객체에 대해 동일한 사본 세트가 있음을 의미합니다.

따라서 Java가 프로그램을 실행할 때마다 최상위 클래스가 정적임을 허용하면 Object를 작성하고 동일한 메모리 위치를 계속 재정의합니다.

매번 실행할 때마다 객체를 바꾸는 경우 객체를 만드는 시점은 무엇입니까?

그래서 Java가 최상위 클래스에 대한 정적을 제거 한 이유입니다.

더 구체적인 이유가있을 수 있지만 이것은 나에게 많은 논리적 의미가 있습니다.


3
내부 클래스는 외부 클래스와 연결되어 있으므로 다른 객체를 사용할 수 있기 때문에 정적 일 수 있습니다.
user2626445

1
당신은 '그것들 이 정적으로 할 수 없는 이유입니다'를 의미 합니다.
Lorne의 후작

2

정적 일 수있는 유일한 클래스는 내부 클래스입니다. 다음 코드는 정상적으로 작동합니다.

public class whatever {
    static class innerclass {
    }
}

정적 내부 클래스의 요점은 외부 클래스 객체에 대한 참조가 없다는 것입니다.


1
'정적 내부'는 용어의 모순입니다. '정적'과 '내부'는 상호 배타적입니다. 찾고있는 단어는 '내부'가 아니라 '중첩'입니다.
Lorne의 후작

1

나는 커피 한 잔을 마시는 것만 큼 쉽다고 생각합니다!. 이것 좀 봐 클래스를 정의하는 동안 정적 키워드를 명시 적으로 사용하지 않습니다.

public class StaticClass {

    static private int me = 3;
    public static void printHelloWorld() {
       System.out.println("Hello World");
    }



    public static void main(String[] args) {
        StaticClass.printHelloWorld();
        System.out.println(StaticClass.me);
    }
}

정적 클래스의 정의가 아닙니까? 우리는 단지 클래스에 바인딩 된 함수를 사용합니다. 이 경우 중첩 된 다른 클래스를 사용할 수 있습니다. 이것 좀봐:

class StaticClass1 {

    public static int yum = 4;

    static void  printHowAreYou() {
        System.out.println("How are you?");
    }
}

public class StaticClass {

    static int me = 3; 
    public static void printHelloWorld() {
       System.out.println("Hello World");
       StaticClass1.printHowAreYou();
       System.out.println(StaticClass1.yum);
    }



    public static void main(String[] args) {
        StaticClass.printHelloWorld();
        System.out.println(StaticClass.me);
    }
}

정적 키워드를 한정자로 사용하는 것이 아니라 정적 클래스 정의를 참조하여 정적 클래스와 같은 클래스를 고려할 수 있다고 생각합니다.
Erfankam

개인 생성자를 작성하십시오. 그렇지 않으면 말할 수 있고 new StaticClass()실제로는 의미가 없습니다. 개인 생성자를 사용하면 인스턴스를 허용하지 않습니다.
grinch

1

PlatformUI정적 메소드와 개인 생성자가 최종 클래스 인 클래스를 Eclipse 에서 살펴볼 수 있습니다 .

public final class <class name>
{
   //static constants
   //static memebers
}

0

정적 클래스 사용의 이점이 객체를 인스턴스화하지 않고 메소드를 사용하는 것이 아니라면 클래스를 public으로 선언 하고이 메소드를 정적으로 선언하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.