Como uma referência Java é diferente de um ponteiro C?

94

C tem ponteiros e Java tem o que é chamado de referências. Eles têm algumas coisas em comum, no sentido de que todos apontam para algo. Eu sei que os ponteiros em C armazenam os endereços para os quais eles apontam. Fazer referência também armazena o endereço? Como eles são diferentes, exceto que o ponteiro é mais flexível e propenso a erros?

    
por Gnijuohz 28.03.2012 / 09:46
fonte

4 respostas

139

As referências podem ser implementadas pelo armazenamento do endereço. Normalmente, 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 indireto para facilitar a coleta de lixo. Mas no final ele (quase sempre) se resumirá aos ponteiros (estilo C) envolvidos na implementação de referências (no estilo Java).

Você não pode fazer aritmética de ponteiros com referências. A diferença mais importante entre um ponteiro em C e uma referência em Java é que você não consegue (e manipula) o valor subjacente de uma referência em Java. Em outras palavras: você não pode fazer aritmética de ponteiros.

Em C você pode adicionar algo a um ponteiro (ou seja, o endereço) ou subtrair algo para apontar para coisas que estão "por perto" ou apontar para lugares que estão em qualquer lugar.

Em Java, uma referência aponta para uma coisa e essa coisa apenas. Você pode fazer uma variável conter uma referência diferente , mas você não pode simplesmente pedir que aponte para "a coisa depois da coisa original".

As referências são strongmente tipadas. Outra diferença é que o tipo de uma referência é muito mais rigorosamente controlado em Java do que o tipo de ponteiro em C. Em C você pode ter um int* e convertê-lo em char* e apenas reinterpretar a memória naquele local. Essa reinterpretação não funciona em Java: você só pode interpretar o objeto no outro extremo da referência como algo que já é (ou seja, você pode converter uma referência Object para String reference somente se o objeto apontado for realmente um String ).

Essas diferenças tornam os ponteiros C mais poderosos, mas também mais perigosos. Ambas as possibilidades (aritmética de ponteiro e reinterpretar os valores apontados) aumentam a flexibilidade para C e são a fonte de alguns do poder da linguagem. Mas eles são também grandes fontes de problemas, porque se usados incorretamente, eles podem facilmente quebrar as suposições de que seu código é construído. E é muito fácil usá-los incorretamente.

    
por 28.03.2012 / 10:02
fonte
7

As referências em C ++ são diferentes novamente.

Eles precisam ser inicializados e não podem ser nulos (pelo menos não em um programa bem formado) e não podem ser recolocados para se referirem a outra coisa. uma referência em C ++ é muito mais parecida com um alias para um objeto.

Outra diferença importante entre ponteiros e referências Java / C ++ é que você pode pegar o endereço de um ponteiro que não pode acessar o endereço de uma referência (na verdade, uma referência C ++ não precisa existir como um objeto na memória) pode ter um ponteiro para um ponteiro, mas não uma referência a uma referência

    
por 28.03.2012 / 10:31
fonte
4

As referências Java e os ponteiros C diferem em exatamente dois pontos:

  1. Não há aritmética de ponteiro para o primeiro.
  2. E você não pode criar uma referência Java para o que você quiser, você só pode copiar aqueles salvos em algum lugar acessível (campos estáticos, campos de objetos, variáveis locais) ou retornados por invocações de função (como chamadas de construtor), consulte objetos Java (nunca para tipos básicos como referências, char , int e assim por diante).

Alguém escreveu que as Referências são strongmente tipificadas, porque você não pode forçar o compilador a tratar um int* como char* .
Completamente além do fato de que a conversão particular é realmente segura , não há polimorfismo em C, então essa comparação é um não-inicial.
Certamente, Java é mais strongmente tipado que C, não que seja um recurso de ponteiros C versus referências Java, você precisa usar o JNI para quebrar a segurança de tipos (além de desconsiderar restrições genéricas), mas mesmo em C você precisa < em> force
o compilador.

Alguém escreveu que as referências Java podem ser implementadas como ponteiros C, às quais eu digo certeza, já que elas são estritamente menos poderosas, em máquinas 32Bit que elas normalmente são, se a JVM for implementada em C . Embora em máquinas de 64 bits, eles são normalmente ponteiros de objetos comuns compactados ("OOPs compactados") para economizar espaço e largura de banda.
De qualquer forma, esses ponteiros C não precisam ser equivalentes a endereços de hardware, mesmo que eles normalmente (> 99% das implementações) sejam por motivos de desempenho. Finalmente, esse é um detalhe de implementação que não é exposto ao programador.

    
por 20.08.2015 / 23:29
fonte
-1

Eles são ligeiramente diferentes. Em Java, uma cópia da referência é copiada para a pilha de uma função chamada, apontando para o mesmo objeto que a função de chamada e permitindo que você manipule esse objeto. No entanto, você não pode alterar o objeto ao qual a função chamadora se refere.

Considere o seguinte código java

public static void changeRValue(StringBuffer sb){
    sb = new StringBuffer("helllllo"); /*attempt to assign the reference
                                        to a new object*/
}
public static void main(String[] args) {
    StringBuffer sb = new StringBuffer("hi");     //Create a new string buffer
    changeRValue(sb);                             //Call changeRValue
    System.out.println(sb.toString());            //Prints "hi" not "hello"
}

Agora considere um ponteiro em c ++:

void func(Dog* dog){
    *dog = Dog("hello world"); //Change the value of dog to a new object
}

int main(int argc, const char * argv[]) {
    Dog dog1("hi");                            //Create a dog object
    func(&dog1);                               //pass the address of dog
    cout << dog1.name;                         //Prints "hello world" not hi.
    return 0;
}
    
por 20.08.2015 / 16:13
fonte