it-swarm.com.de

Warum können statische Methoden nur statische Daten verwenden?

Ich verstehe nicht, warum eine statische Methode keine nicht statischen Daten verwenden kann. Kann jemand erklären, was die Probleme sind und warum wir es nicht können?

38
JAVA

In den meisten OO Sprachen) wird eine Methode innerhalb einer Klasse zu einer Instanzmethode. Wenn Sie eine neue erstellen Instanz dieser Klasse initialisieren Sie über das Schlüsselwort new einen neuen Datensatz, der nur für diese Instanz eindeutig ist. Die zu dieser Instanz gehörenden Methoden können dann mit den von Ihnen verwendeten Daten arbeiten darauf definiert.

Statische Methoden kennen dagegen einzelne Klasseninstanzen nicht. Die statische Methode ähnelt einer freien Funktion in C oder C++. Es ist nicht an eine bestimmte Instanziierung der Klasse gebunden. Aus diesem Grund können sie nicht auf Instanzwerte zugreifen. Es gibt keine Instanz, von der man einen Wert nehmen kann!

Statische Daten ähnelt einer statischen Methode. Einem Wert, der als static deklariert ist, ist keine Instanz zugeordnet. Es existiert für jede Instanz und wird nur an einer einzigen Stelle im Speicher deklariert. Wenn es jemals geändert wird, ändert es sich für jede Instanz dieser Klasse.

Eine statische Methode kann auf statische Daten zugreifen, da beide unabhängig von bestimmten Instanzen einer Klasse existieren.

Es kann hilfreich sein zu sehen, wie Sie eine statische Methode im Vergleich zu einer Instanzmethode aufrufen. Angenommen, wir hatten die folgende Klasse (mit Java-ähnlichem Pseudocode):

class Foo {
    // This static value belongs to the class Foo
    public static final string name = "Foo";

    // This non-static value will be unique for every instance
    private int value;

    public Foo(int value) {
         this.value = value;
    }

    public void sayValue() {
        println("Instance Value: " + value);
    }

    public static void sayName() {
        println("Static Value: " + name);
    }
}

Foo foo1 = new Foo(10);
Foo foo2 = new Foo(20);

foo1.sayValue(); // Prints "Instance Value: 10" - called on foo1
foo2.sayValue(); // Prints "Instance Value: 20" - called on foo2

Foo.sayName(); // Prints "Static Value: Foo" - called on Foo (not foo1 or foo2)

Aktualisieren

Wie COME FROM in den Kommentaren hervorhebt, kann eine statische Methode mit nicht statischen Daten arbeiten, muss es aber explizit übergeben werden. Nehmen wir an, die Klasse Foo hatte eine andere Methode:

public static Foo Add(Foo foo1, Foo foo2) {
    return new Foo(foo1.value + foo2.value);
}

Add ist immer noch statisch und hat keine eigenen value Instanzen, aber als Mitglied der Klasse Foo kann es auf die privaten value Felder des übergebenen foo1 zugreifen und foo2 Instanzen. In diesem Fall verwenden wir es, um ein neues Foo mit den zusätzlichen Werten beider übergebenen Werte zurückzugeben.

Foo foo3 = Foo.Add(foo1, foo2); // creates a new Foo with a value of 30
73
KChaloux

Erklären wir es mit einer hypothetischen Stichprobe.

Stellen Sie sich eine einfache Klasse vor:

class User
{
User(string n) { name = n; };
string name;
}

Jetzt erstellen wir 2 Instanzen dieser Klasse:

User Bones = new User("Bones");
User Jim = new User("Jim");

denken Sie jetzt darüber nach - was ist, wenn wir dem Benutzer eine neue statische Methode hinzufügen, z.

static string GetName();

und du nennst es:

string x = User::GetName()

was würde x enthalten? "Jim", "Bones" oder etwas anderes?

Das Problem ist, dass eine statische Methode eine einzelne Methode ist, die für die Klasse definiert ist, nicht für die Objekte. Infolgedessen wissen Sie nicht, auf welches Objekt es angewendet werden könnte. Deshalb ist es etwas Besonderes. Es ist am besten, sich statische Methoden als einzelne Dinge vorzustellen, wie zum Beispiel Funktionen in C. Dass Sprachen wie Java sie in Klassen enthalten haben) ist hauptsächlich ein Problem mit Java lässt nicht zu, dass etwas außerhalb einer Klasse existiert, daher müssen Funktionen wie diese erzwungen werden in irgendeiner Weise in einer Klasse (ein bisschen wie main () gezwungen ist, auch in einer Klasse zu sein, wenn jeder Sinn sagt, dass es eine singuläre, eigenständige Funktion sein sollte).

