326

非常によくある初心者の間違いは、そのクラスのインスタンスを作成せずにクラス プロパティを「静的に」使用しようとする場合です。上記のエラーメッセージが表示されます:

非静的メソッドを静的にするか、そのクラスのインスタンスを作成してそのプロパティを使用できます。

この背後にある理由は何ですか?解決策ではなく、理由に関心があります。

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

public static void main(String[] strArgs){          
     // The following statement causes the error. 
    java.util.List<String> someList = someMethod();         
}
4

13 に答える 13

443

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

于 2008-11-14T18:10:50.620 に答える
86

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

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

于 2008-11-14T18:04:17.810 に答える
32

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

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

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() );
    }
}

上記のプログラムを実行すると、どのような結果になる可能性がありますか?

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

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

于 2009-07-16T21:30:10.103 に答える
15

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

つまり、インスタンス メソッドにいる場合、以下は同等です。

instanceMethod();
this.instanceMethod();

これらも同等です。

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

コンパイラは効果的に「this」を挿入しています。特定のインスタンスを指定しない場合。

コンパイラによるこの (しゃれを意図した) ちょっとした「魔法の助け」は、初心者を混乱させる可能性があります。これは、インスタンス呼び出しと静的呼び出しが同じ構文を持っているように見えることがありますが、実際には異なる型と基礎となるメカニズムの呼び出しであることを意味します。

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

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

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


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

要するに、静的メソッド内からインスタンス メソッドを呼び出すことができるのはほぼ間違いありません。呼び出し用の明示的なインスタンス オブジェクトを用意して指定するだけで済みます。

于 2012-07-15T19:20:31.090 に答える
15

私は、人々が「静的」の概念に非常に早くさらされるべきではないと思うことに気付きました。

静的メソッドは、おそらく標準ではなく例外であるべきです。OOP を学びたい場合は特に早い段階で。(ルールの例外から始めるのはなぜですか?) これは、Java の教育に反するものです。「最初に」学ぶべきことは public static void main です。(いずれにせよ、独自の main メソッドを持つ実際の Java アプリケーションはほとんどありません。)

于 2008-11-15T07:28:36.610 に答える
8

これまでの回答はその理由を説明していますが、ここで検討したいことがあります。

コンストラクターにメソッド呼び出しを追加することにより、インスタンス化可能なクラスからメソッドを呼び出すことができます。

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

また

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

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

于 2008-11-15T07:18:41.420 に答える
5

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

于 2014-06-05T20:46:19.207 に答える
3

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

元:

クラス Car には、特定の車を洗うことを示すウォッシュ メソッドがある場合がありますが、静的メソッドはタイプ car に適用されます。

于 2008-11-14T18:11:16.470 に答える
3

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

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

于 2008-11-14T18:11:50.290 に答える
3

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

于 2009-04-07T14:09:24.790 に答える
2

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

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

私の英語でごめんなさい!私はラテン語です!

于 2014-08-20T21:48:24.430 に答える
1

この背後にある単純な理由は、親クラスの静的データ メンバーにアクセスできる (オーバーライドされていない場合のみ) が、インスタンス (非静的) データ メンバーまたはメソッドの参照が必要なため、オブジェクトを介してのみ呼び出すことができるためです。 .

于 2011-07-05T14:23:05.647 に答える
1

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

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

于 2014-09-13T15:10:07.890 に答える