Was ist der Fehler "nicht statische Methode" und wie funktioniert "dies"?

7

Ich habe ein paar EXTREM GRUNDLEGENDE Java-Fragen, die ich endlich ein für allemal verstehen möchte. Ich habe das folgende kurze Stück Code:

%Vor%

Wenn ich kompiliere, bekomme ich die gefürchtete "nicht-statische Methode swapMe (int, int) kann nicht von einem statischen Kontext verwiesen werden" -Fehler. Außerdem bekomme ich "a ist bereits in swapMe (int, int) definiert" und "b ist bereits in swapMe (int, int)" definiert

Was ich endlich durch meinen dicken Schädel bekommen muss, ist der Fehler "nicht statische Methode", wie (warum) er verursacht wird und wie man ihn vermeidet.

Außerdem ging ich davon aus, dass Sie mit meiner "a" - und "b" -Variablen in der "swapMe" -Methode tun können, was ich versuche zu tun. Ich dachte, ich könnte ein 'a' und 'b' übergeben, aber auch neue Variablen 'a' und 'b' erstellen und sie mit 'diesem' Schlüsselwort referenzieren.

Ich weiß, dass das extrem einfach ist, aber diese zwei "Probleme" sind zwei der Hauptprobleme, die ich bei Java habe und aus irgendeinem Grund nicht richtig lernen kann.

Danke euch allen, dass ihr euch die Zeit genommen habt, das zu lesen. Habt einen schönen Tag.

    
Brian 19.03.2012, 17:45
quelle

7 Antworten

11

Das bedeutet, dass die Methode swapMe() eine Instanz -Methode ist und Sie eine Instanz der Klasse VeryBasicJava benötigen, um sie wie folgt aufzurufen:

%Vor%

Alternativ können Sie swapMe() als static deklarieren. Auf diese Weise müssen Sie nicht zuerst eine Instanz erstellen:

%Vor%     
Óscar López 19.03.2012 17:46
quelle
5

Sie haben nur ein paar kleinere Probleme. Sie haben in einem Kommentar erwähnt, dass Sie etwas Erfahrung mit C haben, also werde ich versuchen, einige grundlegende Analogien zu zeichnen. Eine static -Methode (wie main ) verhält sich wie eine gewöhnliche C-Funktion. Eine nicht static Methode verwendet jedoch einen versteckten Parameter: this , der sich auf ein Objekt bezieht, auf dem diese Methode ausgeführt werden soll. Wenn Sie eine Methode wie diese schreiben:

%Vor%

Es bedeutet wirklich so etwas:

%Vor%

Da der Parameter this speziell behandelt wird, gibt es eine spezielle Syntax für den Aufruf von nicht static Methoden für Objekte:

%Vor%

Und weil swapMe nicht als static deklariert ist, erwartet es, wie oben genannt zu werden.

Die Tatsache, dass main in der Klasse VeryBasicJava deklariert ist, bedeutet nicht, dass Sie automatisch ein VeryBasicJava Objekt haben. Weil main static ist, ist es wie eine gewöhnliche C-Funktion:

%Vor%

Um eine Instanz eines Objekts zu erstellen, verwenden Sie new :

%Vor%

Dies ist analog zu malloc in C:

%Vor%

Mit einer Instanz können Sie eine Methode aufrufen:

%Vor%

Ihr anderes Problem ist zweifach: eins von scope und von members . Umfang bezieht sich, wie Sie vielleicht wissen, auf , wo eine Variable existiert. Nimm diese Funktion:

%Vor%

Wenn diese Methode aufgerufen wird, passiert Folgendes:

  1. a und b werden mit den im Aufruf von swapMe angegebenen Werten erstellt.

  2. Ein neues a wird erstellt, lokal für swapMe , mit dem Standardwert 0 . Dieser a verbirgt den Parameter a , und es gibt keine Möglichkeit, sie zu unterscheiden.

  3. Ein neues b wird erstellt, auch streng lokal. Es hat auch den Standardwert 0 und blendet den Parameter b aus.

  4. tmp wird erstellt und sein Wert wird auf den Wert des neu deklarierten a gesetzt, also auch 0 .

  5. [ siehe unten ]

  6. [ siehe unten ]

  7. Die Locals a und b existieren nicht mehr, ebenso die Parameter a und b .