22
gbjbaanb

Es kann Felddaten verwenden; Betrachten Sie den folgenden Java Code:

class MyBean {
    private String myString;

    static void myStaticMethod() {
        myString = "tada";/*not allowed; if this was possible how would 
                           be different from a field without static?*/

        MyBean myBean = new MyBean();//allowed if associated with an instance
        myBean.myString = "tada";
    }
}
3
m3th0dman

Ich denke, hier geht es um Verständnis.

Aus technischer Sicht wäre eine statische Methode, die aus einem Objekt heraus aufgerufen wird, durchaus in der Lage, die Instanzfelder zu sehen. Ich vermute sehr, dass dies die Frage überhaupt erst verursacht hat.

Das Problem ist, dass Methoden von außerhalb des Objekts aufgerufen werden können. Zu diesem Zeitpunkt gibt es keine Instanzdaten, um sie bereitzustellen - und somit keine Möglichkeit für den Compiler, den Code aufzulösen. Da das Zulassen von Instanzdaten einen Widerspruch verursacht hat, dürfen wir keine Instanzdaten zulassen.

2
Loren Pechtel

Nicht statische Daten sind einer Instanz der Klasse zugeordnet. Statische Methoden (und Daten) sind keiner bestimmten Instanz der Klasse zugeordnet. Es muss keine Instanz einer Klasse vorhanden sein, um statische Methoden verwenden zu können. Selbst wenn es Instanzen gäbe, könnte Java) nicht garantieren, dass Sie mit der Instanz arbeiten, die Sie beim Aufrufen einer statischen Methode erwarten. Daher können statische Methoden keine haben Zugriff auf nicht statische Daten.

2
smp7d

Ich denke, der einfachste Weg, dies zu erklären, besteht darin, sich einen Code anzusehen und dann zu überlegen, welche Ergebnisse der Code erwarten würde.

// Create three new cars.  Cars have a name attribute.  
Car car1 = new Car("Mazda3");
Car car2 = new Car("FordFocus");
Car car3 = new Car("HondaFit");

// Now we would like to print the names of some cars: 
// First off why don't we try this: 

Car.printCarName();

// Expected behaviour: 
// If we think about what we are trying to do here it doesn't
// really make sense.  What instance of car name should this 
// print?  Should it print Mazda3?  FordFoucs?
// What is the expected behaviour?  If we are going to have a
// static call on car call printCarName it should probably do
// something like print all car names or a random car name or
// throw an error.  


//Now lets try this instead: 

Car.printCarName(car1);

// Expected Behaviour: 
// Luckily the expected behaviour is very clear here.  This
// should print Mazda3.  This works as expected.  


// Finally lets try this: 

car1.printMyName();

// Expected Behaviour:
// Same as previous example, however this is the *right* way
// to do it.  

Der Vollständigkeit halber hier die Fahrzeugklasse:

public class Car{

    public String name;

    public Car(String name){
        this.name = name;
    }

    public static printCarName(){
        print "Not sure what to do here...  Don't know which car you are talking about.";
    }

    public static printCarName(Car c){
        print c.name;
    }

    public /*NOT static*/ printMyName(){
        print this.name;
    }

}
1

Die anderen Antworten sagen so ziemlich alles, es gibt jedoch einige "Details", die ich hinzufügen möchte.

Statischen Methoden (z. B. in Java) ist nur kein implizites Objekt zugeordnet (Zugriff über this), auf dessen Mitglieder Sie normalerweise direkt über den Namen zugreifen können.

Das bedeutet nicht, dass sie nicht auf nicht statische Daten zugreifen können.

class MyClass {
  public static void foo(MyOtherClass object) {
    System.out.println(object.member);
  }
}
class MyOtherClass { public int member = 10; }

Ich weiß, dass dies nur ein Detail ist, aber ich fand Ihre Frage seltsam, als ich sie las. "Kann nur statische Daten verwenden" ist zu restriktiv.

Ich habe den Code übrigens nicht getestet, sondern nur hier geschrieben, um zu veranschaulichen, was ich gesagt habe.

Stellen Sie sich das als statische Methoden vor, die in einer nicht objektorientierten Dimension leben.

In der "objektorientierten Dimension" kann eine Klasse mehrere Egos (Instanzen) hervorbringen, jedes Ego hat über seinen Zustand ein Gewissen von sich.

In der flachen Nicht-OO-Dimension ist sich eine Klasse ihres in der OO-Dimension lebenden Egos nicht bewusst. Ihre Welt ist flach und prozedural, fast so, als ob OOP noch nicht erfunden worden wäre) und als ob die Klasse ein kleines prozedurales Programm wäre und die statischen Daten nur globale Variablen wären.

1