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

Construyendo una aplicación multi-idioma en Java. Obteniendo un error al insertar el valor de R.string archivo XML del recurso R.string :

 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) del tipo Contexto

¿Cómo es esto causado y cómo puedo resolverlo?

Como getText() 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 el nuevo como este:

 SomeClass myObject = new SomeClass(); 

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

 myObject.getText(...) 

Sin embargo, un método / campo estático solo se puede invocar directamente en el tipo, por ejemplo, así: la statement anterior no es correcta. También se puede hacer referencia a los campos estáticos con una referencia de objeto como myObject.staticMethod() pero esto se desaconseja 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 y explicar 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, TTT es 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 estático o por qué getTex () no es estático?

Elimina la static y debería superar este error, pero sin entender lo que hace tu tipo es solo un yeso adhesivo hasta el próximo error. ¿Cuáles son los requisitos de getText() que requieren que sea no estático?

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

Una buena pregunta es: ¿por qué quieres hacer esto? Está intentando cargar un String de su recurso de strings y rellenar su valor en un campo public static . Supongo que esto es para que algunas de tus otras clases puedan acceder a él. Si es así, no hay necesidad de hacer esto. En su lugar, pase un Context en sus otras clases y llame a context.getText(R.string.TTT) desde dentro de ellos.

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

Y para llamar esto desde tu Activity :

 NonActivity.doStuff(this); 

Esto le permitirá acceder a su recurso de String sin necesidad de utilizar un campo public static .

para otros que encuentran esto en la búsqueda:

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

es decir:

 MyClass myclass = new MyClass(); // then later MyClass.someFunction(); 

Esto es obviamente un método estático. (bueno para algunos) 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, desperdicio 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 curiosa: el desbordamiento de la stack resalta la syntax para hacer que el error sea realmente obvio aquí.

Puedes hacer que tu 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)

getText es miembro de tu Actividad, por lo que debe invocarse cuando “this” exista. Su variable estática se inicializa cuando su clase se carga antes de que se cree su actividad.

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

No puede hacer referencia a la variable estática del método no estático. Para entender esto, necesitas entender 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, creadas solo en la primera. Las variables no estáticas se inicializan cada vez que creas un objeto de la clase.

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

Esta pregunta no es nueva y las respuestas existentes dan algunos buenos antecedentes teóricos. Solo quiero agregar una respuesta más pragmática.

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

Hay varias formas de resolver esto:

  1. Haga que la variable sea 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. Mantenerlo estático y retrasar la inicialización a un punto posterior (por ejemplo, en el método onCreate);
  3. Haz que sea una variable local en el lugar de uso real.

No puede usar un método no estático para inicializar una variable estática.