As referências podem ser implementadas armazenando o endereço. Geralmente, as referências Java serão implementadas como ponteiros, mas isso não é exigido pela especificação. Eles podem estar usando uma camada adicional de indireção para facilitar a coleta de lixo. Mas no final (quase sempre) se resume a ponteiros (no estilo C) envolvidos na implementação de referências (no estilo Java).
Você não pode fazer aritmética de ponteiro com referências. A diferença mais importante entre um ponteiro em C e uma referência em Java é que você não pode realmente obter (e manipular) o valor subjacente de uma referência em Java. Em outras palavras: você não pode fazer aritmética de ponteiro.
Em C, você pode adicionar algo a um ponteiro (ou seja, o endereço) ou subtrair algo para apontar para coisas que estão "próximas" ou para lugares que estão em qualquer lugar.
Em Java, uma referência aponta para uma coisa e apenas essa coisa. Você pode fazer uma variável manter uma referência diferente , mas não pode simplesmente pedir que aponte para "a coisa após a coisa original".
As referências são fortemente digitadas. Outra diferença é que o tipo de uma referência é muito mais rigorosamente controlado em Java do que o tipo de um ponteiro em C. Em C, você pode ter um int*
e convertê-lo em um char*
e apenas reinterpretar a memória nesse local. Essa reinterpretação não funciona em Java: você só pode interpretar o objeto na outra extremidade da referência como algo que já é (ou seja, você pode converter uma Object
referência em String
referência apenas se o objeto apontado for realmente a String
).
Essas diferenças tornam os ponteiros C mais poderosos, mas também mais perigosos. Essas duas possibilidades (aritmética do ponteiro e reinterpretação dos valores apontados) adicionam flexibilidade ao C e são a fonte de parte do poder da linguagem. Mas eles também são grandes fontes de problemas, porque, se usados incorretamente, podem facilmente quebrar as suposições de que seu código foi criado. E é muito fácil usá-los incorretamente.