web-dev-qa-db-ja.com

非静的変数は静的コンテキストから参照できません

私はこのテストコードを書きました:

class MyProgram
{
    int count = 0;
    public static void main(String[] args)
    {
        System.out.println(count);
    }
}

しかし、それは以下のエラーを出します:

Main.Java:6: error: non-static variable count cannot be referenced from a static context
        System.out.println(count);
                           ^

メソッドにクラス変数を認識させるにはどうすればよいですか。

247
Greg

あなたはクラスとそのクラスのインスタンスの違いを理解しなければなりません。路上で車を見れば、どのモデルやタイプが見えなくても、車だとすぐにわかります。これはあなたが見るものと class "car"を比較するからです。クラスには、どれがすべての車に似ているが含まれています。テンプレートやアイデアとして考えてください。

同時に、あなたが見ている車はそれがあなたが期待するすべての特性を持っているのでクラス "car"のインスタンスです:それを運転している誰かがいる、それはエンジン、車輪を持っています。

したがって、クラスは「すべての車に色があります」と言い、インスタンスは「この特定の車は赤です」と言います。

OOの世界ではクラスを定義し、クラスの中ではColor型のフィールドを定義します。クラスがインスタンス化されるとき(特定のインスタンスを作成するとき)、メモリは色用に予約されており、この特定のインスタンスに色を付けることができます。これらの属性は固有のものであるため、静的ではありません。

静的フィールドとメソッドはすべてのインスタンスと共有されます。これらはクラス固有の値であり、特定のインスタンスではありません。メソッドの場合、これは通常グローバルヘルパーメソッドです(Integer.parseInt()のように)。フィールドの場合、通常は定数です(車の種類のように、つまり頻繁には変更されない限られたセットがあるものなど)。

問題を解決するには、ランタイムがインスタンス用にメモリを確保できるように、クラスのインスタンスをインスタンス化する(オブジェクトを作成する)必要があります(そうしないと、異なるインスタンスがお互いを上書きしてしまい、不要になります)。

あなたの場合は、このコードを開始ブロックとして試してください。

public static void main (String[] args)
{
    try
    {
        MyProgram7 obj = new MyProgram7 ();
        obj.run (args);
    }
    catch (Exception e)
    {
        e.printStackTrace ();
    }
}

// instance variables here

public void run (String[] args) throws Exception
{
    // put your code here
}

新しいmain()メソッドは、それが含むクラスのインスタンスを作成し(奇妙に聞こえますが、main()はインスタンスではなくクラスで作成されるため、これを実行できます)、次にインスタンスメソッド(run())を呼び出します。

252
Aaron Digulla

静的フィールドとメソッドはクラス自体に接続されており、そのインスタンスには接続されていません。クラスA、 'normal'メソッドb、および静的メソッドcがあり、クラスaのインスタンスAを作成する場合、A.c()およびa.b()の呼び出しは有効です。メソッドc()はどのインスタンスが接続されているかわからないため、非静的フィールドを使用することはできません。

あなたのための解決策はあなたがあなたのフィールドを静的にするか、あなたのメソッドを非静的にすることです。あなたは主にこのようになります:

class Programm {

    public static void main(String[] args) {
        Programm programm = new Programm();
        programm.start();
    }

    public void start() {
        // can now access non-static fields
    }
}
71
Mnementh

staticキーワードは、クラス内のメソッドまたは変数のライフサイクルを変更します。クラスがロードされるときにstaticメソッドまたは変数が作成されます。 staticとして宣言されていないメソッドや変数は、たとえばnew演算子を使用して、クラスがオブジェクトとしてインスタンス化されている場合にのみ作成されます。

クラスのライフサイクルは、広い意味では、次のとおりです。

  1. クラスのソースコードはテンプレートやパターン、スタンプを作成するために書かれています。
  2. クラスを使用してnew演算子を使用してオブジェクトを作成し、実際のオブジェクトとしてそのクラスのインスタンスを作成します
  3. ガベージコレクション中にメモリなど、保持しているリソースを回収しているオブジェクトを破棄します。

アプリケーションの初期エントリポイントを持つために、JavaはJavaプログラムが合意された名前または特別な名前を持つメソッドを含むクラスを持たなければならないという規約を採用しています。この特別なメソッドはmain()と呼ばれています。メソッドはmainメソッドを含むクラスがインスタンス化されているかどうかにかかわらず存在しなければならないので、main()メソッドはstatic修飾子を付けて宣言し、クラスがロードされるとすぐにmain()メソッドが使用できるようにします。

その結果、Java helloworldなどのコマンドラインでJavaアプリケーションを起動すると、一連のアクションが発生します。まず最初に、Java仮想マシンが起動され初期化されます。次に、コンパイルされたJavaコードを含むhelloworld.classファイルがJava仮想マシンにロードされます。次に、Java仮想マシンはhelloworldクラスでmain(String [] args)と呼ばれるメソッドを探します。このメソッドは、クラスが実際にはオブジェクトとしてインスタンス化されていなくても存在するように、staticである必要があります。 Java仮想マシンは、クラスからオブジェクトを作成してもクラスのインスタンスを作成しません。クラスをロードしてmain()メソッドで実行を開始するだけです。

