Archive Page 2

Java passa por valor: sempre!

Foi publicada uma thread no The Server Side sobre um dos conceitos mais básicos da linguagem Java e que causa bastante confusão. Trata-se da passagem de parâmetros, que no caso da linguagem Java sempre ocorre por valor.

Exatamente, não existe passagem de parâmetros por referência na linguagem Java. Vejamos um exemplo básico:

class Test{
    public static void main(){
        int a = 10;

        soma5(a);

        System.out.println(a);
    }

    static void soma5(int num){
        num += 5;
    }
}

ou seja, como esperado, a soma dentro do método soma5 não afeta a variável original a, no escopo de main, de forma que será impresso o valor 10. Agora vejamos outro exemplo:

class Test{
    public static void main(){
        A a = new A();
        
        a.a = 10;

        soma5(a);

        System.out.println(a.a);
    }

    static void soma5(A a){
        a.a += 5;
    }
}

class A{
    int a;
}

Como esperado, o valor impresso será 15. Isso porque o objeto a foi passado por referência para o método soma5, correto ? ERRADO. E aqui está a armadilha! Objetos nunca são passados por parâmetro, objetos residem na heap e sempre devem ser acessados através de variáveis de referência. E são as referências que são passadas para os métodos. E da mesma maneira que variáveis de primitivos, elas são passadas por cópia para os métodos. Como o método que recebeu o parâmetro recebeu uma cópia, então o método altera o mesmo objeto.

É importante que este conceito fique bastante claro para evitar o seguinte tipo de erro:

class Test{
    public static void main(){
        A a = new A();
        
        a.a = 10;

        soma5(a);

        System.out.println(a.a);
    }

    static void soma5(A a){
        a = new A(); //esse objeto novo será marcado para gc assim que soma5 terminar
        a.a += 5;
    }
}

class A{
    int a;
}

nesse caso, a saída do programa é 10 porque o objeto original não será afetado pelo método soma5. Apesar do método receber a referência para o objeto criado em main este valor é perdido na atribuição a = new A() dentro de soma5. Porém, esta atribuição não afeta a variável “a” em main, justamente porque soma5 recebe uma cópia da referência.

A discussão original pode ser vista aqui:

http://www.theserverside.com/discussions/thread.tss?thread_id=61622

Anúncios

Categorias

Atualizações Twitter