CodeGym /Blog Java /Random-ES /Palabra clave de retorno de Java
Autor
Jesse Haniel
Lead Software Architect at Tribunal de Justiça da Paraíba

Palabra clave de retorno de Java

Publicado en el grupo Random-ES
Como sabemos, el lenguaje Java es un lenguaje de programación orientado a objetos. En otras palabras, el concepto fundamental, es decir, el fundamento del fundamento, es que todo es un objeto. Los objetos se describen usando clases. Las clases, a su vez, definen el estado y el comportamiento. Por ejemplo, una cuenta bancaria puede tener un estado en forma de cantidad de dinero en la cuenta y tener comportamientos que aumenten o disminuyan el saldo de la cuenta. En Java, los comportamientos se implementan a través de métodos. Aprender a definir métodos se encuentra al comienzo de sus estudios de Java. Por ejemplo, en el tutorial oficial de Oracle, bajo el título " Definición de métodos ". Hay dos cosas importantes a tener en cuenta aquí:
  • Cada método tiene una firma. La firma consta del nombre del método y sus parámetros de entrada.
  • Se debe especificar un tipo de retorno para los métodos. El tipo de retorno de un método se declara en su declaración de método.
El tipo de retorno no es parte de la firma del método. Nuevamente, esto es consecuencia del hecho de que Java es un lenguaje fuertemente tipado y el compilador quiere saber qué tipos se usan y dónde, con anticipación y tanto como sea posible. Nuevamente, esto es para salvarnos de errores. Básicamente, todo es por una buena causa. Y me parece que esto nos inculca una vez más una cultura de manejo de datos. Por lo tanto, el tipo de valor devuelto se especifica para los métodos. Y la palabra clave return en Java se usa para hacer la devolución. Palabra clave de retorno de Java - 1

¿Qué hace return en Java?

La palabra clave return es una declaración de flujo de control, como se describe en el tutorial de Oracle aquí . También puede leer sobre cómo devolver valores en la sección " Devolver un valor de un método " del tutorial oficial. El compilador realiza un seguimiento cuidadoso de si puede garantizar que el valor de retorno de un método coincida con el tipo de retorno especificado del método. Usemos el IDE en línea de Tutorialspoint para considerar un ejemplo. Veamos el ejemplo primitivo:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}
Como podemos ver, aquí se ejecuta el método principal , que es el punto de entrada del programa. Las líneas de código se ejecutan de arriba a abajo. Nuestro método principal no puede devolver un valor. Si intentamos devolver un valor allí, obtendremos un error: "Error: el método principal debe devolver un valor de tipo void" . En consecuencia, el método simplemente da salida a la pantalla. Ahora vamos a mover el literal de cadena a un método separado para generar el mensaje:

public class HelloWorld {

    public static void main(String[] args) {
        System.out.println(getHelloMessage());
    }
    
    public static String getHelloMessage() {
        return "Hello World";
    }
    
}
Como podemos ver, usamos la palabra clave de retorno para indicar el valor de retorno, que luego pasamos al método println . La declaración del método getHelloMessage indica que el método devolverá un String . Esto permite que el compilador verifique que las acciones del método sean consistentes con la forma en que se declara. Naturalmente, el tipo de devolución especificado en la declaración de un método puede ser más amplio que el tipo del valor realmente devuelto en el código, es decir, lo importante es que es posible una conversión de tipo. De lo contrario, obtendremos un error en tiempo de compilación: "Error: tipos incompatibles" . Por cierto, probablemente tengas una pregunta: ¿Por qué se devuelveconsiderado una declaración de flujo de control? Porque puede interrumpir el flujo normal de arriba hacia abajo de un programa. Ejemplo:

public class HelloWorld {

    public static void main(String[] args) {
        if (args.length == 0) {
            return;
        }
        for (String arg : args) {
            System.out.println(arg);
        }
    }
    
}
Como puede ver en el ejemplo, interrumpimos el método principal en el programa Java si se llama sin argumentos. Es importante recordar que si tiene un código después de una declaración de devolución , no será accesible. Nuestro compilador inteligente lo notará y evitará que ejecute dicho programa. Por ejemplo, este código no compila:

public static void main(String[] args) {
        System.out.println("1");
        return;
// we use output method after return statement, which is incorrect 
        System.out.println("2");
 }
Hay un truco sucio para evitar esto. Por ejemplo, con fines de depuración o por algún otro motivo. El código anterior se puede corregir envolviendo la declaración de devolución en un bloque if :

if (2==2) {
    return;
}

Declaración de devolución durante el manejo de errores

Hay algo más complicado: podemos usar return junto con el manejo de errores. Quiero decir de inmediato que usar una declaración de retorno en un bloque catch es una forma muy, muy mala, por lo que debe evitarlo. Pero necesitamos un ejemplo, ¿verdad? Aquí lo tienes:

public class HelloWorld {

    public static void main(String[] args) {
        System.out.println("Value: " + getIntValue());
    }
    
    public static int getIntValue() {
        int value = 1;
        try {
            System.out.println("Something terrible happens");
            throw new Exception();
        } catch (Exception e) {
            System.out.println("Cached value: " + value);
            return value;
        } finally {
            value++;
            System.out.println("New value: " + value);
        }
    }
    
}
A primera vista, parece que debería devolverse 2, ya que finalmente siempre se ejecuta. Pero no, el valor de retorno será 1, y el cambio a la variable en el bloque finalmente será ignorado. Además, supongamos que el valor contiene un objeto y decimos valor = nulo en el bloque finalmente . Entonces ese objeto, no nulo, sería devuelto en el bloque catch . Pero una declaración de retorno funcionaría correctamente en el bloque finalmente . Obviamente, sus compañeros de trabajo no le agradecerán las pequeñas sorpresas relacionadas con las declaraciones de devolución.

void.class

Y finalmente. Existe esta extraña construcción que puedes escribir: void.class . Mmm. ¿Por qué y qué significa? Realmente hay varios marcos y casos complicados relacionados con la API de Java Reflection donde esto puede ser muy útil. Por ejemplo, puede verificar qué tipo devuelve un método:

import java.lang.reflect.Method;

public class HelloWorld {

    public void getVoidValue() {
    }

    public static void main(String[] args) {
        for (Method method : HelloWorld.class.getDeclaredMethods()) {
            System.out.println(method.getReturnType() == void.class);
        }
    }
}
Esto puede ser útil en marcos de prueba donde necesita reemplazar el código real en los métodos. Pero para hacer esto, necesita comprender cómo se comporta un método (es decir, qué tipo devuelve). También hay una segunda forma de implementar el método principal en el código anterior:

public static void main(String[] args) {
        for (Method method : HelloWorld.class.getDeclaredMethods()) {
            System.out.println(method.getReturnType() == Void.TYPE);
        }
 }
Puede leer una discusión bastante interesante sobre la diferencia entre los dos en Stack Overflow: ¿ Cuál es la diferencia entre java.lang.Void y void?
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION