Javaでクラスを静的として宣言できないのはなぜですか?


459

Javaでクラスを静的として宣言できないのはなぜですか?


72
反問:トップレベルのクラスを宣言した場合、どのような効果が期待できstaticますか?
Joachim Sauer

3
いいえ、できません。静的内部クラスを除きます。しかし、それで何を達成したいですか?
manolowar 2010

60
@Joachim Sauer:まあ、C#はstaticクラスをとして解釈しますabstract final。つまり、クラスをインスタンス化したり拡張したりすることはできません。つまり、静的メンバーのみを含めることができます。これは、ヘルパーメソッドのみを含むクラスに役立ちます。
bcat

30
@bcatこれはC#に当てはまりますが、Javaクラスは抽象クラスまたは最終クラスのいずれかであり、両方ではありません。クラスがインスタンス化されないようにするには、プライベートコンストラクターを宣言します。
ロレンツォポリドリ

7
@JoachimSauer単純です。クラスのすべてのメンバーを静的に強制したいと思います(たぶん、各メソッドまたはプロパティで宣言する必要があります)。
hmartinezd 2014年

回答:


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 2010

2
@Carlos Heubergerさん、そうです、私は投稿を更新しました。@Joeri Hendrickx、質問は、「なぜクラスをstaticとして宣言できないのか?」という質問でした。そして、[ここに私の投稿を読んでください]。これは、静的クラスの使用法と、それらがネストされたクラスでなければならない理由についての説明です。
Colin Hebert、2010

1
ここで与えられた解決策は素晴らしいです...しかし、静的クラスがjava..OOPsの概念の説明では不可能であることを論理的に説明していないのではないかと思います。私はそれを待っています
プニス・ラージ

9
それは事実ですが、「静的クラス」が何であるかを自問し始めると、通常、考えている質問はそれ自体で解決します。Javaでは、静的要素は、それを含むクラスのインスタンスがなくてもアクセス/呼び出しできることを意味します。クラス自体にキーワードを適用するとどうなるでしょうか。あなたの意図は何ですか?何を期待しますか?あなたはそれが何であるかについての考えを持っているので、私はそれが「実際には意味をなさない」か、または「はるかにフェッチされた」(それは理にかなっているでしょうが、結局それは単なる選択肢です)それが行われました)。
Colin Hebert、2012年

39

トップレベルのクラスはデフォルトで静的です。内部クラスはデフォルトでは静的ではありません。明示的に静的とマークすることで、内部クラスのデフォルトを変更できます。トップレベルであるため、参照する親クラスがないため、トップレベルのクラスは非静的セマンティクスを持つことができません。したがって、最上位クラスのデフォルトを変更する方法はありません。


14
»トップレベルのクラスはデフォルトで静的です。«これが最良の答えです。それらを参照するために何かのインスタンスを必要としないため、これらは静的です。どこからでも参照できます。それらは(Cストレージクラスのように)静的ストレージにあります。-他の人が指摘したように(Iain Elderが別の回答へのコメントで)、言語設計者はstatic、最上位クラスのキーワードが静的メンバーのみを含み、インスタンス化されないことを示し、強制することを許可することができます。ただし、staticネストされたクラスには別の意味があるため、混乱する可能性があります。
ルミ

35

それで、私はパーティーに遅れて来ています、しかしここに私の2セントがあります-哲学的にコリン・ハーバートの答えに追加します。

高レベルでは、質問はオブジェクトとタイプの違いを扱います。車(オブジェクト)は多数ありますが、車クラス(タイプ)は1つだけです。静的として宣言することは、「タイプ」スペースで操作していることを意味します。1つだけです。最上位のclassキーワードは、「タイプ」スペースでタイプをすでに定義しています。その結果、「public static class Car」は冗長になります。


1
はい。言い換えると、最上位クラスはデフォルトで静的であるため、キーワードは必要ありません。
Warren Dew

1
まあ、私はウォーレンデューが言ったことに「静的メンバーにアクセスするとき、トップレベルのクラスはデフォルトで静的です」と付け加えます。
デクスター

1
過小評価された答え。クラス内のすべてのメソッドを静的にし、コンストラクターをプライベートにする新しいキーワードがいいでしょう。混乱を招くだけなので、静的な名前は付けません。
G_V

@G_V Javaはそのような怪物を作成する可能性がありますが、Javaはほとんど愚かなことを困難にする方法から抜け出します。静的は一般的に悪い考えです。静的クラスは恐ろしいです(それ自体がアンチパターンと見なされるシングルトンよりも悪い)。多くの人々はこれを理解していないので、それにキーワードを与えることは非常に悪い考えでしょう。代わりに、悪いことを難しくして、そのままにしておきます。「シングルトン」キーワードもないことに注意してください。プロパティキーワードはありません。これらはすべて悪いコードを引き起こします(Javaがプロパティをサポートするほど多くの人がプロパティをまだ使用していますが)
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 2013年

9
ここで何が起こっているのか疑問に思っている場合、これは「静的クラス」のC#定義-msdn.microsoft.com/en-us/library/79b3xss3%28v=vs.90%29.aspxと一致します。Javaの「静的クラス」の定義を前提として、すべての非内部クラスは静的です(兄弟の回答を参照)。
Calum 2013

1
@ user1883212が正しいことは別として、私はこの答えは、プライベートコンストラクターがここではなんらか重要であると読者に混乱させるとさえ言いますが、実際にはまったく問題ではありません。
tlwhitec 2013

