web-dev-qa-db-ja.com

クラスで 'static'キーワードは何をするのですか?

具体的には、私はこのコードを試していました:

package hello;

public class Hello {

    Clock clock = new Clock();

    public static void main(String args[]) {
        clock.sayTime();
    }
}

しかし、それはエラーを与えました

Staticメソッドmainの非staticフィールドにアクセスできません

だから私はclockの宣言をこれに変更しました:

static Clock clock = new Clock();

そしてそれはうまくいった。そのキーワードを宣言の前に置くことはどういう意味ですか?そのオブジェクトに対して何ができるのかという点で、それは正確に何をし、そして/または制限するでしょうか。

414
Click Upvote

staticメンバーは、特定のインスタンスではなくクラスに属しています。

だということだ staticフィールドのインスタンスは1つだけ存在します[1] たとえあなたがクラスのインスタンスを何百万も作成したとしても、作成しなくても。すべてのインスタンスで共有されます。

staticメソッドも特定のインスタンスに属していないため、インスタンスメンバーを参照できません。与えられた例では、mainHelloクラスのどのインスタンス(したがってClockクラスのどのインスタンス)を参照すべきかを知りません。 staticメンバーは、staticメンバーのみを参照できます。インスタンスメンバーはもちろんstaticメンバーにアクセスできます。

サイドノート: もちろん、staticメンバーはインスタンスメンバーにアクセスできます。 オブジェクト参照を通じて

例:

public class Example {
    private static boolean staticField;
    private boolean instanceField;
    public static void main(String[] args) {
        // a static method can access static fields
        staticField = true;

        // a static method can access instance fields through an object reference
        Example instance = new Example();
        instance.instanceField = true;
    }

[1]:実行時の特性に応じて、ClassLoader、AppDomain、またはスレッドごとに1つになりますが、それは重要なことです。

597
Mehrdad Afshari

これは、Helloには "clock"のインスタンスが1つだけで、 "Hello"クラスのインスタンスごとに1つだけではないことを意味します。つまり、すべてのインスタンス間で共通の "clock"参照が1つになります。 "Hello"クラス.

それで、あなたがあなたのコードのどこかで "new Hello"をやろうとしたら:A-最初のシナリオでは( "static"を使わずに)、 "new Hello"が呼ばれるたびに新しい時計を作ります。 B - 2番目のシナリオ(変更後、 "static"を使用)では、すべての "new Hello"インスタンスは、最初に作成された最初の同じ "clock"参照を共有して使用します。

あなたがmainの外側のどこかで "clock"を必要としない限り、これは同様にうまくいくでしょう:

package hello;
public class Hello
{
    public static void main(String args[])
    {
      Clock clock=new Clock();
      clock.sayTime();    
    }
}
129
Paul Tomblin

staticキーワードは、特定のinstanceではなく、何か(フィールド、メソッド、またはネストされたクラス)がtypeに関連していることを意味します。たとえば、MathクラスのインスタンスなしでMath.sin(...)を呼び出すと、実際にca n'tMathクラスのインスタンスを作成します。

詳細については、 OracleのJavaチュートリアルの関連ビット を参照してください。


サイドノート

Java残念ながらallowsインスタンスメンバーであるかのように静的メンバーにアクセスできます。

// Bad code!
Thread.currentThread().sleep(5000);
someOtherThread.sleep(5000);

これにより、looksleepがインスタンスメソッドであるかのようになりますが、実際には静的メソッドです。alwaysは、現在のスレッドをスリープ状態にします。呼び出し元のコードでこれを明確にすることをお勧めします。

// Clearer
Thread.sleep(5000);
96
Jon Skeet

Javaのstaticキーワードは、実際のオブジェクト自体ではなく、 type に属するため、変数または関数がそのクラスのすべてのインスタンス間で共有されることを意味します。

したがって、変数private static int i = 0;があり、それを1つのインスタンスでインクリメント(i++)すると、その変更はすべてのインスタンスに反映されます。 iはすべてのインスタンスで1になります。

オブジェクトをインスタンス化せずに静的メソッドを使用できます。

40
geowa4

静的メンバーの基本的な使い方.

public class Hello
{
    // value / method
    public static String staticValue;
    public String nonStaticValue;
}

class A
{
    Hello hello = new Hello();
    hello.staticValue = "abc";
    hello.nonStaticValue = "xyz";
}

class B
{
    Hello hello2 = new Hello(); // here staticValue = "abc"
    hello2.staticValue; // will have value of "abc"
    hello2.nonStaticValue; // will have value of null
}

これにより、クラスインスタンスHelloを他のクラスに送信しなくても、すべてのクラスメンバーで値を共有できます。そして静的であれば、クラスインスタンスを作成する必要はありません。

Hello hello = new Hello();
hello.staticValue = "abc";

クラス名で静的な値やメソッドを呼び出すことができます。

Hello.staticValue = "abc";
23
Vasil Valchev

Javaでは静的:

静的は非アクセス修飾子です。 staticキーワードはクラスのインスタンスよりもクラスに属します。変数またはメソッドをクラスにアタッチするために使用できます。

静的キーワードは:とともに使用できます

方法

変数

別のクラス内に入れ子になったクラス

初期化ブロック

:は使用できません

クラス(入れ子になっていない)

コンストラクタ

インターフェース

メソッドローカル内部クラス(違いがある場合は入れ子になったクラス)

内部クラスメソッド

インスタンス変数

ローカル変数

例:

次の例で想像してみてください。コンストラクター内で増分されるcountという名前のインスタンス変数

package pkg;

class StaticExample {
    int count = 0;// will get memory when instance is created

