¿En qué se diferencia una referencia de Java de un puntero de C?

94

C tiene punteros y Java tiene lo que se llama referencias. Tienen algunas cosas en común en el sentido de que todos apuntan a algo. Sé que los punteros en C almacenan las direcciones a las que apuntan. ¿La referencia también almacena la dirección? ¿En qué se diferencian, excepto que el puntero es más flexible y propenso a errores?

    
pregunta Gnijuohz 28.03.2012 - 09:46

4 respuestas

139

Las referencias pueden implementarse almacenando la dirección. Generalmente Las referencias de Java se implementarán como punteros, pero eso no es requerido por la especificación. Es posible que estén usando una capa adicional de direccionamiento indirecto para permitir una recolección de basura más fácil. Pero al final, (casi siempre) se reducirá a punteros (estilo C) involucrados en la implementación de referencias (estilo Java).

No se puede hacer aritmética de punteros con referencias. La diferencia más importante entre un puntero en C y una referencia en Java es que realmente no se puede llegar (y manipular) el valor subyacente de una referencia en Java. En otras palabras: no se puede hacer aritmética de punteros.

En C, puede agregar algo a un puntero (es decir, la dirección) o restar algo para señalar cosas que están "cerca" o para señalar lugares que están en cualquier lugar.

En Java, una referencia apunta a una cosa y solo a esa cosa. Puedes hacer que una variable contenga una referencia diferente , pero no puedes simplemente pedirle que señale "lo que está detrás de lo original".

Las referencias están muy escritas. Otra diferencia es que el tipo de referencia es mucho más controlado de forma más estricta en Java que el tipo de puntero en C. En C puede tener un int* y convertirlo en un char* y simplemente volver a interpretar la memoria en esa ubicación. Esa reinterpretación no funciona en Java: solo puede interpretar el objeto en el otro extremo de la referencia como algo que ya está (es decir, puede convertir una referencia Object a String reference solo si el objeto señalado es en realidad un String ).

Esas diferencias hacen que los punteros C sean más potentes, pero también más peligrosos. Ambas posibilidades (la aritmética de punteros y la reinterpretación de los valores a los que se apunta) agregan flexibilidad a C y son la fuente de algunos del poder del lenguaje. Pero son también grandes fuentes de problemas, porque si se usan incorrectamente, pueden romper fácilmente las suposiciones sobre las que se basa su código. Y es bastante fácil usarlos incorrectamente.

    
respondido por el Joachim Sauer 28.03.2012 - 10:02
7

Las referencias de C ++ son diferentes otra vez.

Tienen que estar inicializados y no pueden ser nulos (al menos no en un programa bien formado) y no pueden ser reubicados para referirse a otra cosa. una referencia de C ++ es mucho más como un alias para un objeto.

Otra diferencia importante entre los punteros y las referencias de Java / C ++ es que puede tomar la dirección de un puntero, no puede acceder a la dirección de una referencia (de hecho, una referencia de C ++ en realidad no es un objeto en la memoria). puede tener un puntero a un puntero pero no una referencia a una referencia

    
respondido por el jk. 28.03.2012 - 10:31
4

Las referencias de Java y los punteros C se diferencian exactamente en dos puntos:

  1. No hay puntero-aritmética para el primero.
  2. Y no puede crear una referencia de Java para lo que quiera, solo puede copiar los guardados en un lugar accesible (campos estáticos, campos de objetos, variables locales) o devueltos por invocaciones de función (como constructor-llamadas), que por lo tanto todos refiérase a objetos Java (nunca a tipos básicos como referencias, char , int y así sucesivamente).

Alguien escribió que las Referencias están fuertemente escritas, porque no puedes obligar al compilador a tratar un int* como un char* .
Completamente aparte del hecho de que esa conversión particular es en realidad segura , no hay polimorfismo en C, por lo que la comparación no es iniciadora.
Ciertamente, Java está más fuertemente tipado que C, no es que sea una característica de los punteros C vs las referencias de Java, necesita usar el JNI para romper la seguridad de tipo (aparte de ignorar las restricciones genéricas), pero incluso en C tiene que < em> force el compilador

Alguien escribió que las referencias de Java podrían implementarse como punteros de C, de los que estoy seguro , ya que son estrictamente menos potentes, en las máquinas de 32 bits que suelen ser, si la JVM se implementa en C . Aunque en máquinas de 64 bits, normalmente son punteros de objetos ordinarios comprimidos ("OOP comprimidos") para ahorrar espacio y ancho de banda.
De todos modos, esos punteros C tampoco tienen que ser equivalentes a las direcciones de hardware, incluso si típicamente (> 99% de las implementaciones) son por razones de rendimiento.
Finalmente, ese es un detalle de implementación que no está expuesto al programador.

    
respondido por el Deduplicator 20.08.2015 - 23:29
-1

Son ligeramente diferentes. En Java, una copia de la referencia se copia a la pila de una función llamada, apuntando al mismo objeto que la función de llamada y permitiéndole manipular ese objeto. Sin embargo, no puede cambiar el objeto al que se refiere la función de llamada.

Considere el siguiente 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"
}

Ahora considere un puntero en 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;
}
    
respondido por el Eladian 20.08.2015 - 16:13

Lea otras preguntas en las etiquetas