web-dev-qa-db-ja.com

「非静的メソッドは静的コンテンツから参照できない」の背後にある理由は何ですか?

非常に一般的な初心者の間違いは、そのクラスのインスタンスを作らずに「静的に」クラスプロパティを使用しようとしたときです。上記のエラーメッセージが表示されます。

非静的メソッドを静的にするか、そのクラスのインスタンスにそのプロパティを使用させることができます。

どうしてですか?私は解決策を求めていません。その理由が何であるかを知っていただければ幸いです。非常に根本的な理由!

private Java.util.List<String> someMethod(){
    /* Some Code */
    return someList;            
}

public static void main(String[] strArgs){          
     // The following statement causes the error. You know why..
    Java.util.List<String> someList = someMethod();         
}
231
DragonBorn

存在しないものを呼び出すことはできません。オブジェクトを作成していないので、非静的メソッドはまだ存在しません。静的メソッド(定義上)は常に存在します。

328
Brian Knoblauch

あなたが呼び出そうとしているメソッドはインスタンスレベルのメソッドです。あなたはインスタンスを持っていません。

staticメソッドはクラスに属し、非staticメソッドはクラスのインスタンスに属します。

53
Steven A. Lowe

オブジェクト指向プログラミングの本質は、それが操作するデータとともにロジックをカプセル化することです。

インスタンスメソッドはロジック、インスタンスフィールドはデータです。一緒に、彼らはオブジェクトを形成します。

public class Foo
{
    private String foo;
    public Foo(String foo){ this.foo = foo; }
    public getFoo(){ return this.foo; }

    public static void main(String[] args){
        System.out.println( getFoo() );
    }
}

上記のプログラムを実行した結果、どうなるのでしょうか。

オブジェクトがなければ、インスタンスデータはありません。インスタンスメソッドはクラス定義の一部として存在しますが、それらにデータを提供するにはオブジェクトインスタンスが必要です。

理論的には、インスタンスデータにアクセスしないインスタンスメソッドは、静的なコンテキストで動作する可能性がありますが、インスタンスメソッドになる理由はまったくありません。それを禁止する追加の規則を作るのではなく、とにかく許可するのが言語設計の決定です。

22

私はただ気づいた、私は人々が非常に早い段階で「静的」の概念にさらされるべきではないと思う。

静的メソッドはおそらく標準よりもむしろ例外であるべきです。あなたがOOPを学びたいのであれば特にとにかく早く。 (規則の例外から始めるのはなぜですか?)それがJavaの非常に反教育的です、あなたが学ぶべきである「最初の」事はpublicstaticvoid主なものです。 (とにかく、独自の主なメソッドを持つ実際のJavaアプリケーションはほとんどありません。)

12
Hugo

私は、Java言語の規則により、Javaコンパイラが「これ」と同等のものを挿入することを指摘する価値があると思います。明示的なインスタンスなしでインスタンスメソッドまたはインスタンスフィールドにアクセスしていることに気付いたとき。もちろん、静的メソッドではできないように、 "this"変数を持つインスタンスメソッド内からしか実行できないことをコンパイラは認識しています。

つまり、インスタンスメソッドを使っているときは、次のようになります。

instanceMethod();
this.instanceMethod();

そしてこれらも同等です:

... = instanceField;
... = this.instanceField;

コンパイラは事実上「this」を挿入しています。特定のインスタンスを指定しないと.

これは、インスタンス呼び出しと静的呼び出しが同じ構文を持っているように見えることがある一方で、実際には異なるタイプの呼び出しと基本的なメカニズムであることを意味します。

インスタンスメソッド呼び出しは、多態性をサポートする仮想メソッドの動作により、メソッド呼び出しまたはディスパッチと呼ばれることがあります。明示的なオブジェクトインスタンスを使用するように記述したか、コンパイラが「this」を挿入したかに関係なく、ディスパッチ動作は発生します。

OOP以外の言語での関数呼び出しのように、静的メソッド呼び出しメカニズムはより単純です。

個人的には、エラーメッセージは誤解を招く可能性があると思います。「非静的メソッドは静的コンテキストから参照できません明示的なオブジェクトインスタンスを指定せずに」と読むことができます。


