java modificador atributo estático final privado versus atributo final privado




public private protected java (16)

Se você marcar esta variável estática, como você sabe, você precisaria de métodos estáticos para acessar novamente esses valores, isso será útil se você já pensar em usar essas variáveis ​​apenas em métodos estáticos. Se assim for, então este seria o melhor.

Você pode, no entanto, tornar a variável agora pública, já que ninguém pode modificá-la como "System.out", novamente depende das suas intenções e do que você deseja alcançar.

Em Java, qual a diferença entre:

private final static int NUMBER = 10;

e

private final int NUMBER = 10;

Ambos são private e final , a diferença é o atributo static .

O que é melhor? E porque?


Como uma variável em uma classe é declarada como final e inicializada no mesmo comando, não há absolutamente nenhum motivo para não declará-la como estática, pois ela terá o mesmo valor, independentemente da instância. Assim, todas as instâncias podem compartilhar o mesmo endereço de memória para um valor, economizando tempo de processamento, eliminando a necessidade de criar uma nova variável para cada instância e economizando memória compartilhando um endereço comum.


Em geral, static significa "associado ao próprio tipo , em vez de uma instância do tipo".

Isso significa que você pode referenciar uma variável estática sem nunca ter criado uma instância do tipo, e qualquer código referente à variável está se referindo exatamente aos mesmos dados. Compare isso com uma variável de instância: nesse caso, há uma versão independente da variável por instância da classe. Então, por exemplo:

Test x = new Test();
Test y = new Test();
x.instanceVariable = 10;
y.instanceVariable = 20;
System.out.println(x.instanceVariable);

imprime 10: y.instanceVariable e x.instanceVariable são separados porque x e y referem a objetos diferentes.

Você pode se referir a membros estáticos através de referências, embora seja uma má idéia fazê-lo. Se nós fizemos:

Test x = new Test();
Test y = new Test();
x.staticVariable = 10;
y.staticVariable = 20;
System.out.println(x.staticVariable);

então, imprimiria 20 - há apenas uma variável, não uma por instância. Teria sido mais claro escrever isso como:

Test x = new Test();
Test y = new Test();
Test.staticVariable = 10;
Test.staticVariable = 20;
System.out.println(Test.staticVariable);

Isso torna o comportamento muito mais óbvio. Os IDEs modernos geralmente sugerem a mudança da segunda listagem para a terceira.

Não há razão para ter uma declaração como

private final int NUMBER = 10;

Se não puder mudar, não faz sentido ter uma cópia por instância.


Como já disse Jon, uma variável estática, também chamada de variável de classe, é uma variável que existe entre instâncias de uma classe.

Eu encontrei um exemplo disso here :

public class StaticVariable
{
  static int noOfInstances;
  StaticVariable()
  {
    noOfInstances++;
  }
  public static void main(String[] args)
  {
    StaticVariable sv1 = new StaticVariable();
    System.out.println("No. of instances for sv1 : " + sv1.noOfInstances);

    StaticVariable sv2 = new StaticVariable();
    System.out.println("No. of instances for sv1 : "  + sv1.noOfInstances);
    System.out.println("No. of instances for st2 : "  + sv2.noOfInstances);

    StaticVariable sv3 = new StaticVariable();
    System.out.println("No. of instances for sv1 : "  + sv1.noOfInstances);
    System.out.println("No. of instances for sv2 : "  + sv2.noOfInstances);
    System.out.println("No. of instances for sv3 : "  + sv3.noOfInstances);
  }
}

A saída do programa é dada abaixo:

Como podemos ver neste exemplo, cada objeto tem sua própria cópia da variável de classe.

C:\java>java StaticVariable
No. of instances for sv1 : 1
No. of instances for sv1 : 2
No. of instances for st2 : 2
No. of instances for sv1 : 3
No. of instances for sv2 : 3
No. of instances for sv3 : 3

Variável estática pertence à classe (o que significa que todos os objetos compartilham essa variável). Variável não estática pertence a cada objeto.

public class ExperimentFinal {

private final int a;
private static final int b = 999; 

public ExperimentFinal(int a) {
    super();
    this.a = a;
}
public int getA() {
    return a;
}
public int getB() {
    return b;
}
public void print(int a, int b) {
    System.out.println("final int: " + a + " \nstatic final int: " + b);
}
public static void main(String[] args) {
    ExperimentFinal test = new ExperimentFinal(9);
    test.print(test.getA(), test.getB());
} }