    StaticExample() {
        count++;
        System.out.println(count);
    }

    public static void main(String args[]) {

        StaticExample c1 = new StaticExample();
        StaticExample c2 = new StaticExample();
        StaticExample c3 = new StaticExample();

    }
}

出力:

1 1 1

インスタンス変数はオブジェクト作成時にメモリを取得するため、各オブジェクトはインスタンス変数のコピーを持ちます。インクリメントされても他のオブジェクトには反映されません。

インスタンス変数の数を静的に変更 oneの場合、プログラムは異なる出力を生成します。

package pkg;

class StaticExample {
    static int count = 0;// will get memory when instance is created

    StaticExample() {
        count++;
        System.out.println(count);
    }

    public static void main(String args[]) {

        StaticExample c1 = new StaticExample();
        StaticExample c2 = new StaticExample();
        StaticExample c3 = new StaticExample();

    }
}

出力:

1 2 3

この場合、静的変数は一度だけメモリを取得します。オブジェクトが静的変数の値を変更しても、その値は保持されます。

Final with Static:

finalおよびstaticとして宣言されているグローバル変数は、実行全体にわたって変更されません。なぜなら、静的メンバーはクラスメモリに格納され、実行全体で一度だけロードされるからです。それらはクラスのすべてのオブジェクトに共通です。静的変数をfinalとして宣言した場合、どのオブジェクトも値がfinalであるため変更できません。そのため、finalおよびstaticとして宣言された変数は、定数と呼ばれることがあります。インターフェースのすべてのフィールドは、デフォルトでは最終フィールドで静的なので、定数と呼ばれます。

enter image description here

Picture Resource: ファイナルスタティック

19
Virtual

静的とは、クラスに関連付けられたメソッドや変数を使用するためにクラスのインスタンスを作成する必要がないということです。あなたの例では、あなたは呼び出すことができます:

Hello.main(new String[]()) //main(...) is declared as a static function in the Hello class

次の代わりに直接

Hello h = new Hello();
h.main(new String[]()); //main(...) is a non-static function linked with the "h" variable

静的メソッド(クラスに属する)の内部からは、静的ではないメンバーにはアクセスできません。メンバーの値はクラスのインスタンス化に依存するためです。インスタンスメンバである非静的Clockオブジェクトは、Helloクラスのインスタンスごとに異なる値/参照を持つことになるため、クラスの静的部分からアクセスすることはできません。

19
Elie

この説明では、これまでクラスローダーの考慮事項を無視しています。厳密に言うと、Javaの静的フィールドは特定の クラスローダー のクラスのすべてのインスタンス間で共有されます。

13
Julien Chastang

既存の回答に追加するには、私は絵を試してみましょう:

2%の金利がすべての普通預金口座に適用されます。したがって、それは静的です。

残高はindividualである必要があります。したがって、それはnot staticです。

enter image description here

13
Andrejs

フィールドは、クラスまたはクラスのインスタンスに割り当てることができます。デフォルトでは、フィールドはインスタンス変数です。 staticを使用することでフィールドはクラス変数になります。したがってclockは1つだけです。あなたが一箇所で変更を加えた場合、それはどこにでも表示されます。インスタンス変数は互いに独立して変更されます。

7
sblundy

Javaでは、staticキーワードは単に次のことを示すと見なすことができます。

「特定のインスタンスとは関係なく、または関係なく」

このようにstaticを考えると、それが遭遇するさまざまな文脈でその使用法を理解するのがより簡単になります。

  • staticフィールドは、特定のインスタンスではなくクラスに属するフィールドです。

  • staticメソッドはthisの概念がないメソッドです。それはクラスで定義されており、参照が渡されない限りそのクラスの特定のインスタンスについては知りません。

  • staticメンバクラスは、その親クラスのインスタンスについての概念や知識がないネストクラスです(親クラスのインスタンスへの参照が渡されない限り)。

6
scottb

キーワードstaticは、インスタンスではなくクラス自体に属するものとしてフィールドまたはメソッドを示すために使用されます。コードを使用して、オブジェクトClockが静的である場合、HelloクラスのすべてのインスタンスはこのClockデータメンバ(field)を共有します。静的にしない場合、Helloの個々のインスタンスはそれぞれ固有のClockフィールドを持つことができます。

問題は、コードを実行できるように、クラスHello main メソッドを追加したことです。ここでの問題は、 main メソッドが静的であり、それ自体の内部で非静的フィールドやメソッドを参照できないことです。これを解決するには2つの方法があります。

  1. main メソッド内で参照できるように、Helloクラスのすべてのフィールドとメソッドを静的にします。これは実際には良いことではありません(あるいはフィールドやメソッドを静的にする間違った理由)
  2. Mainメソッド内にHelloクラスのインスタンスを作成し、そもそも意図した方法でそのすべてのフィールドとメソッドにアクセスします。

あなたのために、これはあなたのコードに次のような変更があることを意味します。

package hello;

public class Hello {

    private Clock clock = new Clock();

    public Clock getClock() {
        return clock;
    }

    public static void main(String args[]) {
        Hello hello = new Hello();
        hello.getClock().sayTime();
    }
}
6
hfontanez

私は "ヘルパー"クラスの静的メソッド(可能な場合のみ)を好みます。

呼び出し側クラスは、ヘルパークラスの別のメンバー(インスタンス)変数を作成する必要はありません。ヘルパークラスのメソッドを呼び出すだけです。また、コンストラクタが不要になり、メンバ(インスタンス)変数が不要になるため、ヘルパークラスも改善されています。

おそらく他の利点があります。

5
javaguy

静的は、クロックメンバーをインスタンスメンバーではなくクラスメンバーにします。 staticキーワードがなければ、Helloクラスのインスタンス(clockメンバ変数を持つ)を作成する必要があります。

Hello hello = new Hello();
hello.clock.sayTime();
5
Stephen Doyle

静的メソッドは、それらが定義されているクラスのインスタンス変数を使用しません。違いについての非常に良い説明は このページ にあります。

5
Marc Novakowski

静的メンバーが "this"ポインタを持たないことも考えられます。それらはすべてのインスタンスで共有されています。

3
kal

静的概念を理解する

public class StaticPractise1 {
    public static void main(String[] args) {
        StaticPractise2 staticPractise2 = new StaticPractise2();
        staticPractise2.printUddhav(); //true
        StaticPractise2.printUddhav(); /* false, because printUddhav() is although inside StaticPractise2, but it is where exactly depends on PC program counter on runtime. */

        StaticPractise2.printUddhavsStatic1(); //true
        staticPractise2.printUddhavsStatic1(); /*false, because, when staticPractise2 is blueprinted, it tracks everything other than static  things and it organizes in its own heap. So, class static methods, object can't reference */

    }
}

セカンドクラス

public class StaticPractise2 {
    public static void printUddhavsStatic1() {
        System.out.println("Uddhav");
    }

    public void printUddhav() {
        System.out.println("Uddhav");
    }
}
3
Uddhav Gautam

main()は、2つの基本的な制限がある静的メソッドです。

  1. 静的メソッドは、非静的データメンバーを使用したり、非静的メソッドを直接呼び出すことはできません。
  2. this()super()は静的コンテキストでは使用できません。

    class A {  
        int a = 40; //non static
        public static void main(String args[]) {  
            System.out.println(a);  
        }  
    }
    

出力:コンパイル時エラー

2
Bharthan
//Here is an example 

public class StaticClass 
{
    static int version;
    public void printVersion() {
         System.out.println(version);
    }
}

public class MainClass 
{
    public static void main(String args[]) {  
        StaticClass staticVar1 = new StaticClass();
        staticVar1.version = 10;
        staticVar1.printVersion() // Output 10

        StaticClass staticVar2 = new StaticClass();
        staticVar2.printVersion() // Output 10
        staticVar2.version = 20;
        staticVar2.printVersion() // Output 20
        staticVar1.printVersion() // Output 20
    }
}
2
Mohammad Parvez

静的変数静的メソッドでのみアクセスできるので、静的変数を宣言すると、これらのgetterメソッドとsetterメソッドは静的メソッドになります。

静的メソッドはクラス名を使ってアクセスできるクラスレベルです

以下は、静的変数の取得メソッドと設定メソッドの例です。

public class Static 
{

    private static String owner;
    private static int rent;
    private String car;
    public String getCar() {
        return car;
    }
    public void setCar(String car) {
        this.car = car;
    }
    public static int getRent() {
        return rent;
    }
    public static void setRent(int rent) {
        Static.rent = rent;
    }
    public static String getOwner() {
        return owner;
    }

    public static void setOwner(String owner) {
        Static.owner = owner;
    }

}
1
Bala Krishna

あるプロジェクトを実行するとき、最初に静的なもの(変数、メソッド、ブロックなど)をロードします。

このプロジェクトを実行すると、最初にメインメソッドがロードされます。そのstatic methodので。それからオブジェクト"a" object .Butオブジェクトはまだ定義されていないように見えます。その非静的だから。その後、このエラーのようになります。

0
Dev4World