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


102

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

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

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

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

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


1
「多言語アプリケーション」で静的である必要があるのはなぜですか?よくわからない。
xil3

3
静的データメンバーに文字列リソースを格納しないでください。getString()あなたがそれらを必要とするときは常に経由でそれらを要求します。これにより、選択した言語を変更するユーザーに合わせてアプリケーションが適切に調整されます。
CommonsWare、2011

回答:


143

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

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

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

SomeClass myObject = new SomeClass();

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

myObject.getText(...)

ただし、静的メソッド/フィールドは、次のように直接型でのみ呼び出すこと ができます。前のステートメントは正しくありません。同様にオブジェクト参照で静的フィールドを参照することもできますが、 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 
}

では、問題はなぜTTTが静的であるか、なぜgetText()が静的ではないのかということです。

を削除するstaticと、このエラーを乗り越えるはずですが、タイプが何であるかを理解していないと、次のエラーが発生するまで石膏が付着するだけです。getText()非静的であることを要求する要件は何ですか?


プロジェクトの複数のファイルから呼び出すため、静的です。「静的」を削除すると、エラーコードは消えましたが、この変数を使用している他のファイルに多くのエラーがあります。
チェンM

しかし、それが私のポイントです。2つをいつ使用できるかを理解する必要があります。
Preet Sangha

「Constants notifications_values = new Constants();」という行をメインアクティビティクラスに追加すると、コンパイルは正常に行われますが、エミュレータではこのアクティビティの実行時にクラッシュします
Chen M

11

非静的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);

これによりStringpublic staticフィールドを使用せずにリソースにアクセスできます。


1
本当にありがとうございます。あなたの推薦に従ってすべてのファイルを変更しました。
Chen M

私はこれをやろうとしていましたが、文字列配列とString a[] = context.getTextArray(R.array.myStringArray); 、ただし、エラーが発生しますThe method getTextArray(int) is undefined for the type Context-getTextで機能するのになぜ未定義になるのですか?
auspicious99

1
@ auspicious99 Contextは、aに呼び出されるメソッドgetTextArrayがないためgetTextです。多分あなたはResourcesどちらが持っているのかを考えていますgetTextArray
dave.c '08 / 08/14

ああ、ありがとう!(アクティビティから非アクティビティへの)コンテキストの代わりにリソースに渡され、私のgetStringArrayは機能しました。
auspicious99

9

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

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

つまり:

MyClass myclass = new MyClass();

// then later

MyClass.someFunction();

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

myclass.someFunction();

これはばかげた間違いですが、数か月ごとに、「MyClass」定義の変数をいじって約30分無駄にし、実際に何が間違っているのかを解決します。これは単なるタイプミスです。

面白いメモ:スタックオーバーフローは構文を強調表示して、間違いをここで明らかにします。


IDEもこれを強調していませんか?そうするように設定できると思います:)
Matthias Meid

2

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

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

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


2

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

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


2

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

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

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


0

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

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

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

  1. static修飾子を削除してクラス本体内に配置することにより、変数をアクティビティまたはコンテキストの他のサブクラスのメンバー変数(フィールド)にします。
  2. それを静的に保ち、初期化を後で(たとえば、onCreateメソッドで)遅延させます。
  3. 実際に使用する代わりにローカル変数にしてください。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.