Variável não estática não pode ser referenciada a partir de um contexto estático


288

Eu escrevi este código de teste:

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

Mas dá o seguinte erro:

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

Como obtenho meus métodos para reconhecer minhas variáveis ​​de classe?


Tente evitar o uso de estática sempre que possível. Você pode escrever um programa completo, tudo estático, como em C. Mas não será muito bom. Tente usar Java da maneira como deve ser usado, como uma linguagem orientada a objetos.
Erick G. Hagstrom

Respostas:


294

Você deve entender a diferença entre uma classe e uma instância dessa classe. Se você vê um carro na rua, sabe imediatamente que é um carro, mesmo que não consiga ver qual modelo ou tipo. Isso ocorre porque você compara o que vê com a classe "carro". A classe contém o que é semelhante a todos os carros. Pense nisso como um modelo ou uma ideia.

Ao mesmo tempo, o carro que você vê é uma instância da classe "carro", pois possui todas as propriedades esperadas: há alguém dirigindo, ele tem um motor, rodas.

Assim, a turma diz "todos os carros têm uma cor" e a instância diz "este carro específico é vermelho".

No mundo OO, você define a classe e, dentro da classe, define um campo do tipo Color . Quando a classe é instanciada (quando você cria uma instância específica), a memória é reservada para a cor e você pode atribuir uma cor a essa instância específica. Como esses atributos são específicos, eles não são estáticos.

Campos e métodos estáticos são compartilhados com todas as instâncias. Eles são para valores específicos da classe e não para uma instância específica. Para métodos, geralmente são métodos auxiliares globais (como Integer.parseInt()). Para campos, geralmente são constantes (como tipos de carros, ou seja, algo em que você tem um conjunto limitado que não muda com frequência).

Para resolver seu problema, você precisa instanciar uma instância (criar um objeto) da sua classe para que o tempo de execução possa reservar memória para a instância (caso contrário, diferentes instâncias se substituirão, o que você não deseja).

No seu caso, tente este código como um bloco de partida:

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
}

O novo main()método cria uma instância da classe que contém (soa estranho, mas como main()é criado com a classe e não com a instância, ele pode fazer isso) e depois chama um método de instância ( run()).


No momento, estou explicando isso ao nosso novo colega - obrigado por esta ótima explicação. Isso deve ser respondido pelo aceitador.
Supahupe

83

Os campos e métodos estáticos estão conectados à própria classe e não a suas instâncias. Se você tem uma classe A, um método 'normal' be um método estático ce cria uma instância ada sua classe A, as chamadas A.c()e a.b()são válidas. O método c()não tem idéia de qual instância está conectada, portanto, não pode usar campos não estáticos.

A solução para você é que você torne seus campos estáticos ou seus métodos não estáticos. Você principal pode se parecer com isso, então:

class Programm {

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

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

54

A staticpalavra-chave modifica o ciclo de vida de um método ou variável dentro de uma classe. Um staticmétodo ou variável é criado no momento em que uma classe é carregada. Um método ou variável que não é declarado como staticé criado apenas quando a classe é instanciada como um objeto, por exemplo, usando o newoperador

O ciclo de vida de uma classe, em termos gerais, é:

