Entendendo static

45 respostas
A

Assunto: Você se sente confuso quanto à utilidade da palavra-chave static? Não sabe quando nem como usar? Seus problemas acabaram, leia este tutorial aqui do GUJ e acabe com suas dúvidas.

Você pode ler este artigo na íntegra em http://www.guj.com.br/java.artigo.121.1.guj

Por favor, coloque os seus comentários sobre este artigo aqui.

45 Respostas

D

Adorei o seu artigo. Muito claro e direto!

Entretanto gostaria de saber de você se já esteve em alguma situação onde determinados métodos precisavam existir, mas simplesmente não se encaixavam em nenhuma classe da aplicação. E como você resolveu o problema? Que técnicas ou design patterns teve de usar ou “quebrar”?

Abraços.

P

Um método static realmente se parece com uma funcao
Cabe a voce a decisao de onde ele deve ficar. Pois voce pode mudar muito bem onde o metodo estatico esta para outra classe, sem maiores problemas.

A SUN criou a classe Math para ter os metodos estaticos que abordam o mesmo assunto. Voce vai ver por ai muita gente ter uma classe que chama “MeuProjetoUtils” contendo uma serie de cosntantes e metodos estaticos. Apesar de eu tambem usar isso, creio que a melhor solucao seja ter classes que possuem metodos estaticos e nao estaticos. Assim como a aclasse Integer têm.

R

Muito bom o artigo sobre static…uma vez estava desenvolvendo um projeto em java e apanhei muito ocm variaveis estaticas…deu muito pau no meu programa e eu nao sabia pq, depois fui descobrir que eram variaveis estaticas do programa.

ate mais…

P

:smiley: Gostaria de deixar a minha dica aqui sobre o assunto. Bem, se uma classe generica possui um dado statico… cujo valor 1… Todas as classe que a utilizarem (a classe generica) possuiram o valor 1 do dado. Agora se alterarmos na classe generica o valor do dado p/ por exemplo 2, todas as classe q utilizam ( a classe generica ) teram o valor 2. Um exemplo p/ ficar mais claro da logica… Eh soh imaginarmos o jogo pac-man… Por que todos os fantasminhas (objetos) fogem quando o comecome (objeto) se alimenta das frutas? :wink: Ai estah um exemplo na pratica do uso de static.
Gostei do artigo…
PJ2002.

R

Exatamente. Como soh existe uma unica referencia na memoria, caso alguem altere o valor, o efeito sera global. Uma saida para garantir a seguranca, caso o valor nao possa ser alterado de maneira alguma, eh simplesmente declarar como “final” tambem.

Rafael

G

Lá vai mais algumas dicas:

– Métodos estáticos nunca são VIRTUAIS, e não podem ser sobreescritos (Overriding) em suas subclasses! Isso explica a impossibilidade de usar Polimorfismo, onde qualquer referência é resolvida através de early binding!

– Static são úteis para membros, seja uma variavel ou metodo, que não depende da instância de uma classe, isto é, quando não existe nenhum vínculo/dependencia com o estado de um objeto.

– membros statics são corregados em memória assim que o programa é executado.

– Ah, uma outra coisa interessante… o metodo entry point main() precisa ser static justamente pq a VM nao cria nenhuma instancia de sua classe.

Espero ter contribuído!

Gerson K.

R

Eu nao sei exatamente como definir, mas é possivel sobrescrever um metodo static:

class Pai
{
	public static void escreve()
	{
		System.out.println("Pai");
	}
}

class Filho extends Pai
{
	public static void escreve()
	{
		System.out.println("Filho");
	}
}

public class OverrideStatic
{
	public static void main(String args[])
	{
		Pai p = new Pai();
		p.escreve();
		
		Filho f = new Filho();
		f.escreve();
		
		Pai p2 = new Filho();
		p2.escreve();
	}
}

Resultado:

Pai
Filho
Pai

Note que, ao contrario de um metodo normal, chamar

p2.escreve();

