Programação Orientada a Objetos - Instância de Classes
Autor: Guilherme Viterbo Galvão | Publicado: 2012-10-29T17:37:00-07:00

Programação Orientada a Objetos - Instância de Classes


Nesse post eu vou falar sobre o que é uma instância de classe e sobre qual é a diferença entre uma variável primitiva e uma de referência. Para isso vamos precisar do seguinte código:



class Carro{
&nbsp;&nbsp; //métodos e propriedades e construtores

&nbsp;&nbsp; public static void main(String[] args){
&nbsp; &nbsp; &nbsp;&nbsp; Carro c;
&nbsp; &nbsp; &nbsp;&nbsp; c = new Carro('Palio'); 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c.setAno(2002);
&nbsp;&nbsp; } 
}



O que acabamos de fazer foi declarar uma variável de referência do tipo "Carro" e apilidamos ela de "c". Dizemos que ela é uma variável de referência pois ela apenas está se referênciando a um objeto na memória RAM.
&nbsp; 
"Entendi, então ela funciona igual a um ponteiro do C++?"

NÃO! No java nós não temos ponteiros, nós apenas temos variáveis que se referenciam a uma região da memória RAM. A diferença entre ponteiros e referência é simples, o ponteiro é que fica, de certa forma, responsável por excluir o objeto da memória RAM após ele ter sido usado, já as variáveis de referência não, elas servem apenas para acessar uma região da memória e não possuem responsabilidade nenhuma em limpá - la.

"Mas então a minha memória vai começar a lotar se eu não limpá - la"

Sim e não! Isso aconteceria se o java não tivesse o maravilhoso Coletor de Lixo (ou Garbage Collector). É ele que sempre aponta para os objetos que você instancia e ele quem decide quando limpar a memória RAM.

"Mas como ele sabe a hora certa de limpar a memória?"

Essa pergunta não é tão fácil de explicar, pois ele faz a limpeza sempre seguindo algumas normas para que o seu código não dê erros. Vou tentar explicar de forma simples. Vamos tomar como exemplo o código abaixo:



class Carro{
&nbsp;&nbsp; //métodos e propriedades e construtores


&nbsp;&nbsp; public static void main(String[] args){
&nbsp; &nbsp; &nbsp;&nbsp; Carro c;
&nbsp; &nbsp; &nbsp;&nbsp; c = new Carro('Palio'); 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c.setAno(2002);

&nbsp; &nbsp; &nbsp;&nbsp; Carro c2 = c; 

&nbsp; &nbsp; &nbsp;&nbsp; c = null;

&nbsp; &nbsp; &nbsp;&nbsp; c2 = null;
&nbsp;&nbsp; } 

}



Para entender como são essas regras de decisão para descartar o objeto, teremos que depurar o código mentalmente. Quando criamos o carro Palio (c = new Carro('Palio'); ), a JVM entende que estamos criando um objeto e o aloca em uma posição específica da memória RAM e o adiciona um indíce que diz quantas variáveis o apontam, nesse momento 1. Mais abaixo dizemos que a variável de referência "c2", referência-se a "c", que por sua vez referência-se a uma objeto na memória RAM que "é um Palio", então "c2" está apontando para o mesmo Palio que "c". Nesse ponto a JVM diz que o indíce do objeto é 2. Mais abaixo estamos dizendo que "c" agora é nulo e quando a JVM executar o GC(Garbage Collector) ele irá ver apenas uma variável de referência aponta para Palio, logo ele irá decrementar o seu indíce, passando - o para 1. Seguindo em frente o nosso código diz que "c2" é nulo e quando a JVM executar o GC ela irá executar o mesmo procedimento, passando o indíce do objeto Palio de 1 para 0 nesse ponto a JVM percebe que ninguém está utilizando esse objeto e que não tem como ninguém referenciá - lo, sendo assim o remove da memória deixando os bytes que ele ocupava livre.

Existem outros fatores que implicam na decisão da remoção do objeto na memória RAM por parte da JVM, um deles é se outra thread têm acesso a uma referência do objeto. Mas isso é um assunto muito longo e detalhado, o que você precisa saber é que ele funciona +/- da forma dita acima (irá te ajudar muitooooo no dia-a-dia). Caso queira mais informações detalhadas GOOGLE =).

Vamos agora falar das variáveis primitivas. É bem simples, quando declaramos uma variável primitiva é como se criácemos uma caixa dizendo o quanto ela suporta e logo após colocamos algo dentro dela.&nbsp; O código expressa isso:



//classe
//main

int valor = 1; 

float valor2 = 2.55;

valor2 = valor; 

System.out.println(valor);
System.out.println(valor2); 

//fim da classe



Declaramos que a "caixa" valor é do tipo int, logo ela suporta coisas que um int suporta e "colocamos dentro dela" o valor 1. Fizemos a mesma coisa com o valor2. Abaixo dizessemos que valor2 aponta para valor, certo? Errado as variáveis do tipo primitivo não apontam, ou elas apenas possuem valores. Estamos falando que valor2 agora possui dentro de si o mesmo que valor, ou seja ambas as variáveis estão valendo 1.

Bom é isso pessoal até o próximo post onde iremos falar de métodos construtores! 

 prettyPrint();