valores valor tipos sintaxis retornan referencia que por paso pasar parametros metodos metodo entero ejemplos java immutability

valor - Cómo determinar si un método Java modifica un objeto pasado como parámetro



sintaxis de un metodo en java (7)

Vengo de un fondo de C ++ y actualmente estoy aprendiendo Java. Una pregunta surgió cuando intenté usar algunas bibliotecas de terceros. ¿Cómo determino si la llamada a un método que toma una referencia de objeto como parámetro modifica el objeto? En C ++ esto está claro gracias al uso de la palabra clave const. Si la firma del método es:

void foo(Boo& boo);

Sé que el objeto referenciado puede ser modificado, mientras que si la firma del método es:

void foo(const Boo& boo);

El compilador garantiza que el objeto al que se hace referencia no se modifica.

No he visto algo análogo en Java, ya que solo la referencia en sí puede declararse final, no el objeto al que se hace referencia, y un argumento final no tiene mucho sentido en primer lugar ya que se pasa por valor de todos modos. Por lo tanto, cuando veo un método como:

void foo(Boo boo) {...}

¿Cómo puedo determinar si el objeto referenciado por boo se modifica dentro del cuerpo de la función (quizás usando anotaciones)? Si no hay forma de saberlo, ¿existe alguna convención ampliamente utilizada o algunas mejores prácticas para evitar confusiones y errores?


¿Cómo determino si el objeto referenciado por boo se modifica dentro del cuerpo de la función (quizás usando anotaciones)?

La única forma es leer el código desafortunadamente.

Si no hay forma de saberlo, ¿existe alguna convención ampliamente utilizada o algunas mejores prácticas para evitar confusiones y errores?

La convención común es pasar un objeto que no se puede modificar, utilizando un contenedor si es necesario. Esto asegura que la clase no puede modificar el objeto.

List<String> readOnly = Collections.unmodifiableList(list);

Si el objeto es clonable, también puede usar clone() pero otro enfoque común es usar una copia.

List<String> readOnly = new ArrayList<>(list);

Si te preocupa ese comportamiento, las pruebas unitarias pueden mostrar si un método modifica o no un objeto. Si ya tiene pruebas unitarias, usualmente hay una o dos líneas adicionales para verificar esto.


¿Cómo puedo determinar si el objeto referenciado por boo se modifica dentro del cuerpo de la función (quizás usando anotaciones)?

Debo estar de acuerdo con otras respuestas de que no hay una forma directa de determinar que el método modificará su objeto o no y sí para asegurarse de que el método no puede modificar su Object todos tienen que hacerlo desde su lado.

Si no hay forma de saberlo, ¿existe alguna convención ampliamente utilizada o algunas mejores prácticas para evitar confusiones y errores?

Aquí el nombre del método llega a la escena. Avanzando con la convención de nombres del método, tenemos que echar un vistazo a algunas declaraciones de métodos que claramente lo convencen de que su Object no se cambiará en absoluto.

Por ejemplo, usted sabe que Arrays.copyOf no cambiará su matriz real, System.out.println(boo) no cambiará su boo

Los nombres de métodos son armas reales para proporcionar la mayor cantidad de información posible al usuario del método. (Sí, no siempre es posible, pero es una buena práctica seguirlo).

Consideremos en su caso que diga printBoo solo imprimirá, copyBoo solo copiará, clearBoo restablecerá todos los atributos, checkAndCreateNewBoo revisará su boo Object y creará nuevo si es necesario.

Por lo tanto, en última instancia, si podemos usarlos de manera adecuada, se puede asegurar a la persona que llama con el hecho de que Object seguirá siendo el mismo después de llamar al método.


Como todos dicen, prefieren usar objetos inmutables y también evitar los métodos de vacío

Los propósitos disponibles de métodos como este

void foo(Boo boo) {...}

son cambiar el estado del objeto en sí o cambiar el objeto pasado como parámetro

void completOrder(Order order) { ... } //or void parserTokenEnded(String str) { ... }


Desafortunadamente, no hay tal instalación incorporada al lenguaje. Una buena práctica defensiva es definir los objetos de datos que se pasan como inmutables (es decir, sin ningún método público que permita modificar su estado). Si realmente le preocupa esto, puede copiar / clonar un objeto antes de pasarlo a un método en el que no confíe, pero esto generalmente es una precaución redundante.


Hay una manera, que el desarrollador del método debe marcar el parámetro como final, si no va a modificar el parámetro.

public void test(final Object param)

Sin embargo, muy pocas personas siguen esto, por lo que es difícil de saber. Sin embargo, un buen programador sigue esta regla, especialmente escribiendo la api. Si quieres escribir el método y exponerlo. Haga param final para indicar que el objeto pasado no va a ser modificado.


Un análisis de efectos secundarios no está incorporado en el lenguaje Java.

Puede realizar análisis de efectos secundarios mediante inspección manual, pero existen varias herramientas para automatizar el proceso.

Puede usar una herramienta de inferencia ( 1 , 2 , 3 ) para detectar si su código tiene efectos secundarios en un parámetro.

También puede escribir anotaciones de pureza o efectos secundarios en su código y luego usar una herramienta de verificación / verificación ( 1 , 2 ) para asegurarse de que su código cumpla con las anotaciones que ha escrito.

Todas las herramientas mencionadas anteriormente tienen limitaciones, pero puede que las encuentren útiles. Si conoce otras herramientas, mencionelas en los comentarios.


NOTA: esta respuesta es una versión más detallada de

También puede escribir anotaciones de pureza o efectos secundarios en su código - mernst

Existe el marco Checker entre las diversas cosas que puede verificar en tiempo de compilación a través de anotaciones es el verificador Immutablity de IJG . Este corrector le permite anotar referencias de objetos con @Immutable o @ReadOnly .

El problema es que a menudo tendría que anotar la biblioteca usted mismo. Para facilitar su tarea, Checker Framework puede inferir automáticamente parte de las anotaciones; aún tendrás que hacer mucho por ti mismo.