Repare que, na secção 6.3.1., em cada um dos métodos imprimeTabuadas
e imprimeMultiplos
, definimos um parâmetro chamado m
.
Lembra-se do que dissemos na Secção 4.4. acerca do âmbito das variáveis (e parâmetros)?
Então, em termos de memória, os dois parâmetros m
não têm nada em comum, pois são declarados em métodos diferentes. São completamente independentes.
Se já experimentou executar os programas ao longo destas páginas, já está familiarizado com a forma como é usual representar o conteúdo da memória, compartimentada em blocos locais aos métodos que estão em execução.
O programa TabelaDeTabuadas
da secção 6.3.1. é muito revelador dessa "localidade" das variáveis, pois em muitos dos seus passos de execução existem três blocos de memória, associados aos três métodos (main
e imprimeTabuadas
em standby e imprimeMultiplos
em execução).
Para quem, por alguma razão, não experimentou executar esse programa, vamos supor que o programa TabelaDeTabuadas
está em execução e que a instrução que está a ser executada é System.out.print(n * i + " ")
do método imprimeMultiplos
para valores 3 e 10 dos seus parâmetros e quando a variável i
local ao método tem o valor 5.
Esta execução, em particular, deste método, terá resultado da invocação imprimeMultiplos(3,10)
a partir do método imprimeTabuadas
, quando a variável local linha
tem o valor 3.
Podemos representar o estado da memória nesse momento da seguinte forma:
Repare nas duas variáveis de nome m
, uma em cada bloco local a um método. Embora neste caso as duas refiram exatamente o mesmo valor, pois representam o mesmo conceito (só que em contextos diferentes), nem sempre isto acontece. Podemos ter duas variáveis com o mesmo nome, em contextos diferentes, que tenham significados e valores completamente diferentes.
Também os blocos das instruções if
e for
definem contextos locais para as variáveis neles definidas. Inspecione o seguinte programa:
xpublic class EscreveTabuada {
public static void main(String[] args) {
for (int i = 1 ; i <= 10 ; i++) {
System.out.println(i * 7);
}
System.out.println(i * 7);
}
}
Como o ciclo termina quando i
fica com o valor 11, poder-se-ia pensar que a última instrução (já fora do ciclo) imprimiria o valor 77. Mas isso não é verdade pois o programa tem um erro de compilação:
xxxxxxxxxx
EscreveTabuada.java:8: error: cannot find symbol
System.out.println(i * 7);
^
symbol: variable i
location: class EscreveTabuada
1 error
O problema aqui é que a variável i
é local ao ciclo for
, pois foi declarada no contexto do ciclo, na parte da inicialização. Por isso só é conhecida no âmbito do ciclo.
Se precisássemos mesmo de aceder à variável de progresso fora do ciclo, teríamos que a declarar fora do ciclo, para que o âmbito de uso dessa variável fosse alargado, neste caso ao método main
.
xxxxxxxxxx
public class EscreveTabuada {
public static void main(String[] args) {
int i;
for (i = 1 ; i <= 10 ; i++) {
System.out.println(i * 7);
}
System.out.println(i * 7);
}
}
Nesta versão a variável i
é declarada antes do ciclo e é inicializada já dentro do ciclo. A última instrução do main
já estaria correta e teria como efeito a impressão do valor 77 no standard output.
A última instrução do pedaço de código seguinte também provocaria um erro semelhante. A variável i
é local à instrução condicional pois é declarada dentro do bloco do if
:
xxxxxxxxxx
int n = 3;
if (n > 0) {
int i;
for (i = 1 ; i <= n ; i++) {
System.out.println(i * 7);
}
System.out.println(i * 7);
}
System.out.println(i);
Anterior: 6.4. Ainda a abstração procedimental
Seguinte: 6.6. A instrução while