Sunteți pe pagina 1din 7

http://moodle.ufsc.br/mod/resource/view.php?

inpopup=true&id=89103

Alocação Dinâmica de Memória em Java


Programas escritos na linguagem Java podem fazer Alocação Dinâmica de Memória. Alocar dinamicamente a memória significa que a
quantidade de memória usada por um programa pode ser definida durante a execução do programa.

Em Java, o operador new é usado para alocar memória dinamicamente. Este operador, como todos sabem, é usado para instanciar
objetos e para criar arrays.

Memória do Computador
A memória de um computador pode ser entendida como sendo um gigantesco array. Cada posição deste array é chamado de endereço
de memória.

Um programa, para que possa ser executado, precisa estar armazenado em algum local na memória. As variáveis, por fazerem parte do
programa, também estão em aluma posição (endereço) na memória.

Variáveis em Java
Toda variável ocupa (gasta) alguns bytes da memória. A quantidade de bytes depende do tipo da variável. Por exemplo, se uma variável é
do tipo int entãoela ocupa, em algum local, 4 bytes (32 bits).

A linguagem Java define dois tipos de variáveis: as primitivas e as de referência.

Variáveis Primitivas

Variávei primitivas são usadas para representar números, caracter e valor lógico (booleano). Assim, por exemplo, no fragmento de código

int i;

1 de 7 21/9/2010 20:40
http://moodle.ufsc.br/mod/resource/view.php?inpopup=true&id=89103

i = 40;

podemos dizer que:

a variável de nome "i" ocupa 4 bytes da memória;


os 4 bytes ocupados pela variável "i" são usados para representar o valor 40. Dizemos então que o valor de "i" é o número 40. O
comando de atribuição é usado para atribuir um valor a uma variável.
estes 4 bytes estão em algum local na memória. Este local, a posição do primeiro dos 4 bytes, é chamado de endereço da variável.
Em Java, não temos como saber qual é o endereço de uma variável.
porque a variável "i" é do tipo int então o comando de atribuição pode ser usado apenas para atribuir um valor numérico inteiro à
variável. A expressão à direita do "=", quando avaliada, deve produzir um número inteiro.

Variáveis primitivas são chamadas de variáveis estáticas. A palavra estática, neste contexto, significa que a quantidade de bytes
alocados para que a variável possa armazenar um dado é definida durante a compilação do programa. Assim, no exemplo acima, o simples
fato da variável "i" estar declarada implica que ela já está ocupando 4 bytes, mesmo que ainda não tenhamos atribuído nenhum valor à
variável.

Variáveis Referência

Variáveis referência são usadas para representar objetos e arrays. Contudo, estas variáveis não armazenam objetos e arrays "dentro
delas". Se isso fosse possível, a quantidade de bytes gastos por uma variável dependeria da quantidade de atributos da classe do objeto
ou então do tipo e tamanho do array.

As variáveis referência armazenam o endereço (posição no array memória) onde estão localizados os objetos ou arrays. Por causa disso,
estas variáveis são chamadas de variáveis dinâmicas ou ponteiros (pointers em inglês).

Por exemplo, no código

int[] v;
v = new int[6];

dizemos que:

a variável "v" ocupa 4 bytes de memória.


os 4 bytes ocupados pela variável "v" são usados para armazenar o endereço (posição na memória) onde deve existir um array
capaz de armazenar 6 números inteiros.

2 de 7 21/9/2010 20:40
http://moodle.ufsc.br/mod/resource/view.php?inpopup=true&id=89103

como a variável "v" é dinâmica, ela armazena endereço de memória (e não outro tipo de dado).
a expressão "new int[6]" deve ser compreendida da seguinte forma:
ao ser executada, a Máquina Virtual Java (MVJ) procurará na memória um local com 24 (6 * 4) bytes livres. Encontrando este
local, os 24 bytes são reservados para que seja possível armazenar, no futuro, 6 números inteiros. Em cada posição deste
array o valor inicial é o número zero.
se a MVJ não conseguir encontrar 24 bytes livres na memória então a execução do programa é interrompida porque
literalmente não há memória suficiente.
se a MVJ conseguiu encontrar 24 bytes livres na memória então estes 24 bytes estão localizados em algum local, algum
endereço. Considera-se que o endereço do array é a posição do primeiro dos 24 bytes. Este endereço é o valor resultante da
avaliação da expressão "new int[6]" e será o valor atribuído à variável "v".
dizemos então que a variável "v" não contém o array (se fosse assim "v" teria que ocupar 24 bytes da memória) mas sim o
endereço onde está localizado o array. Dito de outra forma, a variável "v" aponta para o array.
ao final da execução do comando de atriuição, terão sido gastos 28 bytes de memória: 24 bytes necessários para armazenar 6
números inteiros e mais 4 bytes da variável "v" para armazenar o endereço deste array.

Se uma variável "x" é dinâmica, do tipo referência na terminologia Java, então o comando de atribuição só pode ser usado para atribuir
valores do tipo endereço de memória a esta variável. As únicas formas de se atribuir um valor para este tipo de variável são:

