Pessoal, agradeço as respostas e a disposição em ajudar. Mas quando disse que respostas do tipo “Não tem porque não precisa.” não ajudavam na discussão, eu estava falando sério.
Não sou exatamente novato em Java. Na verdade já trabalho com a linguagem desde 96, o que me confere uma certa experiência. Sei perfeitamente que quando se declara
String s = "oi!";
O ‘s’ é uma referência (ponteiro se preferirem) ao objeto em memória, e que a declaração
String t = s;
Não copia o “conteúdo” de ‘s’ para ‘t’, mas ao invés faz com que ‘t’ seja uma segunda referência para o mesmo objeto e todas as demais pérolas que foram colocadas nas respostas. Sei perfeitamente como contornar as limitações que a falta de argumentos por referência impõem a linguagem. A pergunta não é sobre esses tópicos. A pergunta é
“POR QUE Java não tem passagem de argumentos por referência.”
Quanto a questão de não precisar porque dá para simular com arrays, porque objetos são sempre passados por referência, etc. Digamos que eu queira trocar o valor de duas variáveis (operação extremamente comum em vários algoritmos). O óbvio para quem está habituado a programação estruturada (da qual a OO é uma extensão) é criar uma função que realize a operação. Em Java essa operação trivial (e muito útil) vira um “inferno”. Vejam o código abaixo:
Em C:
void swap(int *a, int *b) {
int x = *a;
*a = *b;
*b = x;
}
Em pascal:
procedure swap(var a, b: integer);
var x: integer;
begin
x := a;
a := b;
b := x;
end;
Em C++ usando templates (generics)
template <T> void swap(T &a, T &b) {
T x = a;
a = b;
b = x;
}
Em Java:
Tentativa 1:
void swap(int a, int b) {
int x = a;
a = b;
b = x;
}
Falha por razões óbvias.
Tentativa 2:
<code>
void swap(Integer a, Integer b) {
Integer x = a;
a = b;
b = x;
}
</code>
Também falha, pois apesar de a referência me permitir alterar o objeto (nem isso nesse caso porque objetos Integer não tem acessores – setters e getters – são objetos constantes) a referência em si é passada por VALOR o que significa que as atribuições a ‘a’ e ‘b’ serão perdidas ao final do método.
Tentativa 3:
void swap(int[] v) {
assert(v.length == 2);
int x = v[0];
v[0] = v[1];
v[1] = v[0];
}
O método realiza a operação desejada, inclusive com persistência do efeito colateral após o final da execução, entretanto se interpõe um outro problema. A sintaxe desejada para a função seria.
p = /* algum valor */;
...
q = /* um outro valor */;
....
swap(p, q); /* valores de p e q são trocados */
A versão do método da tentativa 3 não funciona. Vejam o código abaixo:
int[] w = {p, q};
swap(w);
Quando o vetor ‘w’ acima é construído ele armazena os VALORES de p e q e não referências. Desta forma, quando o método ‘swap’ for executado ele irá trocar com sucesso o conteúdo das posições 0 e 1 do vetor ‘w’ mas não o conteúdo das variáveis p e q.
É evidente que é possível trabalhar com a linguagem mesmo com esta limitação. Certamente não é NECESSÁRIO ter passagem de argumentos por referência, entretanto TODAS as linguagens estão CHEIAS de coisas que não são necessárias, mas que facilitam o uso da linguagem. Estritamente falando, nenhuma linguagem precisa de mais do que IF e RECURSÃO. Nem a atribuição de valores é necessária (lembram das aulas de Teoria da Computação e de Linguagens Formais e Autômatos? pois é eu dou aulas dessas coisas). Não é necessário ter FOR se você tem WHILE, não é necessário ter SWITCH se você tem IF. Não é necessário ter BOOLEAN se você tem INTEGER. Mas as linguagens tem para facilitar a vida do programador, reduzir a quantidade de erros semânticos no processo de compilação, ou seja, para ser mais fáceis e eficientes de serem usadas.
Passagem de argumentos por referência é um recurso extremamente poderoso, especialmente em uma linguagem que não trabalho com apontadores. Se alguém tem dúvidas quanto a isso consulte referência apropriada sobre paradigmas de programação na parte de programação imperativa. O livro do Sebesta é muito bom.
O que eu quero saber é por que uma característica tão útil e comum foi deixada de fora do projeto da linguagem. Qual é a justificativa da SUN para isso. Não como contornar o problema. Isso eu já sei.
Grato pela atenção de vocês e por qualquer indicação de documentação da SUN que possa esclarecer a dúvida.
Sds,
Prof. Jefferson O. Andrade, M.Sc.
CEFETES/UnED-Serra