In den Zeilen 5 und 6 versuchen Sie, mit der Syntax this.a auf den lokalen a anstatt auf den Parameter zu verweisen. Obwohl diese Syntax in Java existiert, macht sie nicht das, was Sie meinen. Parameter werden genau wie lokale Variablen behandelt. Daher unterscheidet this.a nicht zwischen diesen beiden Kategorien, sondern unterscheidet zwischen lokalen und Elementen . Nun, was sind Mitglieder? Nun, sagen Sie, Ihre Klassendeklaration enthält Variablendeklarationen:

%Vor%

Das ist wie bei den Member-Deklarationen in einem C struct :

%Vor%

Dies bedeutet, dass beim Erstellen einer Instanz von VeryBasicJava :

%Vor%

Diese Instanz hat ihre eigenen Variablen a und b , die in jeder nicht- static -Methode verwendet werden können:

%Vor%

Wenn Sie eine lokale Variable mit demselben Namen wie ein Mitglied haben, müssen Sie this verwenden, um explizit anzugeben, dass Sie auf das Mitglied verweisen möchten. Dieses vollständige Programm veranschaulicht, wie man Mitglieder und Einheimische erklärt, benutzt und unterscheidet.

%Vor%

Es wird diese Ausgabe erzeugen:

%Vor%

Ich hoffe, dass diese Beispiele und Erklärungen hilfreich sind.

    
Jon Purdy 19.03.2012 20:17
quelle
2

Ihre Probleme rühren daher, dass Sie nicht verstehen, wie das objektorientierte Paradigma funktioniert.

Die Idee ist, dass Sie eine Klasse definieren, die eine Art von Ding ist. Aus dieser Klasse erstellen Sie Instanzen, die effektiv Beispiele für diese Art von Dingen sind.

  

Wenn Sie beispielsweise eine Klasse "Wallet" erstellen, definiert dies, wie Sie   System behandelt Geldbörsen (d. h. was sie tun können und was Sie tun können   mit ihnen). Sie können jetzt mehrere verschiedene Instanzen erstellen   Geldbörsen, die unterschiedliche Werte speichern, aber immer noch auf die gleiche Weise funktionieren.   (Zum Beispiel "myWallet" und "yourWallet" sind beide Wallets, also können Sie nehmen   Geld aus und Geld in etc, aber wenn ich das Geld einchecke   DeinWallet, ich bekomme einen Wert von 50, wenn ich den Wert einchecke   myWallet, ich bekomme einen Wert von 20)

Nun gehören " statische " Methoden zur Klasse . Dies bedeutet, dass sie nicht auf Membervariablen zugreifen können, die für die Klasse spezifisch sind. Wenn ich zum Beispiel jeden Wallet in meinem System im Auge behalte, gehört dieser Wert keinem bestimmten Wallet in der Klasse, aber er ist immer noch mit dieser Klasse verbunden, also machen wir sie statisch.

  

Um mein Beispiel zu verwenden, wenn Sie zwei Objekte vom Typ "Brieftasche" und eins haben   hat seinen "Cash" Wert auf 30 gesetzt, und der andere hat seinen Geldwert gesetzt   Bei "25" kann eine statische Funktion nicht auf beide Werte zugreifen, was nicht möglich ist   Zugang entweder. Sie müssen eine bestimmte Brieftasche für den Zugriff geben.

Der Vorteil dieser Methode gegenüber dem Ansatz von C besteht darin, dass sie verwandte Funktionen miteinander verknüpft. Wenn Sie z. B. ein C-Array mit Ints sehen, wissen Sie nicht, was sie eigentlich darstellen sollen, und tun möglicherweise etwas Unerwartetes mit ihnen. Aber wenn ich Ihnen ein Java-Array von Brieftaschen gebe, erhalten Sie auch die Methoden, die beeinflussen, wie Sie mit ihnen interagieren. (Dies ist eine wirklich abgespeckte Erklärung von Kapselung )