そのため、クラスのインスタンスをオブジェクトとして作成する必要があります。そうすれば、static修飾子で宣言されていないクラスのメソッドと変数にアクセスできます。 Javaプログラムがmain()関数で起動したら、ロードされるクラスの一部として存在するため、staticの修飾子を持つすべての変数またはメソッドを使用できます。

ただし、static修飾子を持たないmain()メソッドの外側にあるクラスの変数およびメソッドは、クラスのインスタンスがmain()メソッド内のオブジェクトとして作成されるまで使用できません。オブジェクトを作成したら、オブジェクトの変数とメソッドを使用できます。クラスのオブジェクトを通過せずにstatic修飾子を持たないクラスの変数とメソッドを使用しようとすると、コンパイル時にJavaコンパイラによってキャッチされ、エラーとして通知されます。

import Java.io.*;

class HelloWorld {
    int myInt;      // this is a class variable that is unique to each object
    static int myInt2;  // this is a class variable shared by all objects of this class

    static void main (String [] args) {
        // this is the main entry point for this Java application
        System.out.println ("Hello, World\n");
        myInt2 = 14;    // able to access the static int
        HelloWorld myWorld = new HelloWorld();
        myWorld.myInt = 32;   // able to access non-static through an object
    }
}
34

プログラムを最初に分析しましょう。プログラムでは、最初のメソッドはmain()です。静的メソッドであることに注意してください。次に、そのメソッドのローカル変数を宣言します(compareCount、low、highなど)。 。この変数の有効範囲は、静的メソッドであるか非静的メソッドであるかにかかわらず、宣言されたメソッドのみです。そのため、そのメソッドの外でこれらの変数を使用することはできません。これが基本的なエラーです。

それでは次のポイントに来ます。あなたはstaticがあなたを殺していると言いました。 (それはあなたを殺しているかもしれませんが、それはあなたのプログラムに命を与えるだけです!!)最初にあなたは基本的な事を理解しなければなりません。 *静的メソッドは静的メソッドのみを呼び出し、静的変数のみを使用します。 *静的変数または静的メソッドはそのクラスのどのインスタンスにも依存しません。 (つまり、静的変数の状態を変更すると、それはクラスのすべてのオブジェクトに反映されます)*このため、クラス変数またはクラスメソッドとして呼び出します。そして "static"キーワードについてもっとたくさんのことがあります。私は今あなたがアイデアを得ることを願っています。最初に変数のスコープを変更し、それを静的として宣言します(静的メソッドで使用できるようにするため)。

そしてあなたへのアドバイスは:あなたは変数の範囲と静的な機能性の考えを誤解しました。それについてはっきり考えてください。

11
Suseendran.P

最も基本的なことは、静的変数または静的メソッドがクラスレベルにあることです。クラスレベルの変数やメソッドは、インスタンスレベルのメソッドや変数よりも先にロードされます。当然、ロードされていないものは使用できません。そのため、実行時に処理するものを許可しないJavaコンパイラは、コンパイル時に解決します。だからこそ、静的ではない文脈を静的なコンテキストから参照することはできません。あなただけのクラスレベルのスコープ、インスタンスレベルのスコープとローカルスコープについて読む必要があります。

10
Ajay Bhojak

あなたの静的メソッドからそれらにアクセスできるようにするためには、これらは静的メンバー変数である必要があります。

public class MyProgram7 {
  static Scanner scan = new Scanner(System.in);
  static int compareCount = 0;
  static int low = 0;
  static int high = 0;
  static int mid = 0;  
  static int key = 0;  
  static Scanner temp;  
  static int[]list;  
  static String menu, outputString;  
  static int option = 1;  
  static boolean found = false;

