web-dev-qa-db-ja.com

非静的メソッドへの静的参照を作成できません

Javaでの多言語アプリケーションの構築。 R.stringリソースXMLファイルから文字列値を挿入するときにエラーを取得する:

public static final String TTT =  (String) getText(R.string.TTT);

これはエラーメッセージです。

エラー:Context型から非静的メソッドgetText(int)への静的参照を作成できません

これはどのように引き起こされ、どうすれば解決できますか?

92
Chen M

getText()は非静的なので、静的メソッドから呼び出すことはできません。

理由を理解するには、2つの違いを理解する必要があります。

インスタンス(非静的)メソッドは、特定のタイプ(クラス)のオブジェクトに対して機能します。これらは、次のような新しいもので作成されます。

SomeClass myObject = new SomeClass();

インスタンスメソッドを呼び出すには、インスタンス(myObject)で呼び出します。

myObject.getText(...)

ただし、静的メソッド/フィールドは、タイプで直接only呼び出すことができます。次のように言います。 前のステートメントは正しくありません。 オブジェクト参照を使用して静的フィールドを参照することもできますmyObject.staticMethod()ですが、クラス変数であることを明確にしないため、これは推奨されません。

... = SomeClass.final

また、異なるデータ空間(インスタンスデータとクラスデータ)で動作するため、2つは連携できません。

説明してみましょう。このクラス(擬似コード)を検討してください。

class Test {
     string somedata = "99";
     string getText() { return somedata; } 
     static string TTT = "0";
}

今、私は次のユースケースを持っています:

Test item1 = new Test();
 item1.somedata = "200";

 Test item2 = new Test();

 Test.TTT = "1";

値は何ですか?

まあ

in item1 TTT = 1 and somedata = 200
in item2 TTT = 1 and somedata = 99

つまり、TTTは、型のすべてのインスタンスで共有されるデータムです。と言っても意味がありません

class Test {
         string somedata = "99";
         string getText() { return somedata; } 
  static string TTT = getText(); // error there is is no somedata at this point 
}

それで、問題はなぜTTTstaticなのか、またはgetText()が静的ではないのか?

staticを削除すると、このエラーが発生するはずです。ただし、タイプが何をするのか理解していなければ、次のエラーまでは絆創膏に過ぎません。非静的であることが必要なgetText()の要件は何ですか?

136
Preet Sangha

静的でないContextメソッドの混合getText()static final Stringで使用できない理由については、すでにいくつかの良い回答があります。

質問するのは良いことです:なぜあなたはこれをしたいのですか? Stringリソースからstringsをロードし、その値をpublic staticフィールドに入力しようとしています。私はこれがあなたの他のクラスのいくつかがそれにアクセスできるようになっていると思いますか?その場合、これを行う必要はありません。代わりにContextを他のクラスに渡し、それらの中からcontext.getText(R.string.TTT)を呼び出します。

public class NonActivity {

    public static void doStuff(Context context) {
        String TTT = context.getText(R.string.TTT);
        ...
    }
}

そして、これをActivityから呼び出すには:

NonActivity.doStuff(this);

これにより、public staticフィールドを使用しなくてもStringリソースにアクセスできます。

11
dave.c

検索でこれを見つける他の人のために:

オブジェクト名ではなくクラス名を使用して誤って関数を呼び出したときに、これを頻繁に取得します。これは通常、あまりにも似た名前を付けるために発生します:P

すなわち:

MyClass myclass = new MyClass();

// then later

MyClass.someFunction();

これは明らかに静的メソッドです。 (何かに良い)しかし、私が本当にやりたかったこと(ほとんどの場合)

myclass.someFunction();

それは非常にばかげた間違いですが、2、3か月ごとに、「MyClass」の定義で変数をいじって約30分間無駄にして、実際に間違っているときに何が間違っているのかを判断しています。

おもしろい注意:スタックオーバーフローは、ここで間違いを明らかにするための構文を強調しています。

8
SpiRail

変数を非静的にすることができます

public final String TTT =  (String) getText(R.string.TTT);

または「getText」メソッドを静的にします(可能な場合)

2
Kellindil

非静的メソッドから静的変数を参照することはできません。これを理解するには、静的と非静的の違いを理解する必要があります。

静的変数はクラス変数であり、最初に作成されたインスタンスが1つだけのクラスに属します。非静的変数は、クラスのオブジェクトを作成するたびに初期化されます。

さて、質問にお答えします。new()演算子を使用すると、すべてのオブジェクトのすべての非静的ファイルのコピーが作成されますが、静的フィールドの場合はそうではありません。そのため、非静的メソッドから静的変数を参照している場合、コンパイル時にエラーが発生します。

2
Krishna

getTextはアクティビティのメンバーであるため、「this」が存在する場合に呼び出す必要があります。アクティビティが作成される前にクラスがロードされると、静的変数が初期化されます。

リソース文字列から変数を初期化するため、静的にすることはできません。静的にしたい場合は、文字列値で初期化できます。

2
Robby Pond

この質問は新しいものではなく、既存の回答はいくつかの優れた理論的背景を提供します。もっと実用的な答えを加えたいだけです。

getTextはContext抽象クラスのメソッドであり、それを呼び出すには、そのサブクラス(アクティビティ、サービス、アプリケーションなど)のインスタンスが必要です。問題は、Contextのインスタンスが作成される前にpublic static final変数が初期化されることです。

これを解決するにはいくつかの方法があります。

  1. 静的修飾子を削除し、クラス本体内に配置することにより、変数をアクティビティのメンバー変数(フィールド)またはコンテキストの他のサブクラスにします。
  2. それを静的に保ち、初期化を後の時点まで遅らせます(例:onCreateメソッド内);
  3. 実際に使用する場所でローカル変数にします。
0
dev.bmax