2012-04-15 25 views
6

permite decir que este es el código C++:¿Cómo funcionan los "punteros" de Java?

void change(int& x){ 
    x++; 
} 

o

void change2(int* a){ 
    *a++; 
} 

Ambos cambiar las x globales, ¿verdad?

Entonces, ¿cómo puedo hacer algo así en Java?
Específicamente, quiero apuntar a un objeto Vector

Pero como Java no tiene punteros, no estoy seguro de qué hacer.
Al buscar en Internet, vi gente que decía que Java lo hace de alguna otra forma, pero no he encontrado ningún ejemplo real.

Gracias por ayuda!

+0

Java siempre pasa por valor. –

+0

La respuesta es probable, "no se puede", pero comience por darnos el código de Java relevante ... –

+1

posible duplicado de [Cómo pasar por referencia en Java] (http://stackoverflow.com/questions/5614562/how-to-pass-by-reference-in-java) –

Respuesta

12

En Java, en lugar de punteros, tiene referencias a objetos. No puede pasar un tipo primitivo por referencia, pero puede envolver un tipo primitivo dentro de un objeto y luego pasar una referencia a ese objeto.

Java proporciona el tipo Integer que se envuelve int, sin embargo, este tipo es inmutable por lo que no puede cambiar su valor después de la construcción. No obstante, usted podría utilizar MutableInt de Apache Commons:

void change(MutableInt x) { 
    x.increment(); 
} 

El cambio de x será visible para la persona que llama.


Específicamente, quiero apuntar a un objeto Vector

Cuando se escribe Vector v = ...; está asignando una referencia a un vector para la variable v. Una referencia en Java es muy similar a un puntero. Las referencias se implementan de hecho internamente mediante punteros.

Java utiliza pasar por valor. Cuando pasa un vector a un método, en realidad está copiando una referencia a ese vector. No clona el vector en sí. Pasar una referencia en Java es muy similar a pasar un puntero en C++.

+0

Lo que no me gusta de esto es que da la impresión de que necesitas una lib de terceros para hacer algo extremadamente básico en Java. Estoy bastante seguro de que OP no ** realmente ** necesita MutableInt o cualquier otra cosa de Apache Commons; en cambio, solo necesitaría aprender Java idiomático. Es cierto que la pregunta es difícil de responder mejor, ya que no está claro lo que * realmente * quiere que haga su código. – Jonik

+0

Tampoco me gusta que esta sea la respuesta aceptada. Consulte http://stackoverflow.com/questions/5614562/how-to-do-the-equivalent-of-pass-by-reference-for-primitives-in-java/5614630#5614630 para obtener una explicación detallada de 4 formas de haz esto, sin importar ninguna biblioteca de terceros. O vea la respuesta de dash1e para una forma común de hacer esto. – ToolmakerSteve

1

Java siempre pasa por valor y no hay variables globales como en el sentido C++. Entonces, si quiere hacer lo mismo que en C++, debe devolver el nuevo valor.

así:

public int change(int x) { 
    return ++x; 
    // or 
    // return x + 1; 
} 

para probarlo:

int x = 2; 

change(x); 

System.out.println(x); // returns 2 

x = change(x); 

System.out.println(x); // returns 3 

lo tanto, no tiene ningún sentido dejar que el método se llama change, que es más sensible a lo largo de las líneas de calculateThisInt.


Java pasa objetos por valor. Pero como Mark Byers menciona que la clase Integer es inmutable y puede usar MutableInt de la biblioteca de Apache Commons.Para describir cómo funciona esto se podría aplicar por sí mismo por su ejemplo:

public class MyInt() { 

    public int i; 

    public void setInt(int i) { 
     this.i = i; 
    } 

    public int getInt() { 
     return this.i; 
    } 

    public int increment() { 
     this.i++; 
    } 

} 

Usted necesita cambiar su función change tener la MyInt objetivo anterior como argumento:

public void change(MyInt i) { 
    i.increment(); 
} 

Uso:

MyInt x = new MyInt(); 
x.setInt(2); 

change(x); 

System.out.println(x.getInt); // returns 3 

En su caso, usted quiere cambiar un Vector objeto ...

public void changeVector(Vector v) { 
    // anything you do with 'v' will change it even 
    // for the scope that called this method 
} 

// Usage: 
Vector v = new Vector(); 
changeVector(v); 
// v should be changed after calling change vector method 

Espero que todo esto tenga sentido.

+0

necesita usar return ++ x; en lugar de devolver x ++; – Chris

+0

@Chris: Ups, corregidos. – Spoike

+0

Los objetos no se pasan por referencia en Java.La referencia a un objeto se pasa por valor. –

4

Con Java no puede pasar tipos primitivos como int por referencia, solo se pasan por valor.

Lo único que puede hacer es encontrar artificios para hacer eso, porque en su lugar Objects se pasan por referencia. Aquí dos ejemplos.

utilizar una matriz de valor único, al igual que este enfoque

int[] value = new int[1]; 
value[0] = 2; 

// call a method 
obj.setValue(value); 

// and in setValue 
public void setValue(int[] value) { 
    value[0] = 5; 
} 

O segundos utilizar una clase titular:

public class Holder<T> { 
    public T value; 
    public Holder(T value) { 
    this.value = value; 
    } 
} 

// then use it in this way 
Holder<Integer> h = new Holder<Integer>(2); 

obj.setValue(h); 

// and in setValue 
public void setValue(Holder<Integer> h) { 
    h.value = 5; 
} 

En este caso utilizo una clase titular implementa con los genéricos, sino que puede tener un titular simple también, solo para entero. Por ejemplo:

public class IntHolder { 
    public int value; 
    public IntHolder(int value) { 
    this.value = value; 
    } 
} 
+0

estimado SmRndGuy, esta es la respuesta que está buscando. (PD: No sabía sobre la clase Holder, así que gracias dash1e.) – guness

+0

@bluebrain presta atención, no es una clase estándar de Java, tienes que escribir tu Titular por ti mismo, pero es muy simple. Tal vez, a veces, puede encontrar titulares en diferentes bibliotecas porque es una forma habitual de resolver ese problema. – dash1e

+0

Esa clase genérica 'Holder' es una buena manera de hacer un" contenedor ". – Spoike

0

Si bien no se puede reemplazar un objeto que se ha pasado a una función, puede cambiar su estado mediante la alteración de los campos directa o llamar a los métodos. Si necesita algo así como un puntero a una primitiva, envuélvalo en un objeto. Para seguir su código, usted puede hacer esto:

public class IntPointer { 
    public int value; 
    public IntPointer(int value) { 
     this.value = value; 
    } 
} 

Entonces otra parte se podría decir:

public static void change(IntPointer ipoint) { 
    ipoint.value++; 
} 
public static void main(String[] args) { 
    IntPointer a = new IntPointer(10); 
    change(a); 
} 

esto puede parecer un poco incómodo, pero no ha llegado para mí tan a menudo como pensaría Sería más probable que hacer algo como esto:

public class ABPair { 
    private int a = 0; 
    private int b = 0; 
    public static void changeA() { 
     a++; 
    } 
    public static void changeB() { 
     b++; 
    } 
} 

Así que en otros lugares que puedo decir:

public static void main(String[] args) { 
    ABPair ab = new ABPair(); 
    if (ACondition) { 
     ab.changeA(); 
    } 
} 

En otras palabras, mis datos ya tiende a ser envuelto en algún tipo de objeto, y tiendo a usar los métodos del objeto de datos para mediar cualquier cambio.

0

Ambos cambiarán la x global, ¿verdad?

Entonces, ¿cómo puedo hacer algo así en Java?En concreto, quiero punto de un objeto Vector

La pregunta es un tanto vaga, pero me dio la impresión de que usted desea en última instancia un mundial Vector que se puede mantener en la materia?

Muchas formas de hacerlo, pero una de las más simples es tener un campo estático en una clase, con métodos públicos estáticos para acceder a él. (O simplemente un campo estático público al que se accede directamente, pero que realmente no habría idiomática en Java.)

public class Foo { 
    private static List<Integer> globalVector = new Vector<Integer>(); 

    public static void add(int number){ 
     globalVector.add(number); 
    } 

    // ... plus whatever other accessors to the global list that you need 
} 

En cualquier otro lugar en el código:

Foo.add(23); // modifies the global vector 

(Por cierto, es un poco obsoleta Vector , y normalmente usaríamos ArrayList en su lugar ahora. Como dice Javadoc, se ha adaptado para implementar la interfaz List, que también usé en el ejemplo).

+0

** Descargo de responsabilidad **: Es posible que haya malinterpretado por completo lo que OP quería, y lo eliminaré si ese fuera el caso. La pregunta realmente debería ser más clara sobre qué es lo que OP quiere realmente lograr con su código. – Jonik

0

Java admite lo que denomina "referencias". Las referencias actúan como punteros en C/C++, como los idiomas. No actúan de la misma manera que las "referencias" funcionan en esos idiomas.

Las principales diferencias entre un puntero en C y una referencia en Java son:

No se puede hacer la aritmética de punteros en Java (es decir, no se puede "añadir" o "restar" de una referencia de Java, solo puedes desreferenciarlo o compararlo con otro). No puede convertirlo en un tipo incompatible: Java es fuertemente seguro para tipos, no puede "reinterpretar" los bytes en la memoria como algún otro objeto. Para algunos usos de punteros, esto no tiene ningún efecto real (por ejemplo, las listas vinculadas funcionan bastante bien en ambos idiomas), para otros la diferencia es bastante importante (las matrices en C son simplemente aritmética de puntero, en Java funcionan de manera bastante diferente) .

Por lo tanto, en cierto modo, las referencias de Java se podrían llamar "punteros restringidos".

Cuestiones relacionadas