web-dev-qa-db-ja.com

public static void main()非静的変数にアクセス

非静的変数は静的メソッドでは使用できないと言われていますが、public static void mainはそうです。

13
user1526671

いいえ、ありません。

public class A {
  int a = 2;
  public static void main(String[] args) {
    System.out.println(a); // won't compile!!
  }
}

だが

public class A {
  static int a = 2;
  public static void main(String[] args) {
    System.out.println(a); // this works!
  }
}

または、Aをインスタンス化する場合

public class A {
  int a = 2;
  public static void main(String[] args) {
    A myA = new A();
    System.out.println(myA.a); // this works too!
  }
}

また

public class A {
  public static void main(String[] args) {
    int a = 2;
    System.out.println(a); // this works too!
  }
}

aはここではローカル変数であり、インスタンス変数ではないため、機能します。メソッドローカル変数は、メソッドがstaticであるかどうかに関係なく、メソッドの実行中に常に到達可能です。

26
Keppil

はい、メインメソッドは非静的変数にアクセスできますが、間接的にのみ実際のインスタンスを介してです。

例:

public class Main {
    public static void main(String[] args) {
        Example ex = new Example();
        ex.variable = 5;
    }
}

class Example {
    public int variable;
}

「静的メソッドでは静的でない変数は使用できない」と言うときの意味は同じクラスの非静的メンバーはできる '直接アクセスする(たとえば Keppilsの回答 に示すように)。

関連質問:


更新:

非静的変数について話すとき、暗黙的にメンバー変数を意味します。 (ローカル変数はとにかく静的修飾子を持つことができないため)

コードで

public class A {
    public static void main(String[] args) {
        int a = 2;
        System.out.println(a); // this works!
    }
}

local変数を宣言しています(静的修飾子がない場合でも、通常は非静的とは呼ばれません)。

10
aioobe

Mainメソッドは、非静的メンバーにもアクセスできません。

_final public class Demo
{
   private String instanceVariable;
   private static String staticVariable;

   public String instanceMethod()
   {
      return "instance";
   }

   public static String staticMethod()
   {
      return "static";
   }

   public static void main(String[] args)
   {
      System.out.println(staticVariable); // ok
      System.out.println(Demo.staticMethod()); // ok

      System.out.println(new Demo().instanceMethod()); // ok
      System.out.println(new Demo().instanceVariable); // ok

      System.out.println(Demo.instanceMethod()); // wrong
      System.out.println(instanceVariable);         // wrong 
   }
}
_

これは、デフォルトでは、メソッドまたは変数を呼び出すときに、実際にthis.method()またはthis.variableにアクセスしているためです。しかし、main()メソッドまたはその他の静的method()では、「this」オブジェクトはまだ作成されていません。

この意味で、静的メソッドはそれを含むクラスのオブジェクトインスタンスの一部ではありません。これがユーティリティクラスの背後にある考え方です。

静的コンテキストで非静的メソッドまたは変数を呼び出すには、最初に、クラス外の任意の場所と同じように、コンストラクターまたはファクトリーを使用してオブジェクトを作成する必要があります。


より深い:

基本的に、これはJava IMOの設計の欠陥であり、静的メンバー(メソッドとフィールド)の参照を許可しますあたかもそれらはインスタンスメンバーでした。これは非常に混乱する可能性があります。このようなコードで:

_Thread newThread = new Thread(runnable);
newThread.start();
newThread.sleep(1000);
_

それはlooks新しいスレッドをスリープ状態に送っているようですが、-実際にはは次のようなコードにコンパイルされます。

_Thread newThread = new Thread(runnable);
newThread.start();
Thread.sleep(1000);
_

sleepは静的メソッドなので、currentスレッドのみをスリープ状態にします。

実際、変数はnullでないかどうかさえチェックされていません(これ以上、以前はそうだったと思います)。

_Thread t = null;
t.sleep(1000);
_

一部のIDEは、このようなコードに対して警告またはエラーを発行するように構成できます。読みやすさを損なうため、行うべきではありません。 (これはC#によって修正された欠陥の1つです...)

3
Lion

**ここでは、静的および非静的メソッドで静的および非静的データメンバーのアクセスをクリアする表を見ることができます。 ** static non-static table

3
Sufyan Ahmad

次のような静的メソッドで非静的参照を作成できます。

_static void method() {
   A a = new A();
}
_

public static void main(String[] args)メソッドの場合と同じこと

0
public class XYZ
{
   int i=0;
   public static void increament()
       {
       i++;   
       }
}
public class M
{
    public static void main(String[] args)
    {
    XYZ o1=new XYZ();
    XYZ o2=new XYZ();
    o1.increament(); 
    XYZ.increament(); //system wont be able to know i belongs to which object 
                  //as its increament method(static method)can be called using   class name system 
                  //will be confused changes belongs to which object.
    }
}
0