No se puede hacer una referencia estática al método no estático

102

Construyendo una aplicación multi-lenguaje en Java. Obteniendo un error al insertar un valor de cadena desde el R.stringarchivo XML de recursos:

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

Este es el mensaje de error:

Error: no se puede hacer una referencia estática al método no estático getText (int) desde el tipo Context

¿Cómo se produce esto y cómo puedo solucionarlo?

Chen M
fuente
1
¿Por qué necesita que sea estático para una 'aplicación multilingüe'? Realmente no lo entiendo.
xil3
3
Nunca almacene recursos de cadena en miembros de datos estáticos. Solicítelos siempre a través de getString()cuando los necesite. De esa manera, su aplicación se ajusta correctamente a los usuarios que cambian el idioma elegido.
CommonsWare

Respuestas:

143

Dado getText()que no es estático, no puede llamarlo desde un método estático.

Para entender por qué, debes entender la diferencia entre los dos.

Los métodos de instancia (no estáticos) funcionan en objetos que son de un tipo particular (la clase). Estos se crean con lo nuevo así:

SomeClass myObject = new SomeClass();

Para llamar a un método de instancia, lo llama en la instancia ( myObject):

myObject.getText(...)

Sin embargo, solo se puede llamar a un método / campo estático en el tipo directamente, digamos así: La declaración anterior no es correcta. También se puede hacer referencia a campos estáticos con una referencia de objeto como, myObject.staticMethod() pero esto no se recomienda porque no deja en claro que son variables de clase.

... = SomeClass.final

Y los dos no pueden trabajar juntos ya que operan en diferentes espacios de datos (datos de instancia y datos de clase)

Déjame intentar explicarte. Considere esta clase (psuedocode):

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

Ahora tengo el siguiente caso de uso:

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

 Test item2 = new Test();

 Test.TTT = "1";

¿Cuáles son los valores?

Bien

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

En otras palabras, TTTes un dato compartido por todas las instancias del tipo. Entonces no tiene sentido decir

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

Entonces, la pregunta es ¿por qué TTT es estático o por qué getText () no es estático?

Quite el staticy debería superar este error, pero sin entender qué hace su tipo, es solo un yeso pegajoso hasta el siguiente error. ¿Cuáles son los requisitos getText()que requieren que sea no estático?

Preet Sangha
fuente
es estático porque lo llamo desde varios archivos en mi proyecto. cuando eliminé la "estática", el código de error desapareció, pero ahora tengo muchos errores en otros archivos que usan esta variable.
Chen M
Pero ese es mi punto. Debe comprender cuándo se pueden usar los dos.
Preet Sangha
cuando agrego la línea "Constants Notifications_values ​​= new Constants (); a mi clase de actividad principal, se compila bien pero en el emulador se bloquea cuando se ejecuta esta actividad
Chen M
12

Ya hay algunas buenas respuestas con explicaciones de por qué la combinación del Contextmétodo getText()no estático no se puede usar con su static final String.

Una buena pregunta es: ¿por qué quieres hacer esto? Está intentando cargar un Stringdesde su stringsrecurso y completar su valor en un public staticcampo. Supongo que esto es para que algunas de sus otras clases puedan acceder a él. Si es así, no es necesario hacer esto. En su lugar, pase un Contexta sus otras clases y llame context.getText(R.string.TTT)desde dentro de ellas.

public class NonActivity {

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

Y para llamar a esto desde tu Activity:

NonActivity.doStuff(this);

Esto le permitirá acceder a su Stringrecurso sin necesidad de utilizar un public staticcampo.

dave.c
fuente
1
muchas gracias, cambié todos los archivos según su recomendación.
Chen M
Estaba tratando de hacer esto, pero para una matriz de cadenas, y con String a[] = context.getTextArray(R.array.myStringArray); ; sin embargo, me da un error The method getTextArray(int) is undefined for the type Context: ¿por qué estaría indefinido mientras funciona con getText?
auspicious99
1
@ auspicious99 simplemente porque a Contextno tiene un método llamado getTextArray, pero tiene getText. Quizás estés pensando en Resourcescuál tienegetTextArray
dave.c
¡Ah gracias! Pasé un recurso en lugar de un contexto (de la actividad a la no actividad) y mi getStringArray funcionó.
auspicious99
9

para otros que encuentran esto en la búsqueda:

A menudo obtengo este cuando llamo accidentalmente a una función usando el nombre de la clase en lugar del nombre del objeto. Esto suele suceder porque les doy nombres demasiado similares: P

es decir:

MyClass myclass = new MyClass();

// then later

MyClass.someFunction();

Obviamente, este es un método estático. (bueno para algunas cosas) Pero lo que realmente quería hacer (en la mayoría de los casos era)

myclass.someFunction();

Es un error tan tonto, pero cada dos meses, pierdo unos 30 minutos jugando con vars en las definiciones de "MyClass" para averiguar qué estoy haciendo mal cuando en realidad es solo un error tipográfico.

Nota divertida: el desbordamiento de pila resalta la sintaxis para que el error sea realmente obvio aquí.

SpiRail
fuente
¿Tu IDE no destaca esto también? Supongo que puedes configurarlo para hacerlo :)
Matthias Meid
2

Puede hacer que su variable no sea estática

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

o hacer que el método "getText" sea estático (si es posible)

Kellindil
fuente
2

getText es miembro de your Activity, por lo que debe llamarse cuando "this" existe. Su variable estática se inicializa cuando su clase se carga antes de que se cree su Actividad.

Dado que desea que la variable se inicialice desde una cadena de recursos, entonces no puede ser estática. Si desea que sea estático, puede inicializarlo con el valor String.

Estanque de Robby
fuente
2

No puede hacer referencia a una variable estática desde un método no estático. Para comprender esto, debe comprender la diferencia entre estático y no estático.

Las variables estáticas son variables de clase, pertenecen a la clase con su única instancia, creada solo en la primera. Las variables no estáticas se inicializan cada vez que crea un objeto de la clase.

Ahora, llegando a su pregunta, cuando use el operador new (), crearemos una copia de cada archivo no estático para cada objeto, pero no es el caso de los campos estáticos. Es por eso que da un error de tiempo de compilación si está haciendo referencia a una variable estática de un método no estático.

Krishna
fuente
0

Esta pregunta no es nueva y las respuestas existentes proporcionan una buena base teórica. Solo quiero agregar una respuesta más pragmática.

getText es un método de la clase abstracta Context y para llamarlo, se necesita una instancia de su subclase (Actividad, Servicio, Aplicación u otra). El problema es que las variables finales estáticas públicas se inicializan antes de que se cree cualquier instancia de Context.

Hay varias formas de solucionar esto:

  1. Haga de la variable una variable miembro (campo) de la Actividad u otra subclase de Contexto eliminando el modificador estático y colocándolo dentro del cuerpo de la clase;
  2. Manténgalo estático y retrase la inicialización hasta un punto posterior (por ejemplo, en el método onCreate);
  3. Conviértalo en una variable local en el lugar de uso real.
dev.bmax
fuente