  public static void main (String[]args) throws IOException {
  ...
8
Nick Moore

これで、メソッド内でインスタンスを追加/使用することができます

public class Myprogram7 {

  Scanner scan;
  int compareCount = 0;
  int low = 0;
  int high = 0;
  int mid = 0;  
  int key = 0;  
  Scanner temp;  
  int[]list;  
  String menu, outputString;  
  int option = 1;  
  boolean found = false;  

  private void readLine() {

  }

  private void findkey() {

  }

  private void printCount() {

  }
  public static void main(String[] args){

    Myprogram7 myprg=new Myprogram7();
    myprg.readLine();
    myprg.findkey();
    myprg.printCount();
  }
}

静的なことをあなたに説明しようと思います。まず第一に、静的変数はクラスの特定のインスタンスに属していません。それらはクラスの名前で認識されます。静的メソッドもまた、特定のインスタンスには属しません。それらは静的変数だけにアクセスできます。あなたがMyClass.myMethod()を呼び、myMethodが静的メソッドであると想像してください。メソッド内で非静的変数を使用する場合、地球上の地獄はどの変数を使用するべきかをどのように知っているでしょうか。それが、静的メソッドから静的変数のみを使用できる理由です。繰り返しますが、それらは特定のインスタンスに属していません。

4
Petar Minchev
  • 最初のことは、クラスのインスタンスとそのクラス自体の違いを知ることです。クラスは、特定のプロパティ、およびそれらのプロパティのコンテキストにおける全体の動作をモデル化します。インスタンスはそれらのプロパティに特定の値を定義します。

  • Staticキーワードに束縛されたものはすべて、クラスのインスタンスのコンテキストではなく、クラスのコンテキストで使用できます。

  • 上記の当然の結果として

    1. メソッド内の変数は静的にできません
    2. 静的フィールド、そしてメソッドはクラス名を使って呼び出さなければなりません。 MyProgram7.main(...)
  • 静的フィールド/メソッドの有効期間は、アプリケーションの有効期間と同じです。

例えば。たとえば、carはcolorというプロパティを持ち、 'motion'という動作を示します。車の実例は、時速25kmで動いているレッドフォルクスワーゲンビートルです。

これで、自動車の静的な特性は道路上の車輪の数(4)になり、これはすべての自動車に当てはまります。

HTH

2
Everyone

これは、すべての初心者にとって静的なキーワードWordについて説明するのとは少し違います。
あなたがクラスとオブジェクトをもっと扱うとき、あなたはそれを明確に知るようになるでしょう。

| * | 静的: 静的項目はクラス名で呼び出すことができます
コードで観察すると、いくつかの関数は次のようなクラス名で直接呼び出されます。

NamCls.NamFnc();

System.out.println();

これはNamFncとprintlnがそれらの前に静的なキーワードを使って宣言されるからです。

| * | 非静的:非静的項目はクラス変数で呼び出すことができます
静的でない場合は、クラスの変数が必要です。
クラス変数の後にドットを置き、
次にfunctionを呼び出します。

NamCls NamObjVar = new NamCls();
NamObjVar.NamFnc();

| * |クラス内の静的および非静的関数

public class NamCls
{
    public static void main(String[] args)
    {
        PlsPrnFnc("Tst Txt");

        NamCls NamObjVar = new NamCls();
        NamObjVar.PrnFnc("Tst Txt");
    }

    static void PlsPrnFnc(String SrgPsgVal)
    {
        System.out.println(SrgPsgVal);
    }

    void PrnFnc(String SrgPsgVal)
    {
        System.out.println(SrgPsgVal);
    }
}

public class NamCls
{
    public static void main(String[] args)
    {
        NamTicCls NamTicVaj = new NamTicCls();
        NamTicVaj.PrnFnc("Tst Txt");

        NamCls NamObjVar = new NamCls();
        NamNicCls NamNicVar = NamObjVar.new NamNicCls();
        NamNicVar.PrnFnc("Tst Txt");
    }

    static class NamTicCls
    {
        void PrnFnc(String SrgPsgVal)
        {
            System.out.println(SrgPsgVal);
        }
    }

    class NamNicCls
    {
        void PrnFnc(String SrgPsgVal)
        {
            System.out.println(SrgPsgVal);
        }
    }
}
1
Sujay U N

インスタンスメソッドまたはインスタンス変数を呼び出す前にオブジェクト(Instance)が必要です。インスタンス変数が静的メソッドコンパイラから呼び出されたとき、この変数がどのオブジェクトに属しているのかわかりません。静的メソッドはオブジェクトを持たないため(常に1つのコピーのみ)。インスタンスメソッドからインスタンス変数またはインスタンスメソッドを呼び出すとき、それはthisオブジェクトを参照します。つまり、変数は作成されたオブジェクトに属し、各オブジェクトにはインスタンスメソッドと変数の独自のコピーがあります。

静的変数はstaticとしてマークされ、インスタンス変数は特定のキーワードを持ちません。

1
ultimatex

クラスファイルをロードするのはClassLoaderです。独自のクラスを作成したときに何が起こるか見てみましょう。

例1

class StaticTest {

      static int a;
      int b;
      int c;
}

これで、クラス "StaticTest"に3つのフィールドがあることがわかりました。しかし、実際にはb、cメンバ変数は存在しません。わかりましたね。ここで、b、cはインスタンス変数です。インスタンス変数はオブジェクト作成時にメモリを取得するためです。だからここb、cはまだメモリを得ていません。 b、cが存在しないのはそのためです。だからの存在だけがあります。 ClassLoaderの場合、aについての情報は1つだけです。 ClassLoaderはまだオブジェクト化されていないため、b、cをまだ認識していません。

他の例を見てみましょう。

class StaticTest {

      public void display() {
          System.out.println("Static Test");
      }


      public static void main(String []cmd) {

             display();       
      }

}

このコードコンパイラをコンパイルしようとすると、CEエラーが発生します。 CE:非静的メソッドdisplay()は静的コンテキストから参照できません。

ClassLoaderの場合は、次のようになります。

class StaticTest {

      public static void main(String []cmd) {

             display();       
      }

}

例2では、​​CEエラーは静的コンテキストから非静的メソッドを呼び出すためです。そのため、ClassLoaderがコンパイル時にメソッドdisplay()を認識することはできません。コンパイル時エラーが発生します。

0