Perché i metodi statici possono utilizzare solo dati statici?

37

Non capisco perché un metodo statico non possa utilizzare dati non statici. Qualcuno può spiegare quali sono i problemi e perché non possiamo farlo?

    
posta JAVA 11.09.2013 - 15:43
fonte

8 risposte

71

Nella maggior parte dei linguaggi OO, quando definisci un metodo all'interno di una classe, diventa un Metodo di istanza . Quando crei una nuova istanza di quella classe, tramite la parola chiave new , inizializzi un nuovo set di dati univoco solo per quell'istanza. I metodi appartenenti a quell'istanza possono quindi lavorare con i dati definiti su di esso.

I metodi statici , al contrario, ignorano le singole istanze di classe. Il metodo statico è simile a una funzione libera in C o C ++. Non è legato a un'istanza specifica della classe. Questo è il motivo per cui non possono accedere ai valori di istanza. Non c'è un'istanza da cui prendere un valore!

Dati statici è simile a un metodo statico. Un valore dichiarato static non ha un'istanza associata. Esiste per l'istanza ogni e viene dichiarata solo in un singolo punto in memoria. Se viene mai cambiato, cambierà per ogni istanza di quella classe.

Un metodo statico può accedere a Dati statici perché esistono entrambi indipendentemente da istanze specifiche di una classe.

Potrebbe aiutare a vedere come si invoca un metodo statico, rispetto a un metodo di istanza. Diciamo che avevamo la seguente classe (usando pseudocodice simile a Java):

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)

Aggiornamento

Come indica COME FROM nei commenti, un metodo statico è in grado di lavorare con dati non statici, ma deve essere passato esplicitamente. Supponiamo che la classe Foo abbia un altro metodo:

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

Add è ancora statico e non ha alcuna istanza di value , ma essendo un membro della classe Foo può accedere ai campi private value del passato foo1 e foo2 le istanze. In questo caso, lo stiamo utilizzando per restituire un nuovo Foo con i valori aggiunti di entrambi i valori passati.

Foo foo3 = Foo.Add(foo1, foo2); // creates a new Foo with a value of 30
    
risposta data 11.09.2013 - 16:04
fonte
22

Lo spieghiamo con un campione ipotetico.

Immagina una classe semplice:

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

Ora creiamo 2 istanze di questa classe:

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

ora, pensa: cosa succede se aggiungiamo un nuovo metodo statico all'Utente, ad esempio:

static string GetName();

e lo chiami:

string x = User::GetName()

cosa dovrebbe contenere x? "Jim", "Bones" o qualcos'altro?

Il problema è che un metodo statico è un singolo metodo, definito sulla classe, non sugli oggetti. Di conseguenza, non si sa a quale oggetto si possa applicare. Questo è il motivo per cui è una cosa speciale. È meglio pensare a metodi statici come cose singole, come le funzioni in C, ad esempio. Che i linguaggi come Java li abbiano contenuti all'interno delle classi è principalmente un problema con Java che non permette che nulla esista al di fuori di una classe, quindi funzioni come questa devono essere forzate all'interno di una classe in qualche modo (un po 'come come main () è forzato ad essere anche all'interno di una classe quando tutto il senso dice che dovrebbe essere una funzione singolare, autonoma).

    
risposta data 11.09.2013 - 16:08
fonte
2

I dati non statici sono associati a un'istanza della classe. I metodi statici (e i dati) non sono associati a una particolare istanza della classe. Non è necessario essere un'istanza di una classe per utilizzare metodi statici su di essa. Anche se ci fossero istanze, non ci sarebbe alcun modo per Java di garantire che si stia operando sull'istanza che si aspetta quando si chiama un metodo statico. Pertanto, i metodi statici non possono avere accesso a dati non statici.

    
risposta data 11.09.2013 - 15:57
fonte
2

Può utilizzare i dati di campo; considera il seguente codice java:

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";
    }
}
    
risposta data 11.09.2013 - 16:03
fonte
2

Penso che il problema qui sia di comprensione.

Da un punto di vista tecnico un metodo statico chiamato da un oggetto sarebbe abbastanza in grado di vedere i campi di istanza. Sospetto strongmente che questo sia ciò che ha causato la domanda in primo luogo.

Il problema è che i metodi possono essere chiamati dall'esterno dell'oggetto. A quel punto non ci sono dati di istanza per fornirli, e quindi nessun modo per il compilatore di risolvere il codice. Dal momento che consentire dati di istanza ha causato una contraddizione non dobbiamo consentire dati di istanza.

    
risposta data 02.05.2014 - 23:00
fonte
1

Consideralo come un metodo statico che vive in una dimensione non orientata agli oggetti.

Nella "dimensione orientata agli oggetti" una classe può generare multipli ego (istanze), ogni ego ha coscienza di sé attraverso il suo stato.

Nella dimensione piatta, non OO, una classe è ignara del proprio ego che vive nella dimensione OO. Il loro mondo è piatto e procedurale, quasi come se l'OOP non fosse ancora stato inventato, e come se la classe fosse un piccolo programma procedurale, ei dati statici erano solo variabili globali.

    
risposta data 11.09.2013 - 17:01
fonte
1

Penso che il modo più semplice per spiegarlo sia guardare un codice e poi considerare quali risultati ci si aspetterebbe che il codice producesse.

// 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.  

Per completezza ecco la classe dell'auto:

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

}
    
risposta data 12.09.2013 - 00:30
fonte
1

Le altre risposte praticamente dicono tutto, tuttavia, ci sono alcuni "dettagli" che vorrei aggiungere.

I metodi statici (ad esempio quelli in Java) non hanno un oggetto implicito ad essi associato (accessibile attraverso this ) di cui puoi accedere direttamente ai membri in base al nome.

Questo non significa che non possano accedere ai dati non statici. %pr_e%

So che questo è solo un dettaglio, ma ho trovato la tua domanda strana quando l'ho letto. "Può utilizzare solo dati statici" è troppo restrittivo.

A proposito, non ho testato il codice, l'ho appena scritto qui per esemplificare quello che stavo dicendo.

    
risposta data 12.09.2013 - 22:27
fonte

Leggi altre domande sui tag