x = null; // o dado "null" representa "nenhum endereço válido"

x = y; // o valor de x passa a ser igual ao valor de y.

x = new ...; // o valor de x será o endereço onde foi alocado um objeto ou um array

Observe que, nos três casos acima, o comando de atribuição funciona como sempre funcionou: ele é usado para atribuir um valor a uma
variável.

Nos casos acima, é possível saber o endereço onde está localizado o objeto ou o array pois o endereço é o valor da variável x.

Em Java não é possível:

saber o endereço de uma variável


representar um endereço de memória explicitamente. Não posso, por exemplo, atribuir à variável x o endereço 50.
realizar operações aritméticas com endereço. Não posso, por exemplo, executar x = x + 1; pois não é possível somar dois
endereços.

3 de 7 21/9/2010 20:40
http://moodle.ufsc.br/mod/resource/view.php?inpopup=true&id=89103

Passagem de parâmetros
Na linguagem Java a passagem de parâmetros se dá por valor. Assim, por exemplo, na expressão

o.m(p);

o objeto "o" está recebendo a ordem "execute o método "m" sendo que este método exige um valor que será o valor da expressão "p".

Supondo que o método "m" tenha a seguinte assinatura

public void m(int x) {


...
}

então é perfeitamente válido invocar a execução de "m" nas seguintes formas:

o.m(50); // o valor da expressão é o número 50

o. m(50 + 30); // o valor da expressão é o número 80

o.m(k); // o valor da expressão é o valor da variável k

o.m(k + 20); // o valor da expressão é o valor da variável k mais 20

o.m(m2()); // o valor da expressão é o valor resultante da execução do método m2 que deve retornar um dado do tipo int

Observe o seguinte fragmento de código Java:

int v = 10;
m(v);
System.out.println(v);

...

4 de 7 21/9/2010 20:40
http://moodle.ufsc.br/mod/resource/view.php?inpopup=true&id=89103

public void m(int v) {


v = v + 10;
}

Porque em Java só existe passagem de parâmetros por valor sabemos que o valor que será mostrado na tela (System.out.println(v)) é 10
pois na invocação do método m a variável "v" só é usada para definir o valor do parâmetro. Em outras palavras, a variável "v" definida no
método "m" não tem nenhuma relação com a variável "v" declarada no início do fragmento Java. É apenas uma coincidência que estas
duas variáveis tenham recebido o mesmo nome.

Mas agora observe o seguinte fragmento de código Java:

int[] v = new int[3];

v[0] = 34;
v[1] = 25;
v[2] = 68;

m(v);
System.out.println(v[0]);

...

public void m(int[] k) {


k[0] = 99;
}

Qual será o valor exibido na tela quando a expressão "Sytem.out.println(v[0]);" for executada? 34 ou 99?

A resposta correta é 99. Você consegue entender por quê?

Vamos imaginar que a expressão "new int[3]" tenha retornado o endereço 5B9 (número hexadecimal) ou no endereço 5B9 foi alocado um
array capaz de armazenar 3 números inteiros.

A execução da expressão "m(v)" pode ser traduzida da seguinte forma: execute o método "m" levando como parâmetro o valor da
variável "v", ou seja, o endereço 5B9 onde está localizado um array.

5 de 7 21/9/2010 20:40
http://moodle.ufsc.br/mod/resource/view.php?inpopup=true&id=89103

Quando o método m vai ser executado, a primeira coisa que é feita é definir o valor da variável "k". No exemplo em questão, o valor de
"k" será o endereço 5B9. Assim, a variável "k" "sabe" que no endereço 5B9 existe um array de números inteiros.

A expressão "k[0] = 99" pode ser traduzida da seguinte forma: altere o valor do primeiro número do array que está localizado no
endereço indicado pela variável "k".

Durante a execução do método "m" nós temos duas variáveis ("v" e "k") que apontam para o mesmo array. Portanto, como só existe um
único array, qualquer alteração feita nele é "permanente".

Em termos práticos dizemos que quando um array é passado como parâmetro qualquer alteração nele será permanente. Sabemos agora
porque isso acontece: não é o array que é passado como parâmetro mas sim o seu endereço.

O mesmo raciocínio se aplica quando a variável representa um objeto. Não passamos objetos como parâmetros, mas sim o endereço dos
objetos.

Ao passarmos como parâmetro um endereço temos o mesmo efeito da passagem de parâmetros por referência. Mas, lembre-se, em Java
só existe passagem de parâmetros por valor.

A título de curiosidade, se houvesse passagem de parâmetro por referência em Java, o valor mostrado na tela para fragmento de código
Java seria 5. No entando, será mostrado o valor 3 pois a variável "v" aponta para um array de tamanho 3.

int[] v = new int [3];

m(v);
System.out.println(v.length);

...

public void m(int[] v) {


v = new int[5];
}

6 de 7 21/9/2010 20:40
http://moodle.ufsc.br/mod/resource/view.php?inpopup=true&id=89103

Você acessou como Carlos Alberto Machado Costa (09138004) (Sair)

7 de 7 21/9/2010 20:40

S-ar putea să vă placă și