chama o metodo da classe Pai, ao contrario da classe Filho, o que eh a acao a acontecer em um metodo “normal”. A especificacao diz que metodos static sao explicitamente “final”, tanto que se voce remover a palavra-chave “static” da classe Filho, um erro de compilacao ira ocorrer. Mas com a assinatura igual, funciona.

Rafael

G

Rafael,

Não dá pra sobreescrever um método estatico não. O que acontece é que existe uma sobreposição de método, onde um deles fica oculto.

O método “p2.escreve()” chamou o método da classe pai justamente pq um método estático não é virtual, diferentemente dos métodos non-static, que por padrão, são implicitamente virtuais (diferentemente de C++). Não sei se está claro esse conceito… Se não, procure por “Virtual Function”.

Não lembro onde exatamente lí isso… Mas, de qquer forma, é só dar uma olhada no proprio tutorial da sun.

"Also, a subclass cannot override methods that are declared static in the superclass. In other words, a subclass cannot override a class method. A subclass can hide a static method in the superclass by declaring a static method in the subclass with the same signature as the static method in the superclass. "

http://java.sun.com/docs/books/tutorial/java/javaOO/override.html

Espero ter contribuído!

Gerson K.

P

gerson e rafael, voces estao falando a mesma coisa

metodos statics nao podem ser reescritos, apenas hidden (pensem e faz todo sentido do mundo isso acontecer)

outra coisa. eh mais facil lembrar eh o seguinte: o unico lugar em que ocorre chamada de metodo virtual sao em metodos de instancia. de todos os outros jeitos, a resolucao ocorre em TEMPO DE COMPILACAO

entao se PAI e FILHO tiverem um public int x, e voce fizer

Pai p = new Filho();
imprime(p.x);

vai sair a variavel do Pai mesmo, e nao do filho, pq existem DUAS. a do filho apenas escondeu a do pai em determinadas situacoes

Geron. membros estaticos NAO sao carregados quando o programa executa. Eles sao carregados quando o ClassLoader le a classe X, e se esse X tiver membros etaticos, eles sao carregados.

E

Mas se você fizer Pai p = new Filho(); System.out.println(p.x); Vai imprimir o x do pai de qualquer maneira. Dinamic binding só ocorre com métodos.

R

Sim, eu li a JLS depois que tinha postado a minha msg, pois tava vendo uns lance com protected tambem, e la falava do hidding e tal.

Rafael

P

exatamente, eh o que eu e o gerson falamos acima!

U

Pessoal,

Outro dia estava lendo um ótimo tutorial no JavaRanch, How my Dog learned Polymorphism e lá diz que Java sempre faz late-binding. Por exemplo, se eu executar…

Animal d = new Dog(); d.play();

…o método [color=“blue”]play()[/color] chamado será da classe [color=“blue”]Dog[/color], e não da classe [color=“blue”]Animal[/color].

Late-binding, então, ocorre apenas para métodos, e não para variáveis?

P

“Rob Fleming”:
Pessoal,
Late-binding, então, ocorre apenas para métodos, e não para variáveis?

exato
associacao de atributos sao resolvidos em tempo de compilacao (early binding), metodos nao estaticos sao resolvidos em tempo de execucao (virtual method invocation, melhor q “late binding”)

U

Saquei :slight_smile: . Valeu! :smiley:

G

Olá pessoal,

Quero dizer que adorei o artigo, muito bom mesmo excelente consegui entender pelo menos basicamente o que rola com o método static, que inclusive a Sun adora pedir na prova de cerificação né!!

Gostaria de saber se vocês teriam em mente os mesmos artigos só que falando a fundo do private e do protected, essas são minhas grandes dúvidas;

Estou fazendo o SL110, e o SL275 da SUN, e tentarei a prova de certificação. O SL110 é muito fraquinho, nem cobre a fundo a questão dos modificadores. Acho muito interessante artigos como este.

Espero que o SL275 cubra :o)

Obrigado pessoal!!!

B

