開発してみると、以下のように non-static method cannot be referenced from a static context
コンパイルエラーが発生することがあります。
error: non-static method printUserName() cannot be referenced from a static context
printUserName();
^
1. エラー発生原因
Static メソッドはオブジェクトを生成せずに使用できるため、Static メソッドの内部ではメンバー変数やメソッドを使用できません。 static メソッドの呼び出し時にオブジェクトが作成されなかった可能性があるため、オブジェクトの変数とメソッドへのアクセスを許可しません。また、オブジェクトが作成されていても、Staticメソッドでどのオブジェクトのメンバ変数にアクセスする必要があるのかわかりません。したがって、 static メソッドでメンバ変数、メソッドアクセス時に、上記のようなコンパイルエラーが発生します。
メンバ変数とメソッドにアクセスするときは、以下のようにthisが省略されていると考えると理解しやすいです。 this はオブジェクト自身を意味しますが、 static はオブジェクト生成なしで使用するメソッドなので、 static メソッドの中で this は指す対象がなくなります。
public void printUserName() {
printSomething(this.name);
printSomething(this.getUserName());
}
2. staticでアクセス可能な変数とメソッド
以下の例のように、 static メソッド staticPrintUserName()
は static 変数とメソッドを呼び出すことができます。
public class User {
private static Boolean DEBUG = true;
private String name;
public User(String name) {
this.name = name;
}
public static void staticPrintUserName() {
if (DEBUG) {
System.out.println("It's running with debug mode.");
}
if (User.DEBUG) {
printSomething("Do something!");
}
}
public static void printSomething(String str) {
System.out.println(str);
}
}
static メソッドは生成されたオブジェクトからの呼び出しも可能で、
User user = new User("John Doe");
user.staticPrintUserName();
オブジェクトが作成されなくても、クラス名で直接メソッドを呼び出すこともできます。
User.staticPrintUserName();
static メソッドの属性がオブジェクト生成なしで呼び出せるため、static メソッドでメンバ変数やメソッドにアクセスしてはいけません。
以下のように staticPrintUserName()
からメンバメソッド printUserName()
を呼び出そうとすると、コンパイルエラーが発生します。
public class User {
private static Boolean DEBUG = true;
private String name;
public User(String name) {
this.name = name;
}
public void printUserName() {
printSomething(name);
}
public static void staticPrintUserName() {
printUserName();
}
public static void printSomething(String str) {
System.out.println(str);
}
}
Output:
src/main/java/User.java:15: error: non-static method printUserName() cannot be referenced from a static context
printUserName();
^
3. non-static メソッドでアクセス可能な変数とメンバー
non-static メソッドでは、static 変数、メソッドだけでなく、メンバー変数、メンバーメソッドの両方にアクセスできます。
public class User {
private static Boolean DEBUG = true;
private String name;
public User(String name) {
this.name = name;
}
public void printUserName() {
if (DEBUG) {
printSomething(name);
}
}
public static void printSomething(String str) {
System.out.println(str);
}
}
4. 問題原因の確認と解決方法
エラーは static でメンバ変数とメンバメソッドにアクセスするために発生します。単純ですが、継承関係が複雑なライブラリコードを見たり、呼び出し構造がねじれていてLambdaコードが混在しているとうまくいっていますが、なぜエラーが発生しないのですか?と考えることができます。メソッド呼び出しの順序によく従うと、問題の原因を見つけることができます。
References
Related Posts
- Java - AtomicReference使用方法
- Java - CountDownLatchを使用する方法、および例
- Java - ScheduledThreadPoolExecutor使用方法
- Java - SummaryStatisticsの使用方法(count、min、max、average)
- Java8 - 関数型インタフェース (Functional Interface) について
- Java - String配列をint配列に変換する
- Java - ArrayList要素の値を変更する方法、replaceAll()
- Java - 2つのリストが同じかどうかを比較
- Java - 配列から特定のIndex要素を削除する3つの方法
- Java - HashMapソート、4つの方法
- Java - 文字列を配列に変換する方法
- Java - ArrayListが空であることを確認する3つの方法
- Java - ArrayListの巡回、4つの方法
- Java - ArrayListの最大値、最小 値を見つける
- Java - ArrayListの合計、平均値の計算
- Java - HashMap巡回、3つの方法
- Java - do whileとwhileの違い
- Java - Lambda式と関数型インタフェース
- Java - List empty(null)チェック、3つの方法
- Java - ArrayListの初期化、4つの方法
- Java - Stream.reduce()の使い方と例
- Java - 2つのマップを結合する(merge、putAll)
- Java - java.util.Dateをjava.sql.Dateに変換する
- Java - ArrayListをStringに変換する
- Java - ClassNotFoundExceptionの発生原因と解決策
- Java - 非静的メソッドは静的コンテキストから参照できません
- Java - NoSuchMethodErrorの原因と解決策
- Java - JSONライブラリを使用する方法(JSONObject、JSONArray)
- Java - byte[]配列をFileに保存
- Java - byte[]の配列をStringに変換
- Java - ファイルのアクセス権を確認し、変更
- Java - 一時フォルダ(Temp directory)パスを取得する
- Javaでシェルスクリプトを実行
- Java - Streamを配列に変換する
- Java - リスト重複排除、2つの方法