  1. o código fonte da classe é escrito, criando um modelo ou padrão ou carimbo que pode ser usado para
  2. crie um objeto com o newoperador usando a classe para criar uma instância da classe como um objeto real e, quando terminar, com o objeto
  3. destrua o objeto que recupera os recursos que está mantendo, como memória durante a coleta de lixo.

Para ter um ponto de entrada inicial para um aplicativo, Java adotou a convenção de que o programa Java deve ter uma classe que contenha um método com um nome especial ou acordado. Este método especial é chamado main(). Como o método deve existir se a classe que contém o método principal foi instanciada ou não, o main()método deve ser declarado com o staticmodificador para que, assim que a classe for carregada, o main()método esteja disponível.

O resultado é que, quando você inicia seu aplicativo Java por uma linha de comandos, como java helloworlduma série de ações, acontece. Antes de tudo, uma Java Virtual Machine é iniciada e inicializada. Em seguida, o arquivo helloworld.class que contém o código Java compilado é carregado na Java Virtual Machine. Em seguida, a Java Virtual Machine procura um método na helloworldclasse que é chamado main(String [] args). esse método deve ser staticpara que exista mesmo que a classe não tenha sido instanciada como um objeto. A Java Virtual Machine não cria uma instância da classe criando um objeto a partir da classe. Ele apenas carrega a classe e inicia a execução nomain() método

Portanto, você precisa criar uma instância da sua classe como um objeto e acessar os métodos e variáveis ​​da classe que não foram declarados com o staticmodificador. Depois que o programa Java iniciar com a main()função, você poderá usar quaisquer variáveis ​​ou métodos que possuam o modificador destatic uma vez que existem como parte da classe que está sendo carregada.

No entanto, as variáveis ​​e métodos da classe que estão fora do main()método e que não possuem o staticmodificador não podem ser usados ​​até que uma instância da classe tenha sido criada como um objeto no main()método. Depois de criar o objeto, você poderá usar as variáveis ​​e métodos do objeto. Uma tentativa de usar as variáveis ​​e métodos da classe que não possuem o staticmodificador sem passar por um objeto da classe é capturada pelo compilador Java no momento da compilação e sinalizada como um erro.

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

Vamos analisar seu programa primeiro. No seu programa, seu primeiro método é main() , e lembre-se de que é o método estático ... Então você declara a variável local para esse método (compareCount, low, high, etc.). O escopo dessa variável é apenas o método declarado, independentemente de ser um método estático ou não estático. Portanto, você não pode usar essas variáveis ​​fora desse método. Este é o erro básico que você fez.

Então chegamos ao próximo ponto. Você disse que a estática está matando você. (Pode estar matando você, mas apenas dá vida ao seu programa !!) Primeiro, você deve entender o básico. * O método estático chama apenas o método estático e usa apenas a variável estática. * Variável estática ou método estático não dependem de nenhuma instância dessa classe. (ou seja, se você alterar qualquer estado da variável estática, ela será refletida em todos os objetos da classe) * Por isso, você a chama como variável de classe ou método de classe. E muito mais existe sobre a palavra-chave "estática". Espero que agora você entenda a idéia. Primeiro, altere o escopo da variável e declare-a estática (para poder usá-la em métodos estáticos).

E o conselho para você é: você não entendeu a idéia do escopo das variáveis ​​e das funcionalidades estáticas. Tenha uma ideia clara sobre isso.


11

O básico é que variáveis ​​estáticas ou métodos estáticos estão no nível da classe. As variáveis ​​ou métodos no nível da classe são carregados antes dos métodos ou variáveis ​​no nível da instância. E, obviamente, a coisa que não está carregada não pode ser usada. Portanto, o compilador java que não permite que as coisas sejam tratadas em tempo de execução resolve em tempo de compilação. É por isso que está dando a você erro coisas não estáticas não podem ser referidas do contexto estático. Você só precisa ler sobre Escopo no nível da classe, Escopo no nível da instância e Escopo local.


8

Para poder acessá-los a partir de seus métodos estáticos, eles precisam ser variáveis ​​de membro estáticas, assim:

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

Agora você pode adicionar / usar instâncias no 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();
  }
}

Exemplo muito sólido que usei como modelo para revisar um arquivo src complexo em uma estrutura adequada.
XMAN 27/11/18

3

Vou tentar explicar a coisa estática para você. Antes de mais, as variáveis ​​estáticas não pertencem a nenhuma instância específica da classe. Eles são reconhecidos com o nome da classe. Os métodos estáticos novamente não pertencem novamente a nenhuma instância específica. Eles podem acessar apenas variáveis ​​estáticas. Imagine que você chame MyClass.myMethod () e myMethod é um método estático. Se você usa variáveis ​​não estáticas dentro do método, como diabos ele saberia quais variáveis ​​usar? É por isso que você pode usar, a partir de métodos estáticos, apenas variáveis ​​estáticas. Repito novamente que eles NÃO pertencem a nenhuma instância específica.