Sobre modificadores de acesso não existem grandes segredos e peculiaridades, mas já escrevi um artigo a respeito, que encontra-se no seguinte endereço:
http://www.portaljava.com/home/modules.php?name=Sections&op=viewarticle&artid=19

H

Estava lendo mais atentamente o artigo e percebi um equívoco no primeiro exemplo completo, o do “contador”. Na verdade a variável "contador é zerada no construtor, assim como a variável “outroContador”, só que, como todos os objetos são criados sucessivamente ele não demostra sua real funcionalidade. Se fosse implemetada desta fora:

public class TesteStatic
{
    public static void main(String args[])
    {
        Classe1 c1 = new Classe1();

        c1.incrementaContador();
        c1.incrementaOutroContador();

        Classe1 c2 = new Classe1();

        c2.incrementaContador();
        c2.incrementaOutroContador();

        Classe1 c3 = new Classe1();

        c3.incrementaContador();
        c3.incrementaOutroContador();

        Classe1 c4 = new Classe1();

        c4.incrementaContador();
        c4.incrementaOutroContador();
    }
}

… o resultado seria o seguinte:
contador agora é 1
outroContador agora é 1
contador agora é 1
outroContador agora é 1
contador agora é 1
outroContador agora é 1
contador agora é 1
outroContador agora é 1

Então por que do resultado obtido é correto no formato original do artigo? Porque quando criado cada instância de “Classe1”, ele cria uma cópia para cada objeto de “outroContador” na memória, mas isso não acontece para “contador”, que existe apenas uma cópia na memória para todas as instância e inclusive para a própria classe “Classe1”.
O artigo é muito interessante e me valeu de muitas informações que eu não dispunha, e se alguém encontrar mais algum equívoco no que escrevi, ficaria grato de ser corrigido.
Valeu galera

R

Ok, vc esta certo. Atualizei ja o tutorial para corrigir esse problema. Valeu.

Rafael

W

Otimo artigo

A

Maravilha de artigo hein…parabéns…

T

Muito bom… para mim esclareceu bastante coisa, obrigado!!

L

muito bom.

R

O livro da Kathy dá uma boa explicação sobre static, mas o artigo é muito bom e ajudou a sedimentar os conhecimentos.
Parabéns!

M

Amigo, muito bom esse seu artigo, realmente me ajudou muito nas aulas de programação !

Continue com o grande trabalho.

Abraços

A

mt bom o tutorial… parabens ao autor.
mt bem explicado !

conseguiu sanar algumas duvidas com relação ao static :stuck_out_tongue:

abs !

H

Pessoal,

e no caso de classes inteiras static? O funcionamentoi é o mesmo, não há nenhuma restrição?

como:

static class teste {
// bla, bla, bla
}
H

Hanzi_West

Statc Class geralmente é usado em Nested Class, mas nunca são instaciadas, é como a classe JOptionPane vc nunca vai ver um objeto dessa classe.

flw

www.heberfa.com.br

D

heberfa:
…é como a classe JOptionPane vc nunca vai ver um objeto dessa classe.
:shock:

Nada impede que se crie uma instância de um JOptionPane. Teste ai para você ver.

Para ver as razões para se criar uma classe static, dê uma olhada aqui.

[]´s

S

Eu escrevi um artigo sobre o modificador static!
http://labs.sadjow.com/2008/08/10/palavra-chave-static/
Espero que gostem!
Vlw! :smiley:

M

Paulo Silveira:
Um método static realmente se parece com uma funcao
Cabe a voce a decisao de onde ele deve ficar. Pois voce pode mudar muito bem onde o metodo estatico esta para outra classe, sem maiores problemas.

:arrow: A Palavra-chave static permite que um método seja executado sem qualquer instância da classe.Um método ser estático significa que o comportamento não depende de uma variável de instância, portanto não são necessárias instâncias/objetos.Apenas a Classe.

L

