No se puede hacer referencia a la variable no estática desde un contexto estático


288

He escrito este código de prueba:

class MyProgram
{
    int count = 0;
    public static void main(String[] args)
    {
        System.out.println(count);
    }
}

Pero da el siguiente error:

Main.java:6: error: non-static variable count cannot be referenced from a static context
        System.out.println(count);
                           ^

¿Cómo obtengo mis métodos para reconocer mis variables de clase?


Intente evitar el uso de estática siempre que sea posible. Usted puede escribir un programa completo, todo estático, al igual que en C. Pero no será muy bueno. Intente utilizar Java de la manera en que debe usarse, como lenguaje orientado a objetos.
Erick G. Hagstrom

Respuestas:


294

Debe comprender la diferencia entre una clase y una instancia de esa clase. Si ve un automóvil en la calle, sabe de inmediato que es un automóvil, incluso si no puede ver qué modelo o tipo. Esto se debe a que compara lo que ve con la clase "auto". La clase contiene cuál es similar a todos los automóviles. Piense en ello como una plantilla o una idea.

Al mismo tiempo, el automóvil que ve es una instancia de la clase "automóvil" ya que tiene todas las propiedades que usted espera: hay alguien conduciéndolo, tiene un motor, ruedas.

Entonces, la clase dice "todos los autos tienen un color" y la instancia dice "este auto específico es rojo".

En el mundo OO, usted define la clase y dentro de la clase, define un campo de tipo Color . Cuando se crea una instancia de la clase (cuando crea una instancia específica), la memoria se reserva para el color y puede darle un color a esta instancia específica. Como estos atributos son específicos, no son estáticos.

Los campos y métodos estáticos se comparten con todas las instancias. Son para valores que son específicos de la clase y no una instancia específica. Para los métodos, estos generalmente son métodos de ayuda global (comoInteger.parseInt() ). Para los campos, generalmente son constantes (como los tipos de automóviles, es decir, algo donde tiene un conjunto limitado que no cambia a menudo).

Para resolver su problema, debe crear una instancia de una instancia (crear un objeto) de su clase para que el tiempo de ejecución pueda reservar memoria para la instancia (de lo contrario, diferentes instancias se sobrescribirán entre sí, lo que no desea).

En su caso, intente este código como bloque inicial:

public static void main (String[] args)
{
    try
    {
        MyProgram7 obj = new MyProgram7 ();
        obj.run (args);
    }
    catch (Exception e)
    {
        e.printStackTrace ();
    }
}

// instance variables here

public void run (String[] args) throws Exception
{
    // put your code here
}

El nuevo main()método crea una instancia de la clase que contiene (suena extraño pero como main()se crea con la clase en lugar de con la instancia, puede hacer esto) y luego llama a un método de instancia ( run()).


Estoy explicando esto en este momento a nuestro nuevo colega, gracias por esta gran explicación. Esto debería responder el aceptante.
Supahupe

83

Los campos y métodos estáticos están conectados a la clase misma y no a sus instancias. Si tiene una clase A, un método 'normal' by un método estático c, y realiza una instancia ade su clase A, las llamadas a A.c()y a.b()son válidas. Métodoc() no tiene idea de qué instancia está conectada, por lo que no puede usar campos no estáticos.

La solución para usted es que haga que sus campos sean estáticos o que sus métodos no sean estáticos. Su principal podría verse así entonces:

class Programm {

    public static void main(String[] args) {
        Programm programm = new Programm();
        programm.start();
    }

    public void start() {
        // can now access non-static fields
    }
}

54

La staticpalabra clave modifica el ciclo de vida de un método o variable dentro de una clase. Se staticcrea un método o variable en el momento en que se carga una clase. Un método o variable que no se declara como staticse crea solo cuando la clase se instancia como un objeto, por ejemplo, utilizandonew operador.

El ciclo de vida de una clase, en términos generales, es:

  1. el código fuente de la clase se escribe creando una plantilla o patrón o sello que luego se puede usar para
  2. crear un objeto con el new operador usando la clase para hacer una instancia de la clase como un objeto real y luego cuando haya terminado con el objeto
  3. destruya el objeto recuperando los recursos que contiene, como la memoria durante la recolección de basura.

Para tener un punto de entrada inicial para una aplicación, Java ha adoptado la convención de que el programa Java debe tener una clase que contenga un método con un nombre acordado o especial. Este método especial se llama main(). Dado que el método debe existir tanto si la clase que contiene el método principal ha sido instanciada como si no, el main()método debe declararse con el staticmodificador para que tan pronto como se cargue la clase, el main()método esté disponible.

El resultado es que cuando inicia su aplicación Java mediante una línea de comando, como java helloworldsucede una serie de acciones. En primer lugar, se inicia e inicializa una máquina virtual Java. A continuación, el archivo helloworld.class que contiene el código Java compilado se carga en la máquina virtual Java. Luego, la máquina virtual Java busca un método en la helloworldclase que se llama main(String [] args). este método debe ser staticpara que exista aunque la clase no haya sido instanciada como un objeto. Java Virtual Machine no crea una instancia de la clase al crear un objeto a partir de la clase. Simplemente carga la clase e inicia la ejecución en el main()método.