Como você pode ver acima exemplo, para "final int" podemos atribuir nossa variável para cada instância (objeto) da classe, no entanto para "static final int", devemos atribuir uma variável na classe (variável estática pertence à classe ).


Isso pode ajudar

public class LengthDemo {
public static void main(String[] args) {
    Rectangle box = new Rectangle();
    System.out.println("Sending the value 10.0 "
            + "to the setLength method.");
    box.setLength(10.0);
    System.out.println("Done.");
    }
}

meios estáticos "associados à classe"; sem isso, a variável é associada a cada instância da classe. Se é estático, isso significa que você terá apenas um na memória; se não, você terá um para cada instância criada. static significa que a variável permanecerá na memória enquanto a classe estiver carregada; sem isso, a variável pode ser gc quando a instância for.


Dos testes que fiz, as variáveis ​​finais estáticas não são as mesmas com as variáveis ​​finais (não-estáticas)! Variáveis ​​finais (não-estáticas) podem diferir de objeto para objeto !!! Mas isso é só se a inicialização for feita dentro do construtor! (Se não for inicializado a partir do construtor, é apenas um desperdício de memória, pois cria variáveis ​​finais para cada objeto criado que não pode ser alterado.)

Por exemplo:

class A
{
    final int f;
    static final int sf = 5;

    A(int num)
    {
        this.f = num;
    }

    void show()
    {
        System.out.printf("About Object: %s\n Final: %d\n Static Final: %d\n\n", this.toString(), this.f, sf);
    }

    public static void main(String[] args)
    {
        A ob1 = new A(14);
        ob1.show();

        A ob2 = new A(21);
        ob2.show();

    }
}

O que aparece na tela é:

Sobre o Objeto: A @ addbf1 Final: 14 Estático Final: 5

Sobre o Objeto: A @ 530daa Final: 21 Estático Final: 5

Anônimo estudante de TI do 1º ano, Grécia


Lendo as respostas, não encontrei nenhum teste real que estivesse realmente chegando ao ponto. Aqui estão meus 2 centavos:

public class ConstTest
{

    private final int         value             = 10;
    private static final int  valueStatic       = 20;
    private final File        valueObject       = new File("");
    private static final File valueObjectStatic = new File("");

    public void printAddresses() {


        System.out.println("final int address " +
                ObjectUtils.identityToString(value));
        System.out.println("final static int address " +
                ObjectUtils.identityToString(valueStatic));
        System.out.println("final file address " + 
                ObjectUtils.identityToString(valueObject));
        System.out.println("final static file address " + 
                ObjectUtils.identityToString(valueObjectStatic));
    }


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


        final ConstTest firstObj = new ConstTest();
        final ConstTest sndObj = new ConstTest();

        firstObj.printAdresses();
        sndObj.printAdresses();
    }

}

Resultados para o primeiro objeto:

final int address java.lang.[email protected]
final static int address java.lang.[email protected]
final file address java.io.[email protected]
final static file address java.io.[email protected]

Resultados para o 2º objeto:

final int address java.lang.[email protected]
final static int address java.lang.[email protected]
final file address java.io.[email protected]
final static file address java.io.[email protected]

Conclusão:

Como eu pensei java faz uma diferença entre tipos primitivos e outros. Tipos primitivos em Java são sempre "armazenados em cache", mesmo para strings literais (não novos objetos String), portanto, não há diferença entre membros estáticos e não-estáticos.

No entanto, há uma duplicação de memória para membros não estáticos, se eles não forem uma instância de um tipo primitivo.

Alterar o valor de valueStatic para 10 irá ainda mais longe, pois o Java fornecerá os mesmos endereços para as duas variáveis ​​int.


Aqui estão meus dois centavos:

final           String CENT_1 = new Random().nextInt(2) == 0 ? "HEADS" : "TAILS";
final   static  String CENT_2 = new Random().nextInt(2) == 0 ? "HEADS" : "TAILS";

Exemplo:

package test;

public class Test {

    final long OBJECT_ID = new Random().nextLong();
    final static long CLASSS_ID = new Random().nextLong();

