Não é possível fazer uma referência estática ao método não estático

102

Construindo um aplicativo multilíngue em Java. Obtendo um erro ao inserir o valor String do R.stringarquivo XML de recurso:

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

Esta é a mensagem de erro:

Erro: não é possível fazer uma referência estática ao método não estático getText (int) do tipo Context

Como isso é causado e como posso resolver isso?

Chen M
fonte
1
Por que você precisa que seja estático para um 'aplicativo multilíngue'? Realmente não entendo.
xil3 de
3
Nunca armazene recursos de string em membros de dados estáticos. Solicite-os sempre via getString()quando precisar deles. Dessa forma, seu aplicativo se ajusta adequadamente aos usuários que mudam o idioma escolhido.
CommonsWare

Respostas:

143

Como getText()não é estático, você não pode chamá-lo de um método estático.

Para entender o porquê, você precisa entender a diferença entre os dois.

Métodos de instância (não estáticos) funcionam em objetos que são de um tipo específico (a classe). Eles são criados com o novo assim:

SomeClass myObject = new SomeClass();

Para chamar um método de instância, você o chama na instância ( myObject):

myObject.getText(...)

No entanto, um método / campo estático pode ser chamado apenas no tipo diretamente, digamos assim: A declaração anterior não está correta. Também se pode referir a campos estáticos com uma referência de objeto como, myObject.staticMethod() mas isso é desencorajado porque não deixa claro que são variáveis ​​de classe.

... = SomeClass.final

E os dois não podem trabalhar juntos, pois operam em espaços de dados diferentes (dados de instância e dados de classe)

Deixe-me tentar explicar. Considere esta classe (psuedocode):

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

Agora tenho o seguinte caso de uso:

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

 Test item2 = new Test();

 Test.TTT = "1";

Quais são os valores?

Bem

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

Em outras palavras, TTTé um dado compartilhado por todas as instâncias do tipo. Então não faz sentido dizer

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

Portanto, a questão é por que o TTT é estático ou por que getText () não é estático?

Remova o statice ele deve passar por esse erro - mas sem entender o que seu tipo faz é apenas um esparadrapo até o próximo erro. Quais são os requisitos getText()que exigem que seja não estático?

Preet Sangha
fonte
é estático porque eu o chamo de vários arquivos em meu projeto. quando removi o "estático", o código de erro desapareceu, mas agora tenho muitos erros em outros arquivos que usam essa variável.
Chen M
Mas esse é o meu ponto. Você precisa entender quando os dois podem ser usados.
Preet Sangha
quando adiciono a linha "Constants notifications_values ​​= new Constants (); à minha classe de atividade principal, ele compila OK, mas no emulador ele trava quando esta atividade é executada
Chen M
11

Já existem algumas boas respostas com explicações de porque a mistura do Contextmétodo getText()não estático não pode ser usado com o seu static final String.

Uma boa pergunta a fazer é: por que você quer fazer isso? Você está tentando carregar um Stringde seu stringsrecurso e preencher seu valor em um public staticcampo. Presumo que seja para que algumas de suas outras classes possam acessá-lo. Nesse caso, não há necessidade de fazer isso. Em vez disso, passe um Contextpara suas outras classes e chame context.getText(R.string.TTT)de dentro delas.

public class NonActivity {

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

E para chamar isso de seu Activity:

NonActivity.doStuff(this);

Isso permitirá que você acesse seu Stringrecurso sem precisar usar um public staticcampo.

dave.c
fonte
1
muito obrigado, mudei todos os arquivos de acordo com sua recomendação.
Chen M
Eu estava tentando fazer isso, mas para uma string-array e com String a[] = context.getTextArray(R.array.myStringArray); ; ele, entretanto, me dá um erro The method getTextArray(int) is undefined for the type Context- por que seria indefinido enquanto funciona com getText?
auspicious99
1
@ auspicious99 simplesmente porque a Contextnão tem um método chamado getTextArray, mas tem getText. Talvez você esteja pensando em Resourcesqual temgetTextArray
dave.c
Ah, obrigado! Passei em Recursos em vez de Contexto (da atividade para a não atividade), e meu getStringArray funcionou.
auspicioso99
9

para outros que encontram isso na pesquisa:

Freqüentemente recebo este quando acidentalmente chamo uma função usando o nome da classe em vez do nome do objeto. Isso geralmente acontece porque eu dou nomes muito semelhantes: P

ie:

MyClass myclass = new MyClass();

// then later

MyClass.someFunction();

Este é obviamente um método estático. (bom para algumas coisas) Mas o que eu realmente queria fazer (na maioria dos casos era)

myclass.someFunction();

É um erro tão bobo, mas a cada dois meses, eu perco cerca de 30 minutos mexendo com vars nas definições "MyClass" para descobrir o que estou fazendo de errado quando, na verdade, é apenas um erro de digitação.

Nota engraçada: o estouro de pilha destaca a sintaxe para tornar o erro realmente óbvio aqui.

SpiRail
fonte
O seu IDE não destaca isso também? Eu acho que você pode configurá-lo para fazer isso :)
Matthias Meid
2

Você pode tornar sua variável não estática

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

ou torne o método "getText" estático (se possível)

Kellindil
fonte
2

getText é membro da sua Activity, portanto, deve ser chamado quando "this" existir. Sua variável estática é inicializada quando sua classe é carregada antes de sua Activity ser criada.

Como você deseja que a variável seja inicializada a partir de uma string de Recurso, ela não pode ser estática. Se você quiser que seja estático, pode inicializá-lo com o valor String.

Robby Pond
fonte
2

Você não pode fazer referência a uma variável estática de um método não estático. Para entender isso, você precisa entender a diferença entre estático e não estático.

Variáveis ​​estáticas são variáveis ​​de classe, pertencem à classe com sua única instância, criada apenas na primeira. Variáveis ​​não estáticas são inicializadas sempre que você cria um objeto da classe.

Agora, voltando à sua pergunta, quando você usa o operador new (), criaremos uma cópia de cada campo não estático para cada objeto, mas não é o caso dos campos estáticos. É por isso que dá erro de tempo de compilação se você estiver referenciando uma variável estática de um método não estático.

Krishna
fonte
0

Esta questão não é nova e as respostas existentes fornecem uma boa base teórica. Eu só quero adicionar uma resposta mais pragmática.

getText é um método da classe abstrata Context e para chamá-lo, é necessária uma instância de sua subclasse (Activity, Service, Application ou outro). O problema é que as variáveis ​​finais estáticas públicas são inicializadas antes que qualquer instância de Context seja criada.

Existem várias maneiras de resolver isso:

  1. Torne a variável uma variável membro (campo) da Activity ou outra subclasse de Context removendo o modificador estático e colocando-o dentro do corpo da classe;
  2. Mantenha-o estático e atrase a inicialização para um ponto posterior (por exemplo, no método onCreate);
  3. Faça dela uma variável local no lugar do uso real.
dev.bmax
fonte