Por lo tanto, debe crear una instancia de su clase como un objeto y luego puede acceder a los métodos y variables de la clase que no se han declarado con el staticmodificador. Una vez que su programa Java ha comenzado con la main()función, puede usar cualquier variable o método que tenga el modificador destatic ya que existe como parte de la clase que se está cargando.

Sin embargo, aquellas variables y métodos de la clase que están fuera del main()método que no tienen el staticmodificador no pueden usarse hasta que se haya creado una instancia de la clase como un objeto dentro del main()método. Después de crear el objeto, puede usar las variables y los métodos del objeto. El staticcompilador de Java detecta un intento de utilizar las variables y métodos de la clase que no tienen el modificador sin pasar por un objeto de la clase en el momento de la compilación y lo marca como un error.

import java.io.*;

class HelloWorld {
    int myInt;      // this is a class variable that is unique to each object
    static int myInt2;  // this is a class variable shared by all objects of this class

    static void main (String [] args) {
        // this is the main entry point for this Java application
        System.out.println ("Hello, World\n");
        myInt2 = 14;    // able to access the static int
        HelloWorld myWorld = new HelloWorld();
        myWorld.myInt = 32;   // able to access non-static through an object
    }
}

11

Analicemos su programa primero. En su programa, su primer método es main() , y tenga en cuenta que es el método estático ... Luego declara la variable local para ese método (compareCount, low, high, etc.). El alcance de esta variable es solo el método declarado, independientemente de que sea un método estático o no estático. Entonces no puedes usar esas variables fuera de ese método. Este es el error básico que cometiste.

Entonces llegamos al siguiente punto. Le dijiste a static que te está matando. (¡Puede que te esté matando, pero solo da vida a tu programa!) Primero debes entender lo básico. * El método estático solo llama al método estático y usa solo la variable estática. * La variable estática o el método estático no dependen de ninguna instancia de esa clase. (es decir, si cambia cualquier estado de la variable estática, se reflejará en todos los objetos de la clase) * Debido a esto, lo llama como una variable de clase o un método de clase. Y hay mucho más sobre la palabra clave "estática". Espero que ahora entiendas la idea. Primero cambie el alcance de la variable y declare como estática (para poder usarla en métodos estáticos).

Y el consejo para usted es: no entendió la idea del alcance de las variables y las funcionalidades estáticas. Tener una idea clara sobre eso.


11

Lo más básico es que las variables estáticas o los métodos estáticos están a nivel de clase. Las variables o métodos de nivel de clase se cargan antes que los métodos o variables de nivel de instancia, y obviamente lo que no se carga no se puede usar. Entonces, el compilador de Java que no permite que las cosas se manejen en tiempo de ejecución se resuelve en tiempo de compilación. Es por eso que le está dando error, las cosas no estáticas no pueden ser referidas desde un contexto estático. Solo necesita leer sobre el alcance del nivel de clase, el alcance del nivel de instancia y el alcance local.


8

Para poder acceder a ellos desde sus métodos estáticos, deben ser variables miembro estáticas, como esta:

public class MyProgram7 {
  static Scanner scan = new Scanner(System.in);
  static int compareCount = 0;
  static int low = 0;
  static int high = 0;
  static int mid = 0;  
  static int key = 0;  
  static Scanner temp;  
  static int[]list;  
  static String menu, outputString;  
  static int option = 1;  
  static boolean found = false;

