2
public class Date
{

static int month; 

public static void setMonth(int x)
{ 
 this.month = x;  //compiler error
}

public static int getMonth()
{
 return month;  //compiles just fine, no error
}

}

コンパイルすると、次のエラーが表示されます。非静的変数これは静的コンテキストから参照できません。ただし、「これ」を削除すると。エラーはありません。キーワードstaticを使用して明確に宣言したときに、月が非静的変数であると言っている理由がわかりません。

4

4 に答える 4

6

this静的コンテキストでは使用できません。それは仕様によるものです -thisクラスではなくオブジェクトを参照します。メソッドのパラメーターとフィールドの間で名前が衝突する可能性があるという問題がある場合は、代わりにクラス名を使用できます。

public static void setMonth(int month)
{ 
 Date.month = month; 
}

一方、設計について考えて、クラス全体を 1 つのシングルトン オブジェクトとして使用するという決定を再考することもできます。

于 2013-03-23T23:55:22.583 に答える
4

これは現在のインスタンスを参照します。静的メソッドはインスタンスに関連付けられていません。それらはクラスに関連付けられています。

この例は悪い考えです。java.util.Dateとについて知っている人なら誰でも混乱するでしょうjava.sql.Date

于 2013-03-23T23:50:16.440 に答える
2

この場合を考えてみましょう:

class ParaentClass {

  public static final int SOME_VALUE = 7;

  public modValue(int m) {
    // WRONG
    return this.SOME_VALUE % m;
  }

}

class ChildClass extends ParentClass { }

// . . .

(new ChildClass()).modValue(4);

上記のコードでは、を呼び出すときmodValuethisは実際にはのインスタンスでChildClassはなく、のインスタンスでParentClassあるため、JVMがメソッドを実行しているときは、静的フィールドを探すクラスさえわかりません。JVMは、継承階層を上って最も一致する静的フィールドを探すようなことを行うことができると思いますが、それはひどいパフォーマンスになります。

とにかく、彼らがセマンティクスを定義することを決定した方法staticは、それらがクラスに関連付けられており、オーバーライドできないということです。ParentClass.SOME_VALUEしたがって、のようなインスタンスへの参照ではなく、クラス名(たとえば)でそれらを参照することは意味がありますthis

静的変数が現在スコープ内にある場合は、クラス名を削除できます

  public modValue(int m) {
    // CORRECT
    return ParentClass.SOME_VALUE % m;
  }

また

  public modValue(int m) {
    // ALSO CORRECT
    return SOME_VALUE % m;
  }
于 2013-03-24T00:00:05.753 に答える
2

Java では、クラス内でフィールドを静的にするか非静的にするかを選択できます。

フィールドが静的な場合、それを参照するためにそのクラスの「インスタンス」を「インスタンス化」する必要はありません。

あなたの例では、別のクラスの同じパッケージ内から「月」変数にアクセスできます(「アクセス修飾子」がないため、Javaはその変数を「パッケージプライベート」にします-中のものを除くすべてのクラスに隠されています次のようにして、同じディレクトリ (Java 用語ではパッケージ) にコピーします。

public class Example {
    void outputMonth() {
         System.out.println("This is the month: " + Date.month);
    }
}

しかし、静的修飾子が削除された場合、「月」は単純にクラスに関連付けられません。クラスの各「インスタンス」に属します。プログラムの現在のバージョンでは、「月」を Example クラスに移動し、Date に月ではなく Example.month で参照させることができ、まったく同じように機能します。

クラスの「インスタンス」を「インスタンス化」するには、「new」キーワードを使用します。

public class Example {
    void instantiateAndDisplay() {
         Date newInstance = new Date();
         System.out.println("This won't be pretty, but it's a new Date: " + newInstance);
    }
 }

ここで、static キーワードが「month」から削除されると、各 Date 「インスタンス」には、個別に変更できる月変数の独自のコピーが含まれます。new を 2 回呼び出すと、インスタンスが 2 つ作成され、呼び出しが 3 回、インスタンスが 3 つというようになります。

それがもう少し明確な場合、コンパイラが「これ」について警告する理由は、「これ」が現在のインスタンスのグラブバッグ用語であるためです。そのメソッドを静的にしたため、インスタンスはありません。そのコードはクラスにアタッチされていますが、Example クラスに移動でき、Date は Example.setMonth(month); を呼び出して使用できます。

「this」が定義されている理由は、スコープがあいまいな場合があるためです。setMonth の例では、すべてのメソッドから static 修飾子を削除した場合、ローカル変数の名前を「x」から「month」に変更できますが、これがないと、それ自体から渡されたローカル変数 month をそれ自体は何もしません。「this」は、「month」のスコープを「Date クラスの現在のインスタンス」を意味するように定義します。これにより、次の例に示すように、それを割り当てることができます。

public class Date {
    private int month;
    public void setMonth(int month) {
        this.month = month;
    }
    public void getMonth() {
        return month; // Note - no competing scope, so month comes from the current instance.
    }
 }

次に、2 つの新しい Date インスタンスを作成し、それらの月を異なる値に割り当てて、それらを個別に使用できます。しかし、修飾子が静的である場合、その値は、そのクラスのすべてのインスタンス、および「アクセス修飾子」によって許可されたすべてのクラスからアクセス可能であり、その範囲はこの議論を超えています。

于 2013-03-24T00:26:40.050 に答える