¿Tiene / por qué Java necesita tener void
métodos? Referencia :
Cualquier método declarado vacío no devuelve un valor.
Hasta donde puedo pensar, cada uso de void
sería mejor al devolver un indicador de estado, el objeto que se invoca, o null
.
Esto haría que cada llamada sea una declaración asignable y facilitaría los patrones de creación y el encadenamiento de métodos. Los métodos que solo se invocan por sus efectos generalmente devolverían un tipo booleano o genérico Success
o arrojarían una excepción en caso de falla.
java
programming-languages
return-type
marisbest2
fuente
fuente
Respuestas:
Debido a que existe una diferencia entre "Esta función puede tener éxito o fallar y es lo suficientemente consciente de sí misma como para poder notar la diferencia" y "No hay comentarios sobre el efecto de esta función". Sin esto
void
, verificaría infinitamente los códigos de éxito y creería que está escribiendo un software robusto, cuando en realidad no está haciendo nada por el estilo.fuente
void
no dice nada sobre si el método o la función es lo suficientemente consciente de sí mismo como para lanzarlo según corresponda.void
tipo, y Java fue diseñado para seguir muchas de las convenciones de la familia de lenguaje C.Success
tipo genérico " de todos modos? De hecho, los valores de retorno para indicar el éxito son incluso menos importantes en Java que en C, porque Java tiene excepciones para indicar fallas y C no.fuente
Void
tipo de Java actúa como un tipo de Unidad (por ejemplo, para genéricos), aunque lamentablemente, es diferente devoid
(nota al margen: un gatito adorable muere cada vez que inventa un nuevo tipo para arreglar el tipo que estropeó en la versión anterior). Si alguien no está familiarizado con los tipos de unidades, esta es una introducción decente: en.wikipedia.org/wiki/Unit_typenull
(de hecho, esta es la única opción), pero nulo es algo especial, cualquier valor de tipo de referencia en Java puede ser nulo (este es otro error en el diseño del lenguaje). Y, como dije antes, si está utilizando elVoid
tipo de retorno en lugar devoid
mark, el compilador de Java no es su amigo.null
. El hecho de quenull
sea un miembro de la mayoría de los tipos es irrelevante para saber siVoid
es un tipo de unidad.La razón original por la cual el lenguaje tiene un
void
tipo es porque, como enC
, los creadores del lenguaje no querían complicar innecesariamente la sintaxis del lenguaje con procedimientos y funciones como lo hizo Pascal.Esa fue la razón original.
Tus sugerencias:
Eso es un no-no. No utilizamos banderas de estado. Si algo sale mal, lo informamos a través de excepciones.
El estilo fluido de las invocaciones es un desarrollo reciente. Muchos de los programadores que usan muy bien el fluido hoy y ponen los ojos en blanco si alguna vez tienen que usar una interfaz que no lo admite, ni siquiera nacieron cuando se creó Java.
Eso lo obligaría a declarar que un método devuelve algo, cuando de hecho no devuelve nada, por lo que sería muy confuso para alguien que está mirando una interfaz tratando de descubrir qué hace. La gente inevitablemente inventaría alguna clase inútil que significa "sin valor de retorno" para que todas las funciones que no tienen nada que devolver puedan devolver una referencia nula a dicha clase. Eso sería torpe. Afortunadamente, hay una solución para esto, se llama
void
. Y esa es la respuesta a tu pregunta.fuente
int
, por lo que se agregaba una palabra clave después de K&R para indicar 'tipo de no retorno'.Algunos métodos, como
System.out.println
no devuelve nada útil, pero se llama únicamente por este efecto secundario.void
es un indicador útil para el compilador y para el lector de código de que no se devuelve ningún valor útil.Devolver en
null
lugar devoid
significa que solo obtendríaNullPointerException
el momento en que use este valor para cualquier cosa. Por lo tanto, intercambia un error de tiempo de compilación por un error de tiempo de ejecución que es mucho peor. Además, tendría que definir el tipo de retorno comoObject
, lo que sería engañoso y confuso. (Y el encadenamiento aún no funcionaría).Los códigos de estado generalmente se usan para indicar condiciones de error, pero Java tiene excepciones para este propósito.
this
No es posible regresar de métodos estáticos.Devolver un
Success
objeto genérico no tendría ningún propósito útil.fuente
Una de las razones es que puede ser engañoso para volver jamás otra que, digamos nada,
null
. Ejemplo:¿Qué debería
Arrays.sort(a)
volver?Si argumenta que
a
debe devolverse para poder encadenar la llamada (que parece ser su respuesta a juzgar por su pregunta), entonces ya no está claro si el valor devuelto es una copia del objeto original o el objeto original en sí . Ambos son posibles. Y sí, podría incluirlo en la documentación, pero es lo suficientemente ambiguo como para no crear la ambigüedad en primer lugar.Por otro lado, si usted argumenta que
null
debería devolverse, eso plantea la pregunta de qué información posiblemente el valor de retorno está proporcionando al llamante, y por qué el programador debería verse obligado a escribirreturn null
cuando no transmite información.Y si devuelve algo totalmente absurdo (como la longitud de
a
), entonces hace que usar ese valor de retorno sea realmente confuso, ¡solo piense cuánto más confuso es decir enint len = Arrays.sort(a)
lugar deint len = A.length
!fuente
return null;
: la JVM también podría exigir que si el control se cae al final de una función por otro medio que no sea explícitoreturn
o unathrow
declaración,null
se devuelve implícitamente a la persona que llama. IIRC C hace eso, excepto que el valor de retorno no está definido en ese caso (será el valor que esté en la ubicación utilizada para el valor de retorno en ese momento).return
declaración. En cambio, aparece un error del compilador que le informa sobre su error. Insertar un implícitoreturn null;
sería mejor que el "comportamiento indefinido", pero no mucho. Eso sería útil solo cuando el tipo de retorno no tiene significado, pero ¿de dónde saca el compilador la conclusión de que el valor de retorno no tiene significado, cuando no lo esvoid
?return
realmente no agrega ningún valor ...", bueno, como se dijo, no hay ningún indicador para el compilador de que una devolución no agregaría ningún valor, si no hay ningúnvoid
tipo. En realidad es lo contrario, la primera suposición es que un método que declara un tipo de retorno quierereturn
algo útil de ese tipo. Y aún no hablamos sobre los tipos primitivos, que no tienen unnull
valor, por lo tanto, cualquier valor predeterminado inyectado por el compilador entraría en conflicto con el rango de valores de retorno potencialmente útiles.Devolver un valor
boolean
que siempre es igual altrue
que sugiere, no solo no tiene sentido (el valor de retorno no contiene información), sino que en realidad sería engañoso. La mayoría de las veces, es mejor usar tipos de retorno que solo contengan tanta información como esté realmente disponible; es por eso que en Java tieneboolean
paratrue
/ enfalse
lugar de devolver unint
con 4 mil millones de valores posibles. Del mismo modo, devolver aboolean
con dos valores posibles donde solo hay un valor posible ("éxito genérico"), sería engañoso.También agregaría una sobrecarga de rendimiento innecesaria.
Si un método se usa solo por su efecto secundario, no hay nada que devolver, y el tipo de retorno
void
refleja exactamente eso. Los posibles errores raros se pueden señalar mediante excepciones.Una cosa que podría mejorarse sería crear
void
un tipo real, como el de ScalaUnit
. Esto resolvería algunos problemas, como el manejo de genéricos.fuente
List.add
siempre regresatrue
, pero eso es por ser compatible con el contrato más amplio deCollection.add
, por lo queSet.add
puede regresartrue
ofalse
.Java es un lenguaje relativamente antiguo. Y en 1995 (cuando se creó) y poco después, los programadores estaban muy preocupados por la cantidad de tiempo que un proceso tomó el control del procesador, así como el consumo de memoria. Devolver el vacío eliminaría algunos ciclos de reloj y un poco de consumo de memoria de una llamada a función porque no tendría que poner el valor de retorno en la pila, y no tendría que eliminarlo posteriormente.
El código eficiente no le devuelve algo que nunca usaría y, por lo tanto, anular algo que tiene un valor de retorno sin sentido es una práctica mucho mejor en lugar de devolver un valor de éxito.
fuente
He leído argumentos que sugieren que la segunda opción (retorno
this
) debería ser el enfoque en lugar devoid
. Esta es una idea bastante buena, pero el enfoque de estilo de constructor no era popular en el momento en que se creó Java. Si era tan popular en ese momento como lo es ahora, ese podría haber sido el enfoque adoptado. Volvernull
es una muy mala idea de la OMI. Desearía quenull
ni siquiera estuviera en el idioma.El problema ahora es que si un método devuelve una instancia de su propio tipo, no está claro si es un objeto nuevo o el mismo. A menudo no importa (o no debería), pero otras veces sí importa. Supongo que el lenguaje podría cambiarse para devolver implícitamente los
this
métodos nulos. El único problema que puedo pensar con eso en este momento es que si el método fue cambiado más tarde para devolver un nuevo objeto del mismo tipo, no habría advertencias de compilación, pero tal vez eso no sea gran cosa. El sistema de tipos actual no se preocupa por estos tipos de cambios ahora. La forma en que esto interactúa con la herencia / interfaces necesitaría cierta consideración, pero permitiría que las API antiguas sin un estilo de generador se llamaran fácilmente como si lo hicieran.fuente
null
no fuera parte del lenguaje, las personas estarían usando todo tipo de valores centinela que significan "ignore este argumento / valor de retorno, no contiene ningún valor sensible". El problema connull
no es la cosa en sí, solo que tiende a usarse incorrectamente. Apostaría a que este problema sólo sería exagerado si el estandarizadanull
sería reemplazado con una gran variedad de soluciones a medida, donde cada aplicación se comportaría de manera diferente en silencio como ignorar el uso, o lanzar excepciones especiales en lugar de una excepción de puntero nulo standart, etcnull
es un tipo opcional adecuado (como,Maybe
en Haskell). El problema con los valores nulos en Java es que no hay una forma sensata de decidir de inmediato si un valor es anulable en la práctica o no. Esto lleva a ambos: programación innecesariamente defensiva (verificar nulos donde no tiene sentido, lo que aumenta el porcentaje de popó en el código) y NPE accidentales en producción (si olvidó verificar dónde era necesario). Sí, se resuelve parcialmente mediante anotaciones, pero son opcionales, no siempre se verifican, etc. Por lo tanto, no lo salvarán en los límites con código de terceros.null
funciona bien para esto (fine = simple), pero los valores opcionales estandarizados con semántica sólida son definitivamente otra buena opción (fine = safe).Otro aspecto:
Java es un lenguaje estático con características bastante estrictas. Esto significa que muchas cosas que serían bastante abiertas o dinámicas en otros idiomas (c / f Ruby, Lisp, etc.) están estrictamente determinadas.
Esta es una decisión general de diseño. El "por qué" es difícil de responder (bueno, ¡porque los diseñadores del lenguaje pensaron que sería bueno!). El "para qué" es bastante claro: permite que el compilador detecte muchos errores, que generalmente es una característica bastante buena para cualquier idioma. En segundo lugar, hace que sea relativamente fácil razonar sobre el idioma. Por ejemplo, es relativamente fácil crear pruebas formales de corrección en (subconjuntos de) el lenguaje Java; en comparación, eso sería prácticamente imposible en un lenguaje dinámico como Ruby et al.
Este pensamiento impregna el lenguaje, por ejemplo, la declaración forzada de posibles excepciones que puede arrojar un método, el tipo separado de
interface
vs.class
para evitar una herencia múltiple ambigua, y así sucesivamente. Por lo que es (un lenguaje del mundo real imperativo estático OOP con un fuerte enfoque en el manejo de errores en tiempo de compilación), esas cosas son en realidad bastante elegantes y poderosas. Se acercan más a los lenguajes teóricos (científicos) que están hechos a propósito solo para explorar algunos de estos problemas que cualquier otro lenguaje del mundo real antes (en ese momento, eso sí).Entonces. Tener un
void
tipo estricto es un mensaje claro: este método no devuelve nada, punto. Es lo que es. Reemplazarlo por la aplicación para que siempre devuelva algo conduciría a un comportamiento mucho más dinámico (como en Ruby, donde cada def tiene un valor de retorno explícito o implícito, siempre), lo que sería malo para la demostrabilidad y el razonamiento; o para una hinchazón masiva usando algún otro mecanismo aquí.(Y NB, Ruby (por ejemplo) maneja esto de manera diferente, y su solución sigue siendo exactamente tan aceptable como la de Java, porque tiene una filosofía completamente diferente. Por ejemplo, arroja completamente la probabilidad y la razonabilidad por completo mientras pone un gran enfoque en extremadamente alta expresividad del lenguaje.)
fuente