Impossibile fare un riferimento statico al metodo non statico


102

Creazione di un'applicazione multilingue in Java. Ricezione di un errore durante l'inserimento del valore String dal R.stringfile XML della risorsa:

public static final String TTT =  (String) getText(R.string.TTT);

Questo è il messaggio di errore:

Errore: impossibile fare un riferimento statico al metodo non statico getText (int) dal tipo Context

Come è causato e come posso risolverlo?


1
Perché è necessario che sia statico per una "applicazione multilingue"? Non capisco davvero.
xil3

3
Non archiviare mai risorse stringa in membri dati statici. Richiedili sempre tramite getString()quando ne hai bisogno. In questo modo, l'applicazione si adatta correttamente agli utenti che cambiano la lingua scelta.
CommonsWare

Risposte:


143

Poiché getText()non è statico, non puoi chiamarlo da un metodo statico.

Per capire perché, devi capire la differenza tra i due.

I metodi di istanza (non statici) funzionano su oggetti di un tipo particolare (la classe). Questi vengono creati con il nuovo in questo modo:

SomeClass myObject = new SomeClass();

Per chiamare un metodo di istanza, chiamalo su instance ( myObject):

myObject.getText(...)

Tuttavia un metodo / campo statico può essere chiamato direttamente solo sul tipo, ad esempio in questo modo: L'istruzione precedente non è corretta. Si può anche fare riferimento a campi statici con un riferimento a un oggetto come, myObject.staticMethod() ma questo è sconsigliato perché non chiarisce che si tratta di variabili di classe.

... = SomeClass.final

E i due non possono lavorare insieme poiché operano su spazi dati diversi (dati di istanza e dati di classe)

Fammi provare a spiegare. Considera questa classe (psuedocode):

class Test {
     string somedata = "99";
     string getText() { return somedata; } 
     static string TTT = "0";
}

Ora ho il seguente caso d'uso:

Test item1 = new Test();
 item1.somedata = "200";

 Test item2 = new Test();

 Test.TTT = "1";

Quali sono i valori?

Bene

in item1 TTT = 1 and somedata = 200
in item2 TTT = 1 and somedata = 99

In altre parole, TTTè un dato condiviso da tutte le istanze del tipo. Quindi non ha senso dirlo

class Test {
         string somedata = "99";
         string getText() { return somedata; } 
  static string TTT = getText(); // error there is is no somedata at this point 
}

Quindi la domanda è: perché TTT è statico o perché getText () non è statico?

Rimuovi il statice dovrebbe superare questo errore, ma senza capire cosa fa il tuo tipo è solo un cerotto fino all'errore successivo. Quali sono i requisiti getText()che richiedono che sia non statico?


è statico perché lo chiamo da diversi file nel mio progetto. quando ho rimosso la "statica" il codice di errore è sparito, ma ora ho molti errori in altri file che utilizzano questa variabile.
Chen M

Ma questo è il mio punto. Devi capire quando i due possono essere usati.
Preet Sangha

quando aggiungo la riga "Constants notification_values ​​= new Constants (); alla mia classe di attività principale, si compila bene ma nell'emulatore si arresta in modo anomalo quando questa attività viene eseguita
Chen M

12

Ci sono già alcune buone risposte con spiegazioni sul motivo per cui la miscela del Contextmetodo non statico getText()non può essere utilizzata con il tuo static final String.

Una buona domanda da porsi è: perché vuoi farlo? Stai tentando di caricare un Stringdalla tua stringsrisorsa e popolare il suo valore in un public staticcampo. Presumo che questo sia così che alcune delle tue altre classi possano accedervi? Se è così, non è necessario farlo. Invece passa a Contextnelle tue altre classi e chiama context.getText(R.string.TTT)da dentro di loro.

public class NonActivity {

    public static void doStuff(Context context) {
        String TTT = context.getText(R.string.TTT);
        ...
    }
}

E per chiamarlo dal tuo Activity:

NonActivity.doStuff(this);

Ciò ti consentirà di accedere alla tua Stringrisorsa senza dover utilizzare un public staticcampo.


1
grazie mille, ho cambiato tutti i file secondo la tua raccomandazione.
Chen M

Stavo cercando di farlo, ma per un array di stringhe e con String a[] = context.getTextArray(R.array.myStringArray); ; tuttavia, mi dà un errore The method getTextArray(int) is undefined for the type Context- perché dovrebbe essere indefinito mentre funziona con getText?
buon auspicio

1
@ auspicious99 semplicemente perché a Contextnon ha un metodo chiamato getTextArray, ma lo ha getText. Forse stai pensando a Resourcesquale hagetTextArray
dave.c

Ah, grazie! Passato in una risorsa anziché in un contesto (dall'attività alla non attività) e il mio getStringArray ha funzionato.
buon auspicio99

9

per altri che lo trovano nella ricerca:

Spesso ottengo questo quando chiamo accidentalmente una funzione utilizzando il nome della classe anziché il nome dell'oggetto. Questo in genere accade perché assegno loro nomi troppo simili: P

vale a dire:

MyClass myclass = new MyClass();

// then later

MyClass.someFunction();

Questo è ovviamente un metodo statico. (buono per qualcosa) Ma quello che volevo davvero fare (nella maggior parte dei casi era)

myclass.someFunction();

È un errore così stupido, ma ogni due mesi, spreco circa 30 minuti a fare confusione con le variabili nelle definizioni "MyClass" per capire cosa sto facendo di sbagliato quando in realtà, è solo un errore di battitura.

Nota divertente: lo stack overflow evidenzia la sintassi per rendere l'errore davvero ovvio qui.


Il tuo IDE non evidenzia anche questo? Immagino che tu possa configurarlo per farlo :)
Matthias Meid

2

Puoi rendere la tua variabile non statica

public final String TTT =  (String) getText(R.string.TTT);

o rendere statico il metodo "getText" (se possibile)


2

getText è un membro della tua attività quindi deve essere chiamato quando "this" esiste. La variabile statica viene inizializzata quando la classe viene caricata prima della creazione dell'attività.

Poiché si desidera che la variabile venga inizializzata da una stringa di risorse, non può essere statica. Se vuoi che sia statico puoi inizializzarlo con il valore String.


2

Non è possibile fare riferimento a variabili statiche da un metodo non statico. Per capirlo, è necessario comprendere la differenza tra statico e non statico.

Le variabili statiche sono variabili di classe, appartengono alla classe con la loro unica istanza, creata solo alla prima. Le variabili non statiche vengono inizializzate ogni volta che si crea un oggetto della classe.

Ora venendo alla tua domanda, quando usi l'operatore new () creeremo una copia di ogni file non statico per ogni oggetto, ma non è il caso dei campi statici. Ecco perché dà un errore in fase di compilazione se si fa riferimento a una variabile statica da un metodo non statico.


0

Questa domanda non è nuova e le risposte esistenti forniscono un buon background teorico. Voglio solo aggiungere una risposta più pragmatica.

getText è un metodo della classe astratta Context e per chiamarlo, è necessaria un'istanza della sua sottoclasse (Activity, Service, Application o altro). Il problema è che le variabili finali statiche pubbliche vengono inizializzate prima che venga creata qualsiasi istanza di Context.

Esistono diversi modi per risolvere questo problema:

  1. Rendi la variabile una variabile membro (campo) dell'Attività o di un'altra sottoclasse di Context rimuovendo il modificatore statico e inserendolo nel corpo della classe;
  2. Mantenerlo statico e ritardare l'inizializzazione a un punto successivo (ad esempio nel metodo onCreate);
  3. Rendilo una variabile locale al posto dell'uso effettivo.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.