Eines der Hauptprobleme von Java ist, dass es alles an eine Klasse bindet . Dies verursacht ein Problem für die Hauptmethode, die das Programm starten muss, da es noch keine Instanzen hat, aber immer noch Teil der Klasse sein muss. Daher muss die Hauptmethode immer statisch sein. Dies tendiert dazu, neue Programmierer zu verwirren, da das erste, was Sie innerhalb der Hauptmethode tun, immer eine Instanz der Klasse ist, die "innerhalb" ist.

In Ihrem Beispiel haben Sie keine "spezifischen" Daten. Alles ist in den Methoden enthalten, was bedeutet, dass Sie effektiv versuchen, prozeduralen Code in Java zu schreiben. Du kannst das tun (deklariere einfach alles statisch), aber die Sprache wird dich bekämpfen, und du wirst sehr schlechten Code schreiben.

Als ich ursprünglich mit Java anfing, behandelte ich die main () -Methode einer Klasse so, als wäre sie nicht Teil der Klasse. Konzeptionell hat es geholfen, weil Sie aufhören zu denken von dem nicht-statischen Zeug als etwas, das bereits da ist (was dein Hauptproblem ist). Aber meine Empfehlung an Sie ist Lesen Sie dies durch . Aber es gibt einige sehr gute Übergangskurse, um objektorientiertes Programmieren zu lernen, und Sie möchten vielleicht in diese investieren.

    
deworde 19.03.2012 21:13
quelle
1

Klassen sind eine Vorlage für OBJEKTE. Eine Instanz einer Klasse (d. H. Und eines Objekts) hat ihre eigene Version von Variablen und Methoden, die nicht statisch sind.

statische Methoden und Felder sind nicht an eine bestimmte Instanz einer Klasse gebunden .

Es macht also keinen Sinn, eine Klasseninstanzmethode von einer statischen Methode ohne die Instanz aufzurufen, auf der Sie die Methode aufrufen möchten. In Ihrem Beispiel ist this eine Referenz auf eine Instanz, aber Sie haben keine Instanz ....

    
hvgotcodes 19.03.2012 17:48
quelle
1

Für Ihre zweite Frage, wenn Sie eine Funktion erstellen, erstellt sie einen eigenen kleinen Stapel für alle ihre Variablen. Seine Argumente sind in diesem Stapel enthalten - Ihr Stack sieht also so aus:

%Vor%

Aus diesem Grund bekommen Sie ein Problem - das a und b deklarieren Sie, nachdem Ihre Argumente mit Ihren Argumenten in Konflikt geraten, nicht "this.a" und "this.b".

Ihre erste Frage wurde bereits beantwortet.

    
Marshall Conover 19.03.2012 17:49
quelle
1

Da das Update bereitgestellt wurde, möchte ich hinzufügen:

statische Methoden können nur andere statische Methoden aufrufen und greifen nur auf statische Variablen direkt zu (in Java).

Um nicht statische Methoden aufzurufen, müssen Sie eine Instanz dieser Klasse erstellen und die Methoden dann aufrufen.

    
P.P. 19.03.2012 18:08
quelle
0

swapMe benötigt eine Instanz von VeryBasicJava, um es aufzurufen. Statisch nicht.

Von außerhalb dieses Objekts können Sie aufrufen: VeryBasicJava.main (args).

Außerhalb des Objekts müssen Sie (new VeryBasicJava ()). swapMe (a, b) aufrufen, um diese Methode aufzurufen.

Der Grund dafür, dass Sie Fehler in swapMe bekommen, ist, dass Sie diese Variablen zweimal definieren. Die Signaturzeile hat sie in diesem Namensraum für Sie deklariert. In dieser Methode haben Sie bereits eine int a. Dann deklarieren Sie in der ersten Zeile wieder int.

Was Sie in Ihrem Swap tun möchten, ist etwa so:

%Vor%

Natürlich gibt es die Variablen a und b nur in dieser Methode. Sobald die Methode endet, geht Ihre Arbeit verloren. Wenn Sie es behalten möchten, machen Sie die Variable Klassenvariablen und stellen Sie Getter und Setter für sie bereit.

    
Raevik 19.03.2012 17:51
quelle