コンパイラが不平を言っているのは、標準の "this"を単純に挿入できないことです。このメソッドは静的メソッド内にあるため、インスタンスメソッド内と同じです。ただし、作成者がこの呼び出しの対象となるインスタンスを提供するのを忘れただけかもしれません。たとえば、静的メソッドにパラメータとして提供されるインスタンス、またはこの静的メソッド内で作成されるインスタンスなどです。

つまり、最も確実に静的メソッド内からインスタンスメソッドを呼び出すことができます。呼び出しのために明示的なインスタンスオブジェクトを用意して指定するだけです。

11
Erik Eidt

答えはこれまでのところ説明しています、しかしここにあなたが考慮したいと思うかもしれない他の何かがあります:

あなたはそのコンストラクタにメソッド呼び出しを追加することによってインスタンス化可能なクラスからメソッドを呼び出すことができます。

Object instance = new Constuctor().methodCall();

または

primitive name = new Constuctor().methodCall();

これは、インスタンス化可能なクラスのメソッドを単一のスコープ内で1回だけ使用したい場合に便利です。単一のスコープ内のインスタンス化可能クラスから複数のメソッドを呼び出す場合は、必ず参照可能なインスタンスを作成してください。

6
Ande TURNER

静的コンテキストからインスタンスメソッドにアクセスしようとすると、コンパイラはあなたが参照しているインスタンスメソッド(どのオブジェクトの変数)を推測することができません。ただし、オブジェクト参照を使用していつでもアクセスできます。

3
Vivek Vermani

コンパイラは実際には非静的メソッドに引数を追加します。オブジェクトがないため、this pointer/reference. This is also the reason why a static method can not use thisが追加されます。

2
antiparagon

静的メソッドはアクションをあるタイプのオブジェクトに関連付けますが、非静的メソッドはアクションをそのタイプのオブジェクトのインスタンスに関連付けます。通常はインスタンスとの関係で何かをするメソッドです。

例:

クラスCarには特定の車を洗うことを示す洗浄方法があるかもしれませんが、静的方法はタイプカーに適用されます。

1
Robin

メソッドが静的でない場合は、そのメソッドがクラス内のインスタンスレベルのデータにアクセスする必要があることをコンパイラに「伝えます」(非静的フィールドのように)。このデータは、クラスのインスタンスが作成されていない限り利用できません。そのため、静的メソッドからメソッドを呼び出そうとすると、コンパイラはエラーをスローします。実際にメソッドがクラスの非静的メンバを参照していない場合は、メソッドを静的にします。

たとえば、Resharperでは、クラスの静的メンバーを参照しない非静的メソッドを作成するだけで、「このメソッドを静的にすることができます」という警告メッセージが表示されます。

1
Charles Bretana

それで、あなたは非常に根本的な理由を求めていますか?

Javaで開発しているので、コンパイラはJava仮想マシンが解釈できるオブジェクトコードを生成します。とにかくJVMは、機械語で動くバイナリプログラムです(おそらくあなたのオペレーティングシステムとハードウェアに固有のJVMのバージョンは、あなたのプロセッサで動くことができる機械コードを得るためにCのような別のプログラミング言語によって以前にコンパイルされた)最後に、すべてのコードはマシンコードに変換されます。したがって、オブジェクト(クラスのインスタンス)を作成することは、メモリ空間(オペレーティングシステムのCPUスケジューラがプログラムを実行するためにプログラムをキューの先頭に置くときにプロセッサレジスタになるメモリレジスタ)を予約することと同じです。データを読み書きできるデータ格納場所を持つこと。クラスのインスタンスがない場合(静的なコンテキストで発生します)、データを読み書きするためのメモリスペースはありません。実際、他の人が言ったように、データは存在しません(最初から書き込んだことも、データを保存するためのメモリスペースを予約することもなかったため)。

私の英語ですみません。私はラテンだ!

0

その背後にある単純な理由は、親クラスの静的データメンバーはアクセス可能だが(オーバーライドされていない場合のみ)、例えば(静的でない)データメンバーやメソッドには参照が必要で、オブジェクトを通してしか呼び出せないためです。 。

0
Vipul

非静的メソッドはオブジェクトに依存しています。オブジェクトが作成されると、プログラムによって認識されます。

静的メソッドは、オブジェクトを作成する前でも呼び出すことができます。静的メソッドは、実際に作業する予定のオブジェクトに依存しない比較や操作を実行するのに最適です。

0
Ejesalva