Javaでの多言語アプリケーションの構築。 R.string
リソースXMLファイルから文字列値を挿入するときにエラーを取得する:
public static final String TTT = (String) getText(R.string.TTT);
これはエラーメッセージです。
エラー:Context型から非静的メソッドgetText(int)への静的参照を作成できません
これはどのように引き起こされ、どうすれば解決できますか?
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()
の要件は何ですか?
静的でない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
リソースにアクセスできます。
検索でこれを見つける他の人のために:
オブジェクト名ではなくクラス名を使用して誤って関数を呼び出したときに、これを頻繁に取得します。これは通常、あまりにも似た名前を付けるために発生します:P
すなわち:
MyClass myclass = new MyClass();
// then later
MyClass.someFunction();
これは明らかに静的メソッドです。 (何かに良い)しかし、私が本当にやりたかったこと(ほとんどの場合)
myclass.someFunction();
それは非常にばかげた間違いですが、2、3か月ごとに、「MyClass」の定義で変数をいじって約30分間無駄にして、実際に間違っているときに何が間違っているのかを判断しています。
おもしろい注意:スタックオーバーフローは、ここで間違いを明らかにするための構文を強調しています。
変数を非静的にすることができます
public final String TTT = (String) getText(R.string.TTT);
または「getText」メソッドを静的にします(可能な場合)
非静的メソッドから静的変数を参照することはできません。これを理解するには、静的と非静的の違いを理解する必要があります。
静的変数はクラス変数であり、最初に作成されたインスタンスが1つだけのクラスに属します。非静的変数は、クラスのオブジェクトを作成するたびに初期化されます。
さて、質問にお答えします。new()演算子を使用すると、すべてのオブジェクトのすべての非静的ファイルのコピーが作成されますが、静的フィールドの場合はそうではありません。そのため、非静的メソッドから静的変数を参照している場合、コンパイル時にエラーが発生します。
getTextはアクティビティのメンバーであるため、「this」が存在する場合に呼び出す必要があります。アクティビティが作成される前にクラスがロードされると、静的変数が初期化されます。
リソース文字列から変数を初期化するため、静的にすることはできません。静的にしたい場合は、文字列値で初期化できます。
この質問は新しいものではなく、既存の回答はいくつかの優れた理論的背景を提供します。もっと実用的な答えを加えたいだけです。
getTextはContext抽象クラスのメソッドであり、それを呼び出すには、そのサブクラス(アクティビティ、サービス、アプリケーションなど)のインスタンスが必要です。問題は、Contextのインスタンスが作成される前にpublic static final変数が初期化されることです。
これを解決するにはいくつかの方法があります。