    public static void main(String[] args) {
        Test[] test = new Test[5];
        for (int i = 0; i < test.length; i++){
            test[i] = new Test();
            System.out.println("Class id: "+test[i].CLASSS_ID);//<- Always the same value
            System.out.println("Object id: "+test[i].OBJECT_ID);//<- Always different
        }
    }
}

A chave é que variáveis ​​e funções podem retornar valores diferentes. Portanto, as variáveis ​​finais podem ser atribuídas com valores diferentes.


muito pouco e estático

Não há muita diferença, pois ambas são constantes. Para a maioria dos objetos de dados de classe, static significaria algo associado à própria classe, existindo apenas uma cópia, não importando quantos objetos fossem criados com new.

Como é uma constante, ela pode não ser armazenada na classe ou em uma instância, mas o compilador ainda não permitirá que você acesse objetos da instância a partir de um método estático, mesmo que saiba o que eles seriam. A existência da API de reflexão também pode exigir algum trabalho inútil se você não torná-la estática.


Uma variável static permanece na memória durante toda a vida útil do aplicativo e é inicializada durante o carregamento da classe. Uma variável não static está sendo inicializada toda vez que você constrói um new objeto. Geralmente é melhor usar:

private static final int NUMBER = 10;

Por quê? Isso reduz o consumo de memória por instância. É possivelmente também favorável para ocorrências de cache. E isso faz sentido: a static deve ser usada para coisas que são compartilhadas em todas as instâncias (também conhecidas como objetos) de um determinado tipo (também conhecido como class ).


Para final , pode ser atribuído diferentes valores em tempo de execução quando inicializado. Por exemplo

Class Test{
  public final int a;
}

Test t1  = new Test();
t1.a = 10;
Test t2  = new Test();
t2.a = 20; //fixed

Assim, cada instância tem um valor diferente de campo a .

Para final estático , todas as instâncias compartilham o mesmo valor e não podem ser alteradas após a primeira inicialização.

Class TestStatic{
      public static final int a;
}

TestStatic t1  = new TestStatic();
t1.a = 10;
TestStatic t2  = new TestStatic();
t1.a = 20;   // ERROR, CAN'T BE ALTERED AFTER THE FIRST INITIALIZATION.

Enquanto as outras respostas parecem deixar bem claro que geralmente não há razão para usar constantes não-estáticas, não consegui encontrar ninguém apontando que é possível ter várias instâncias com valores diferentes em suas variáveis ​​constantes.

Considere o seguinte exemplo:

public class TestClass {
    private final static double NUMBER = Math.random();

    public TestClass () {
        System.out.println(NUMBER);
    }
}

Criar três instâncias de TestClass imprimiria o mesmo valor aleatório três vezes, já que apenas um valor é gerado e armazenado na constante estática.

No entanto, ao tentar o seguinte exemplo:

public class TestClass {
    private final double NUMBER = Math.random();

    public TestClass () {
        System.out.println(NUMBER);
    }
}

Criar três instâncias de TestClass agora imprime três valores aleatórios diferentes, porque cada instância tem seu próprio valor constante gerado aleatoriamente.

Não consigo pensar em nenhuma situação em que seria realmente útil ter valores constantes diferentes em instâncias diferentes, mas espero que isso ajude a apontar que há uma clara diferença entre finais estáticos e não estáticos.


Se você usar estático, o valor da variável será o mesmo em todas as suas instâncias, se alterado em uma instância, as outras também serão alteradas.


Além disso, para a resposta de Jon, se você usar a final estática, ela se comportará como uma espécie de "definição". Depois de compilar a classe que a usa, ela estará no arquivo .class compilado. Verifique meu tópico sobre isso here .

Para o seu objetivo principal: Se você não usar o NUMBER de forma diferente nas diferentes instâncias da classe, aconselho usar final e estático. (Você só precisa se lembrar de não copiar os arquivos de classe compilados sem considerar possíveis problemas como o descrito no meu estudo de caso. Na maioria dos casos isso não ocorre, não se preocupe :))

Para mostrar como usar valores diferentes nas instâncias, verifique este código:

public class JustFinalAttr {
  public final int Number;

  public JustFinalAttr(int a){
    Number=a;
  }
}

...System.out.println(new JustFinalAttr(4).Number);




final