web-dev-qa-db-fra.com

Impossible de faire une référence statique à la méthode non statique

Construire une application multilingue en Java. Obtention d'une erreur lors de l'insertion de la valeur String à partir du fichier XML de ressource R.string:

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

C'est le message d'erreur:

Erreur: Impossible de faire une référence statique à la méthode non statique getText (int) à partir du type Le contexte

Comment cela est-il causé et comment puis-je le résoudre?

92
Chen M

Étant donné que getText() est non statique, vous ne pouvez pas l'appeler à partir d'une méthode statique.

Pour comprendre pourquoi, vous devez comprendre la différence entre les deux.

Les méthodes d'instance (non statiques) fonctionnent sur des objets d'un type particulier (la classe). Ceux-ci sont créés avec le nouveau comme ceci:

SomeClass myObject = new SomeClass();

Pour appeler une méthode d'instance, vous l'appelez sur l'instance (myObject):

myObject.getText(...)

Cependant, une méthode/un champ statique peut être appelé directement uniquement sur le type, par exemple:L'instruction précédente est incorrecte. On peut également faire référence à des champs statiques avec une référence d'objet telle quemyObject.staticMethod(), mais cela est déconseillé, car cela n'indique pas clairement qu'il s'agit de variables de classe. 

... = SomeClass.final

Et les deux ne peuvent pas fonctionner ensemble car ils opèrent sur des espaces de données différents (données d'instance et données de classe).

Laissez-moi essayer et expliquer. Considérons cette classe (psuedocode):

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

Maintenant, j'ai le cas d'utilisation suivant:

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

 Test item2 = new Test();

 Test.TTT = "1";

Quelles sont les valeurs?

Bien

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

En d'autres termes, TTT est une donnée partagée par toutes les instances du type. Donc, cela n'a aucun sens de dire 

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

Donc, la question est de savoir pourquoi TTT static ou pourquoi getText () n'est-il pas statique? 

Supprimez la static et vous devriez dépasser cette erreur - mais sans comprendre ce que votre type fait, il ne s'agit que d'un plâtre collant jusqu'à l'erreur suivante. Quelles sont les exigences de getText() qui exigent qu’elles soient non statiques?

136
Preet Sangha

Il existe déjà quelques bonnes réponses expliquant pourquoi le mélange de la méthode Context non statique getText() ne peut pas être utilisé avec votre static final String.

Une bonne question à poser est: pourquoi voulez-vous faire cela? Vous essayez de charger une String à partir de votre ressource strings et de renseigner sa valeur dans un champ public static. Je suppose que c'est pour que certaines de vos autres classes puissent y accéder? Si c'est le cas, il n'est pas nécessaire de le faire. Passez plutôt une Context dans vos autres classes et appelez context.getText(R.string.TTT) à partir de celles-ci.

public class NonActivity {

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

Et appeler ceci de votre Activity:

NonActivity.doStuff(this);

Cela vous permettra d'accéder à votre ressource String sans avoir à utiliser un champ public static.

11
dave.c

pour les autres qui trouvent cela dans la recherche:

Je reçois souvent celui-ci lorsque j'appelle accidentellement une fonction en utilisant le nom de la classe plutôt que le nom de l'objet. Cela se produit généralement parce que je leur donne des noms trop similaires: P

c'est à dire: 

MyClass myclass = new MyClass();

// then later

MyClass.someFunction();

Ceci est évidemment une méthode statique. (bon pour quelque chose) Mais ce que je voulais vraiment faire (était dans la plupart des cas)

myclass.someFunction();

C'est une erreur stupide, mais tous les deux mois, je perds environ 30 minutes à bricoler avec vars dans les définitions de "MyClass" pour déterminer ce qui ne va pas quand c'est vraiment une faute de frappe. 

Note amusante: le débordement de pile met en évidence la syntaxe pour rendre l'erreur vraiment évidente ici. 

8
SpiRail

Vous pouvez soit rendre votre variable non statique

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

ou rendre la méthode "getText" statique (si possible)

2
Kellindil

getText est un membre de votre activité, il doit donc être appelé lorsque "ceci" existe. Votre variable statique est initialisée lorsque votre classe est chargée avant la création de votre activité.

Puisque vous voulez que la variable soit initialisée à partir d'une chaîne de ressources, elle ne peut pas être statique. Si vous voulez qu'il soit statique, vous pouvez l'initialiser avec la valeur String.

2
Robby Pond

Vous ne pouvez pas faire référence à une variable statique à partir d'une méthode non statique ..__ Pour comprendre cela, vous devez comprendre la différence entre statique et non statique.

Les variables statiques sont des variables de classe, elles appartiennent à la classe avec leur seule instance, créée à la première .. .. uniquement. Les variables non statiques sont initialisées à chaque fois que vous créez un objet de la classe.

Pour en venir à votre question, lorsque vous utilisez l'opérateur new (), nous allons créer une copie de chaque fichier non statique pour chaque objet, mais ce n'est pas le cas pour les champs statiques. C'est pourquoi cela donne une erreur de compilation si vous référencez une variable statique à partir d'une méthode non statique.

1
Krishna

Cette question n'est pas nouvelle et les réponses existantes donnent un bon fond théorique. Je veux juste ajouter une réponse plus pragmatique. 

getText est une méthode de la classe abstraite Context et pour l'appeler, il faut une instance de sa sous-classe (Activity, Service, Application ou autre). Le problème est que les variables finales statiques publiques sont initialisées avant la création d'une instance de Context.

Il y a plusieurs façons de résoudre ce problème: 

  1. Faites de la variable un membre (champ) de l'activité ou de la sous-classe de Context en supprimant le modificateur static et en le plaçant dans le corps de la classe;
  2. Maintenez-le statique et retardez l'initialisation à un point ultérieur (par exemple, dans la méthode onCreate);
  3. Faites-en une variable locale à la place de l'utilisation réelle.
0
dev.bmax