.NETの世界では、クラスが抽象と最終の両方(static classC#での宣言の効果)とマークされている場合、コンパイラーはコードでその型の変数を宣言することも、ジェネリック型パラメーターとして使用することもできません。クラスにアクセス可能なコンストラクターが欠けているだけで、インスタンス化または継承される可能性がある場合、その型の変数の宣言も、ジェネリック型パラメーターとしての使用も除外されません。
スーパーキャット2014年

この答えは完全に間違っています。プライベートコンストラクタはそれとは何の関係もありません。このコードは、静的な属性とメソッドのみを含むクラスの例にすぎません。静的クラスとは何の関係もありません。
ローンの侯爵

13

もちろん可能ですが、ネストされた内部クラスのみです。そこでは、ネストされたクラスのインスタンスは、外側のクラスの囲んでいるインスタンスを必要としないことを意味します。

しかし、トップレベルのクラスの場合、言語設計者はキーワードを使用して役立つことを何も考えられなかったため、許可されていません。


最初のフレーズが正確ではないにもかかわらず+1。JLSが述べているように、「内部クラスは、明示的または暗黙的に静的に宣言されていないネストされたクラスです。」(ただの用語、私は知っています...)
user85421 2010

7
トップレベルのクラスを宣言することはできませんがstatic、できるようにすると意味がある場合があります。たとえば、静的ヘルパーメソッドのみを含むクラスは、インスタンス化しても意味がありませんが、Java言語はインスタンス化を妨げません。デフォルトのコンストラクターを宣言することにより、クラスを他のクラスに対してインスタンス化不可能(および実質的に「静的」)にprivateすることができます。これにより、コンストラクターが表示されないため、インスタンス化が禁止されます。
Iain Samuel McLean Elder

12

インスタンスのない列挙型を宣言することで、ユーティリティクラス(インスタンスを作成できない)を作成できます。つまり、インスタンスがないことを具体的に宣言しています。

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

25
タイプとしての列挙は、特定の期待です。列挙されたアイテムのセットです。「ユーティリティクラス」にそれを使用すると、プライベートコンストラクターを持つクラスを作成するだけで、意味的に混乱します。
ビジョナリーソフトウェアソリューション

5
@VisionarySoftwareSolutions私にとって、この特定性は、クラスのインスタンスを作成することを間接的に不可能にするのではなく、このクラスのインスタンスがないことを示しています。
Peter Lawrey 2013年

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

...メンバークラスである限り、静的と宣言できます。

JLSから:

メンバークラスは静的である場合があり、その場合、周囲のクラスのインスタンス変数にアクセスできません。または、それらは内部クラスである場合があります(§8.1.3)。

そしてここ:

staticキーワードは、非内部クラスTの本体内のメンバー型Cの宣言を変更する場合があります。その効果は、Cが内部クラスではないことを宣言することです。Tの静的メソッドの本体にTの現在のインスタンスがないのと同じように、CにもTの現在のインスタンスがなく、字句的に囲んでいるインスタンスもありません。

静的キーワードは、トップレベルのクラスに囲み型がないため、トップレベルのクラスには意味がありません。


それがインナーでない場合は、なぜそれを呼び出すのInnerですか?Nested混乱の少ない選択だったでしょう。
ローンの侯爵

5

上記で説明したように、クラスは別のクラスのメンバーでない限り、静的であってはなりません。

「複数のインスタンスが存在できない」クラスを設計する場合は、「シングルトン」の設計パターンを調べることをお勧めします。

初心者シングルトン情報はこちら

警告:

シングルトンパターンの使用を検討している場合は、全力で抵抗してください。これは、理解するのが最も簡単なDesignPatternsの1つであり、おそらく最も人気があり、間違いなく最も乱用されています。 (ソース:上記のリンクのJavaRanch)


4

Javaが静的内部クラスを定義する方法に加えて、C#の世界ごとに静的クラスの別の定義があります[1]。静的クラスは、静的メソッド(関数)のみを含むクラスであり、手続き型プログラミングをサポートするためのものです。このようなクラスは、クラスのユーザーがヘルパー関数にのみ関心があり、クラスのインスタンスの作成には関心がないという点で、実際にはクラスではありません。静的クラスはC#でサポートされていますが、Javaではそのような直接的なサポートはありません。ただし、列挙型を使用して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

Javaでコーディングしたものはすべてクラスに入ります。クラスJVMを実行するたびに、オブジェクトがインスタンス化されます。JVMは、多くのオブジェクトを作成できます。定義上、静的とは、すべてのオブジェクトに同じコピーのセットがあることを意味します。

そのため、プログラムを実行するたびにJavaがトップクラスを静的にできるようにした場合、オブジェクトが作成され、同じメモリロケーションに上書きされ続けます。

実行するたびにオブジェクトを置き換えるだけの場合、作成のポイントは何ですか?

そのため、Javaがトップレベルクラスのstaticを削除したのはそのためです。

より具体的な理由があるかもしれませんが、これは私にとって非常に理にかなっています。


3
依存する別のオブジェクトがあるため、内部クラスは外部クラスに関連付けられており、それが静的である理由です。
user2626445 2013

1
あなたは「それが彼らが静的ではありえない理由」を意味します。
ローンの侯爵

2

静的にできる唯一のクラスは内部クラスです。次のコードは問題なく動作します。

public class whatever {
    static class innerclass {
    }
}

静的内部クラスの要点は、外部クラスオブジェクトへの参照がないことです。


1
「静的インナー」は用語で矛盾しています。「静的」と「内部」は相互に排他的です。あなたが探している言葉は「入れ子」であり、「内側」ではありません。
ローンの侯爵

1

これは一杯のコーヒーを飲むのと同じくらい簡単だと思います!。これを見てください。クラスを定義するときに、staticキーワードを明示的に使用しません。

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);
    }
}

staticキーワードを修飾子として使用するだけでなく、静的クラス定義を参照することで、そのようなクラスを静的クラスと見なすことができると思います。
Erfankam

必ずプライベートコンストラクターを作成してくださいnew StaticClass()。そうしないと言うことができますが、これはあまり意味がありません。プライベートコンストラクターでは、そのインスタンスは許可されません。
グリンチ

1

PlatformUIEclipseで静的メソッドとプライベートコンストラクターを含むクラスを調べ、それ自体が最終的なものにすることができます。

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

0

静的クラスを使用する利点がオブジェクトのインスタンス化とメソッドの使用ではなかった場合は、クラスをpublicとして宣言し、このメソッドをstaticとして宣言します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.