Puxa cara, adorei o artigo mesmo, muito explicativo, principalmente para mim, que estou começando a gostar de java, faço sistema de informação e estou querendo seguir como programador.

Valeu

T

parabéns pelo artigo!

quase impossível encontrar um artigo bom que dê exemplos e explique bem como esse!

nota:10

:wink:

R

Muito bom o material!

Tirou várias dúvidas que ainda tinha sobre o static!

Valeu!

R

Muito bom o material!

Tirou várias dúvidas que ainda tinha sobre o static!

Valeu!

D

Parabens pelo artigo: http://labs.sadjow.com/2008/08/10/palavra-chave-static/

M

Minha dúvida é a respeito de acessar o atributo, sendo ele privado, em uma outra classe.

Mesmo usando o exemplo de getter da apostila não funcionou. :frowning:

E mais uma dúvida noob, o pro que disso: public Classe!() [color=red]{}[/color] essas chaves

Obrigado.

M
Aprendi:
public class Conta {
  
	private int numero;
	private double saldo;
	private double limite;
	private Cliente titular;
	private static int contador = 0;
	
	public Conta (Cliente titular) {
		this.titular = titular;
		 contador++;
		  System.out.println("Conta criada de numero: " + contador);
	}
	public Cliente getTitular() {
		return titular;
	}
	public void setNumero(int numero) {
		this.numero = numero;
	}
	public int getNumero() {
		return numero;
	}
	public void setSaldo(double saldo) {
		this.saldo = saldo;
	}
	public double getSaldo() {
		return saldo;
	}
	public void setLimite(double limite) {
		this.limite = limite;
	}
	public double getLimite() {
		return limite;
	}
	public static int getContador() {
		return contador;
	}
	public static void mostra () {
		System.out.println ("Numero total de contas: " + getContador ());
	}
	
	
}
public class Cliente {
	
	private String nome;
	private String CPF;
	
	public String getCPF() {
		return CPF;
	}
	public void setCPF(String cPF) {
		CPF = cPF;
	}
	public String getNome() {
		return nome;
	}
	public void setNome(String nome) {
		this.nome = nome;
	}

}
public class TestaTudo {
  public static void main (String [] args) {
	  
	  Cliente marcos = new Cliente ();
	  marcos.setNome("Marcos");
	  marcos.setCPF("[CPF removido]");
	  Conta c1 = new Conta (marcos);
	   System.out.println("Nome do titular: " + c1.getTitular().getNome());
	   System.out.println("Numero do seu CPF: " + c1.getTitular().getCPF());
	   
	   
	   System.out.println();
	   
	  Cliente cida = new Cliente ();
	  cida.setNome("Cida");
	  cida.setCPF("[CPF removido]");
	  Conta c2 = new Conta (cida);
	   System.out.println("Nome do titular: " + c2.getTitular().getNome());
	   System.out.println("Numero do seu CPF: " + c2.getTitular().getCPF());
		
		   
	   System.out.println();
	   
	  Cliente rachel = new Cliente ();
	  rachel.setNome("Rachel");
	  rachel.setCPF("[CPF removido]");
	  Conta c3 = new Conta (rachel);
	   System.out.println("Nome do titular: " + c3.getTitular().getNome());
	   System.out.println("Numero do seu CPF: " + c3.getTitular().getCPF());
	   
	   System.out.println();
	  
	 Conta.mostra ();
  }
}
Conta criada de numero: 1
Nome do titular: Marcos
Numero do seu CPF: [CPF removido]

Conta criada de numero: 2
Nome do titular: Cida
Numero do seu CPF: [CPF removido]

Conta criada de numero: 3
Nome do titular: Rachel
Numero do seu CPF: [CPF removido]

Numero total de contas: 3

Vou incrementar mais.

S

Saquei, muito bom mesmo… :smiley:

W

Como ficaria um método de classe (static) que efetuam cálculos, formatações, etc, sem precisar acessar valores staticos da classe mas sim passados por parâmetros em um ambiente multi-thread?