  public static void main (String[]args) throws IOException {
  ...

7

Ahora puede agregar / usar instancias con en el método

public class Myprogram7 {

  Scanner scan;
  int compareCount = 0;
  int low = 0;
  int high = 0;
  int mid = 0;  
  int key = 0;  
  Scanner temp;  
  int[]list;  
  String menu, outputString;  
  int option = 1;  
  boolean found = false;  

  private void readLine() {

  }

  private void findkey() {

  }

  private void printCount() {

  }
  public static void main(String[] args){

    Myprogram7 myprg=new Myprogram7();
    myprg.readLine();
    myprg.findkey();
    myprg.printCount();
  }
}

Un ejemplo muy sólido que utilicé como plantilla para revisar un archivo src complejo en una estructura adecuada.
XMAN

3

Trataré de explicarte lo estático. En primer lugar, las variables estáticas no pertenecen a ninguna instancia particular de la clase. Se reconocen con el nombre de la clase. Los métodos estáticos nuevamente no pertenecen nuevamente a ninguna instancia en particular. Solo pueden acceder a variables estáticas. Imagine que llama a MyClass.myMethod () y myMethod es un método estático. Si usa variables no estáticas dentro del método, ¿cómo demonios sabría qué variables usar? Es por eso que puede usar de métodos estáticos solo variables estáticas. Repito nuevamente que NO pertenecen a ninguna instancia en particular.


2
  • Lo primero es saber la diferencia entre una instancia de una clase y la clase misma. Una clase modela ciertas propiedades y el comportamiento del conjunto en el contexto de esas propiedades. Una instancia definirá valores específicos para esas propiedades.

  • Todo lo relacionado con la palabra clave estática está disponible en el contexto de la clase y no en el contexto de una instancia de la clase.

  • Como corolario de lo anterior.

    1. las variables dentro de un método no pueden ser estáticas
    2. los campos estáticos y los métodos deben invocarse utilizando el nombre de clase, por ejemplo, MyProgram7.main (...)
  • La vida útil de un campo / método estático es equivalente a la vida útil de su aplicación

Por ejemplo, digamos, el automóvil tiene el color de propiedad y exhibe el comportamiento 'movimiento'. Una instancia del auto sería un Volkswagen Beetle Rojo en movimiento a 25kmph.

Ahora, una propiedad estática del automóvil sería la cantidad de ruedas (4) en la carretera, y esto se aplicaría a todos los automóviles.

HTH


1

ClassLoader es responsable de cargar los archivos de clase. Veamos qué sucede cuando escribimos nuestras propias clases.

Ejemplo 1:

class StaticTest {

      static int a;
      int b;
      int c;
}

Ahora podemos ver que la clase "StaticTest" tiene 3 campos. Pero en realidad no existe una variable miembro b, c. ¿Pero por qué ???. OK, no lo veamos. Aquí b, c son variables de instancia, ya que la variable de instancia obtiene la memoria en el momento de la creación del objeto. Así que aquí b, c no están obteniendo ninguna memoria todavía. Por eso no hay existencia de b, c. Entonces solo existe la existencia de a. Para ClassLoader solo tiene una información sobre a. ClassLoader aún no reconoce b, c porque su objeto aún no está instanciado.

Veamos otro ejemplo: Ejemplo 2:

class StaticTest {

      public void display() {
          System.out.println("Static Test");
      }


      public static void main(String []cmd) {

             display();       
      }

}

Ahora si tratamos de compilar este compilador de código dará un error CE. CE: no se puede hacer referencia a la visualización del método no estático () desde un contexto estático.

Ahora para ClassLoader se ve así:

class StaticTest {

      public static void main(String []cmd) {

             display();       
      }

}

En el ejemplo 2, el error CE se debe a que llamamos a un método no estático desde un contexto estático. Por lo tanto, ClassLoader no puede reconocer el método display () en tiempo de compilación, por lo que se produjo un error de tiempo de compilación.


¿Probablemente enviaste tu respuesta por accidente antes de que pudieras terminarla? Edítelo y agregue el contenido que falta, ¡gracias!
plamut

1

Antes de llamar a un método de instancia o variable de instancia Necesita un objeto (Instancia). Cuando se llama a la variable de instancia desde el método estático, el compilador no sabe a qué objeto pertenece esta variable. Porque los métodos estáticos no tienen un objeto (solo una copia siempre). Cuando llama a una variable de instancia o métodos de instancia desde el método de instancia, hace referencia athis objeto. Significa que la variable pertenece a cualquier objeto creado y cada objeto tiene su propia copia de métodos y variables de instancia.

Las variables estáticas se marcan como staticy las variables de instancia no tienen una palabra clave específica.


0

Esto es un poco difícil de explicar sobre la palabra clave estática para todos los principiantes.
Lo conocerá con claridad cuando trabaje más con Clases y Objetos.

| * | Estático: los elementos estáticos se pueden invocar con el nombre de clase
Si observa en los códigos, algunas funciones se invocan directamente con nombres de clase como

NamCls.NamFnc();

System.out.println();

Esto se debe a que NamFnc e println se declararán utilizando la palabra clave static antes que ellos.

| * | No estático: los elementos no estáticos se pueden llamar con Variable de clase
Si no es estático, necesita una variable de la clase,
coloque un punto después de la variable de clase y
luego llame a la función.

NamCls NamObjVar = new NamCls();
NamObjVar.NamFnc();


El siguiente código te explica perfectamente

| * | Función estática y no estática en clase:

public class NamCls
{
    public static void main(String[] args)
    {
        PlsPrnFnc("Tst Txt");

        NamCls NamObjVar = new NamCls();
        NamObjVar.PrnFnc("Tst Txt");
    }

    static void PlsPrnFnc(String SrgPsgVal)
    {
        System.out.println(SrgPsgVal);
    }

    void PrnFnc(String SrgPsgVal)
    {
        System.out.println(SrgPsgVal);
    }
}


| * | Clase estática y no estática dentro de una clase:

public class NamCls
{
    public static void main(String[] args)
    {
        NamTicCls NamTicVaj = new NamTicCls();
        NamTicVaj.PrnFnc("Tst Txt");

        NamCls NamObjVar = new NamCls();
        NamNicCls NamNicVar = NamObjVar.new NamNicCls();
        NamNicVar.PrnFnc("Tst Txt");
    }

    static class NamTicCls
    {
        void PrnFnc(String SrgPsgVal)
        {
            System.out.println(SrgPsgVal);
        }
    }

    class NamNicCls
    {
        void PrnFnc(String SrgPsgVal)
        {
            System.out.println(SrgPsgVal);
        }
    }
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.