2
  • A primeira coisa é saber a diferença entre uma instância de uma classe e a própria classe. Uma classe modela certas propriedades e o comportamento do todo no contexto dessas propriedades. Uma instância definirá valores específicos para essas propriedades.

  • Qualquer coisa vinculada à palavra-chave estática está disponível no contexto da classe e não no contexto de uma instância da classe

  • Como corolário do acima

    1. variáveis ​​dentro de um método não podem ser estáticas
    2. campos estáticos e métodos devem ser chamados usando o nome da classe, por exemplo, MyProgram7.main (...)
  • A vida útil de um campo / método estático é equivalente à vida útil do seu aplicativo

Por exemplo, diga, carro tem a cor da propriedade e exibe o comportamento 'movimento'. Uma instância do carro seria um Fusca Vermelho em movimento a 25 km / h.

Agora, uma propriedade estática do carro seria o número de rodas (4) na estrada, e isso se aplicaria a todos os carros.

HTH


1

É o ClassLoader responsável por carregar os arquivos da classe. Vamos ver o que acontece quando escrevemos nossas próprias classes.

Exemplo 1:

class StaticTest {

      static int a;
      int b;
      int c;
}

Agora podemos ver que a classe "StaticTest" possui 3 campos. Mas, na verdade, não existe uma variável de membro b, c. OK, para que você não veja. Aqui, b, c são variáveis ​​de instância. Uma vez que a variável de instância obtém a memória no momento da criação do objeto. Então aqui b, c não está recebendo nenhuma memória ainda. É por isso que não existe existência de b, c. Portanto, existe apenas a existência de a. Para o ClassLoader, ele possui apenas uma informação sobre a. O ClassLoader ainda não reconhece b, c porque seu objeto ainda não foi instanciado.

Vamos ver outro exemplo: Exemplo 2:

class StaticTest {

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


      public static void main(String []cmd) {

             display();       
      }

}

Agora, se tentarmos compilar esse código, o compilador dará erro CE. CE: método não estático display () não pode ser referenciado a partir de um contexto estático.

Agora, para o ClassLoader, ele se parece com:

class StaticTest {

      public static void main(String []cmd) {

             display();       
      }

}

No exemplo 2, o erro CE é porque chamamos método não estático de um contexto estático. Portanto, não é possível que o ClassLoader reconheça o método display () no momento da compilação.


Provavelmente, você enviou sua resposta por acidente antes de conseguir finalizá-la? Edite-o e adicione o conteúdo que falta, obrigado!
plamut

1

Antes de chamar um método ou variável de instância, ele precisa de um objeto (Instância). Quando a variável de instância é chamada a partir do método estático, o compilador não sabe a qual objeto essa variável pertence. Como os métodos estáticos não têm um objeto (apenas uma cópia sempre). Quando você chama uma variável de instância ou métodos de instância do método de instância, ele faz referência ao thisobjeto. Isso significa que a variável pertence a qualquer objeto criado e cada objeto possui sua própria cópia dos métodos e variáveis ​​da instância.

As variáveis ​​estáticas são marcadas como statice as variáveis ​​de instância não possuem uma palavra-chave específica.


0

Isso é um pouco difícil de explicar sobre a palavra-chave estática para todos os iniciantes.
Você o conhecerá claramente quando trabalhar mais com Classes e Objetos.

| * | Estático: itens estáticos podem ser chamados com o nome da classe.
Se você observar nos códigos, algumas funções são chamadas diretamente com nomes de classe, como

NamCls.NamFnc();

System.out.println();

Isso ocorre porque o NamFnc e o println serão declarados usando a palavra-chave static antes deles.

| * | Não estático: itens não estáticos podem ser chamados com variável de classe
Se não for estático, você precisará de uma variável da classe,
coloque ponto após a variável de classe e
depois chame a função.

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


O código abaixo explica perfeitamente

| * | Função estática e não estática na classe:

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);
    }
}


| * | Classe estática e não estática dentro de uma classe:

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);
        }
    }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.