Como o método é estático e só existe uma única instância dele no processo da jvm, se duas ou mais threads acessarem esse método e passar valores diferentes em seus parâmetros, qual seria o tratamento?
Cada thread teria em sua pilha de execução uma cópia desses valores e o método trataria de forma diferente ou
O valor da segunda thread acabaria afetando o valor da primeira, comprometendo a atomicidade do método?

Seria necessário criar um método thread-safe caso ele seja declarado como static para evitar as "condições de corrida"?

Alguém pode me ajudar?

Vide exemplo de código:

public class StaticValorUtil {


	public static String asString(Object vlr){
		return vlr.toString();
	}
	
	public static Integer asInteger(Object vlr){
		return Integer.parseInt(asString(vlr));
	}
}

Agora a classe que será a thread

public class Gerente implements Runnable{
	
	private String id;
	private int inicio;

	public Gerente(int inicio, String id){
		this.id = id;
		this.inicio = inicio;
	}

	@Override
	public void run() {
		for(int i = inicio; i < inicio + 100; i++){
			System.out.println("Executando linha " + ValorUtil.getInstance(i).asInteger() 
					+ " da thread " + ValorUtil.getInstance(id).asString());
		}
		
	}

}

Agora o cliente que iniciará a thread

public static void main(String[] args) {
		Gerente g1 = new Gerente(0,"Gerente 1");
		Gerente g2 = new Gerente(200, "Gerente 2");
		Gerente g3 = new Gerente(300,"Gerente 3");
		Gerente g4 = new Gerente(400,"Gerente 4");
		Gerente g5 = new Gerente(500,"Gerente 5");
		
		Thread t1 = new Thread(g1);
		Thread t2 = new Thread(g2);
		Thread t3 = new Thread(g3);
		Thread t4 = new Thread(g4);
		Thread t5 = new Thread(g5);
		
		Gerente g6 = new Gerente(600, "Gerente 6");
		Gerente g7 = new Gerente(700, "Gerente 7");
		Gerente g8 = new Gerente(800, "Gerente 8");
		Gerente g9 = new Gerente(900, "Gerente 9");
		Gerente g10 = new Gerente(1000, "Gerente 10");
		
		Thread t6 = new Thread(g6);
		Thread t7 = new Thread(g7);
		Thread t8 = new Thread(g8);
		Thread t9 = new Thread(g9);
		Thread t10 = new Thread(g10);

		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
		t6.start();
		t7.start();
		t8.start();
		t9.start();
		t10.start();
		
	}
	
}

É possível garantir, sem o uso de synchronized, que, apesar do método ser estático, que os valores dos parâmetros passados por uma thread para o método "asInteger()" da classe "StaticValorUtil" não sejam afetados por outra thread??

D

Pelo que eu entendi, a variável passa a pertencer a classe, e seu valor passa a propagar-se por todas as outras sub-classes. Por exemplo, se a variável letra tiver A como seu valor e depois ela passa a ter B, todas as instâncias do objeto terão o mesmo valor. Isso não impede de tratar a variável como eu quiser dentro da sub-classe, tanto que eu vi um exemplo aqui do forum a soma da variável dentro de um método. Entendi também que serve tanto para Classes, métodos e objetos.

R

Excelente artigo!

A

Rafael,

Demais sua explicação do que é static fiz os exemplos, uma luz brilhou no fim do túnel.
rsrsrsrs…mas, ainda não consigo identifica quando usar e quando não usar…
Abraços!
:roll:

J

Boa tarde pessoal estou começando a ver java agora
na faculdade porem estou tendo dificuldade em
usar metodos para chamar outra classe
gostaria de algumas dicas por favor.

J

Cara, muito bom o tópico. Ajudou muito a compreender. Eu sabia que precisaria do static mas não sabia porque usá-lo. Vou continuar lendo e relendo isso pra entrar na cabeça ^^

Valeu.

Criado 11 de janeiro de 2003
Ultima resposta 2 de out. de 2012
Respostas 45
Participantes 36