Programas en Java

Código 01 - Hola Mundo! Organizado en un proyecto Java
public class Saludos {

    public static String general() {
  return para("Mundo");
} 

public static String para(String quien) {
  return String.format("Hola %s!", quien);
}
} 
public class Main {
    public static void main(String[] args) {
     System.out.println(Saludos.general());
     System.out.println(Saludos.para("Java"));
  }
} 
Hola Mundo!
Hola Java

En Java las construcciones principales son las clases. Todas las funciones que hemos definido deben vivir dentro de una clase. Lo bueno es que el nombre de la clase sirve como nombre de agrupación de sus funciones. Por ejemplo el nombre de la clase Math, sirve como nombre de agrupación para las funciones sqrt(), cosine(), max(), etc.

Esto lo puedes tener en cuenta a la hora de crear tus funciones. En el Código 01, línea 07 la función se llama para() porque para usarla escribirás Saludos.para() que es un nombre muy descriptivo! Las reglas para los identificadores de clase siguen las mismas reglas que para las funciones y variables, pero las clases Java usan CamelCase en mayúsculas en lugar de CamelCase en minúsculas.

También ten en cuenta que las funciones necesitan dos modificadores adicionales que no hemos necesitado usar antes: public static. El modificador <public> se usa para indicar que tu método puede ser usado desde cualquier punto de tu aplicación. El método main siempre debe ser público. Cuando haces una aplicación muy grande, es útil poder restringir quién puede utilizar ciertas partes de ella. Por ahora usaremos siempre <public> en nuestras funciones.

El modificador <static> determina, entre otras cosas, como se debe invocar. Un método <static> indica que debes anteponer el nombre de la clase al nombre del método separados por punto. Por ejemplo los métodos sqrt(), cosine(), max() son static y están declarados en la clase Math por lo que debes invocarlos Math.sqrt(), Math.cosine(), Math.max().

Para poder ejecutar código en Java, necesitarás un método main. Como se mencionó, esto debe estar en una clase que puede cualquier nombre, pero es una buena idea darle un nombre que deje claro que es la clase con el método main, por lo que Main (con M mayúscula) parece apropiado.

¿Cuál es el método principal? Es un método con estas propiedades:

  • Es público
  • Es estático
  • No tiene un valor de retorno (de ahí la palabra reservada void)
  • Se llama main (todas las letras en minúsculas)
  • Tiene solo un parámetro que es de tipo String[], puede tener cualquier nombre, pero generalmente se llama args.

Este es el punto de entrada para un programa Java. Sin uno, su código no será ejecutable por una computadora. Cuando el programa se ejecuta, ese es el primer método que se va a ejecutar.

Como se mencionó, el método main puede ser definido dentro de cualquier clase, incluso podríamos ponerlo en la clase Saludos, pero sería una mala idea. En general es bueno tener clases que hagan una cosa específica: las hace más fáciles de entender y reutilizar. Si la clase Saludos tiene métodos para generar saludos esa ya es una responsabilidad. No tiene sentido agregar además la responsabilidad de tener el punto de entrada del programa. Entonces el método main() debería estar en una clase propia.

Para imprimir datos en la salida estándar, que por defecto es la terminal de tu computadora, puede usar el método println() del objeto System.out, que recibe un String como parámetro.

Paquetes

Código 02 - Saludos pero con paquetes
package code.jugs.saludos;

  public class Saludos {

    public static String general() {
  return para("Mundo");
} 

public static String para(String quien) {
  return String.format("Hola %s!", quien);
  }
} 
package code.jugs.saludos;

    public class Main {

     public static void main(String[] args) {
      System.out.println(Saludos.general());
      System.out.println(Saludos.para("Java"));
  }
} 

Imagínate cuántos proyectos de software tienen una clase Usuario. Podría darse el caso de que estés desarrollando un sistema que utilice una biblioteca externa ¿qué pasa si tu código y el de ellos tienen una clase con el mismo nombre? Cuando te refieres a esa clase, ¿cómo sabría el compilador qué código usar? Bueno, resulta que como humanos tenemos apellidos, mientras que las clases en Java tienen paquetes. Cada clase debería tener un paquete, y cada paquete debería constar de al menos 3 partes separadas por puntos: la costumbre es que las dos primeras sean el dominio inverso de su empresa, por ejemplo. com.java, y el siguiente un identificador del proyecto al que pertenece la clase. Si no es una empresa, puedes utilizar cualquier cosa que consideres sea única.

Solo puede haber un paquete por clase, puede ser tan largo como quieras y siempre tendrá que ser la primera línea de una clase, que no sea un comentario.

Importaciones

Codigo 03 - Import
package code.jugs.bisiesto.calculos;
  public class Aritmetica {

    public static boolean esMúltiplo(int a, int b) {
 return (a % b) == 0;
}

  public static boolean esPar(int n) {
    return esMúltiplo(n, 2);
}

  public static boolean esImpar(int n) {
    return !esPar(n);
  }
} 
package code.jugs.biesiestos.utils;
import code.jugs.bisiestos.calculos.Aritmetica;

public class AñoUtils {
  public static boolean esBisiesto(int año) {
      return Aritmetica.esMultiplo(año, 4)
        && (Aritmetica.esMultiplo(año, 400) || !Aritmetica.esMultiplo(año, 100));
  }
} 
package code.jugs.bisiestos;

          import code.jugs.bisiestos.utils.AñoUtils;

          public class Main {

            public static void main(String[] args) {
              System.out.println(AñoUtils.esBisiesto(2024));
              System.out.println(AñoUtils.esBisiesto(2000));
              System.out.println(AñoUtils.esBisiesto(1900));
    }
} 
true
true
false

Si en su código usa una clase YearUtils, ¿cómo sabe la JVM dónde está esa clase? Bueno, resulta que no es así, por lo que debes proporcionar el nombre completo, que es solo el paquete + nombre de clase para que la JVM lo sepa. Usted proporciona esta información con declaraciones de importación. Las declaraciones de importación deben aparecer después de la declaración del paquete pero antes de la declaración de clase. Puede tener tantas importaciones como necesite, pero si usa otras clases en el mismo paquete, la declaración de importación no es necesaria. También hay algunos paquetes que no requieren declaraciones de importación porque son esenciales, como el paquete java.util de donde provienen clases como Object, String y otras.

Importaciones Static

Código 04 - Mejorando la legibilidad con import static
package code.jugs.biesiestos.utils;
  
import static code.jugs.bisiestos.calculos.Aritmetica.esMúltiplo;
  public class AñoUtils {
    public static boolean esBisiesto(int año) {
    return esMúltiplo(año, 4) && (esMúltiplo(año, 400) || !esMúltiplo(año, 100));
    }
} 

Por temas de legibilidad, podríamos interesarnos en llamar a las funciones en otra clase, solo por su nombre. Para tal fin podemos usar un import static. Un import static es como un import, pero con el modificador static después de import, y lo que sigue es el paquete de la clase, el nombre de la clase y finalmente el nombre de la función, separados por puntos.

Si quisiera hacer lo mismo con otra función de la misma clase, debo agregar un nuevo import static.

¿Cuándo conviene usar un import static y no un simple import? Es un tema exclusivamente de legibilidad. No hay ninguna funcionalidad impactada por usar uno u otro.

Constantes de Clase

Código 05 - Constantes de Clase
package code.jugs.basica.fisica;

  public class FísicaPlanetaria {
    private static final double G = 6.67430e-11;
    private static final double GRAVEDAD_SUPERFICIAL_TIERRA = gravedadSuperficial(5.972e24, 6.378e6);
    private static final double GRAVEDAD_SUPERFICIAL_MARTE = gravedadSuperficial(6.421e23, 3.3972e6);
  public static double gravedadSuperficial(double masa, double radio) {
     return G / Math.pow(radio, 2.0) * masa;
    } 
  public static double pesoEnMarte(double peso) {
     return GRAVEDAD_SUPERFICIAL_MARTE / GRAVEDAD_SUPERFICIAL_TIERRA * peso;
  } 
public static double energíaGravitatoria(double masa1, double masa2, double distancia) {
return -((G * masa1 * masa2) / distancia);
  }
} 

En las líneas 5 a 7 creamos constantes de clase, indicados por los modificadores static y final. El modificador private simplemente indica que la constante solo va a ser usada dentro de la misma clase FísicaPlanetaria, en contraposición al otro modificador de visibilidad que hemos visto: public. Más allá de esos modificadores, una constante de clase se declara como una variable cualquiera, utilizando su tipo de dato en vez de <var>.

Al igual que las variables, las constantes de clase se crean para darle un nombre a un valor. La diferencia es que siendo constantes de clase estas se calculan una sola vez. Así que sin importar cuantas veces llamemos la función pesoEnMarte(), el cálculo de la gravedad superficial de la tierra y de marte se calcula una sola vez. También podría pasar que múltiples funciones usen esta misma constante pero nuevamente al ser una constante de clase solo se calculará una vez.

Esto permite una optimización en desempeño pero también mejora la legibilidad del código al dejar claro que la variable G en gravedadSuperficial() y en energíaGravitatoria() es realmente la misma.

Especificaciones

Código 05 - Constantes de Clase
package code.jugs.basica.aritmetica;
public class Aritmetica {
  /**
  * Verifica si un número es múltiplo de otro
  * *
  @param a, un número entero
  * @param b, un número entero diferente de 0
  * @return true si b es múltiplo de a, false en caso contrario
  */
public static boolean esMultiplo(int a, int b) {
return (a % b) == 0;
  } 
  /**
  * Verifica si un número es par.
  * Esta implementación equivale a verificar que el número
  * sea divisible por 2. Bajo esta implementación, 0 es par.
  * *
  @param n, un número entero
  * @return true if a is a multiple of b, false otherwise
  */
public static boolean esPar(int n) {
return esMultiplo(n, 2);
  }
} 

A veces tenemos errores en nuestros programas porque hacemos suposiciones sobre las funciones que usamos en nuestro código. Es perfectamente normal que su función tenga condiciones previas: condiciones que los parámetros deben cumplir para que la función funcione correctamente, p. isLeap() espera un año positivo. También es una muy buena idea que su función especifique sus condiciones posteriores: qué puede esperar del valor de retorno, p. ¿es positivo? ¿Está siempre entre un rango, etc. Las condiciones previas y posteriores de un método se conocen colectivamente como especificación de una función?

Java proporciona Javadocs para escribir especificaciones. Los Javadocs comienzan con /** y terminan con */. Por motivos estéticos, es común agregar un * extra en cada línea. Primero, proporcione una breve descripción de lo que hace el método. Si elige un buen nombre, la descripción simple no es tan importante, pero la descripción es un lugar donde puede brindar más detalles sobre el desempeño del método, detalles sobre su implementación u otra información útil. Además de la descripción, debe tener un @param y luego el nombre del parámetro y luego explicar sus condiciones previas, si las hubiera. Finalmente tenga un @return para especificar las condiciones posteriores.

Existe una herramienta oficial también llamada Javadocs que produce documentación escrita en HTML, de hecho, la documentación oficial que usted ha escrito se produjo con esa herramienta. También se pueden escribir Javadocs para clases, lo cual también es una buena idea

Nota sobre el material

El material seguirá utilizando la convención usada hasta ahora de mostrar los ejemplos de código como funciones sin modificadores public y static y sin ponerlas como parte de una clase, esto con el fin de ahorrar espacio y hacer el código más fácil de leer.

Si vas a copiar ese código en Eclipse debes recordar crear una clase nueva o reutilizar una clase existente. Si vas a crear una nueva entonces debes escoger también un nombre de paquete.

Los ejemplos de uso también se seguirán mostrando como antes, para probarlos debes ir a la clase Main de tu proyecto y usar System.out.println() y utilizar el llamado de ejemplo como argumento, y puedes ver en la salida estándar que obtienes el mismo valor indicado.

Ejercicios

E5.1

Rellena el hueco con una de las opciones numeradas, de modo que si ejecutáramos el programa obtuviéramos el resultado indicado.

E5.1
package code.jugs.basica;
public class Main {
  public static void ___(String[] args) {
    System.out.println("¡Hola Mundo!");
  }
}
¡Hola Mundo!
  1. Main
  2. main
  3. init
  4. saludos

E5.2

Rellena el hueco con una de las opciones numeradas, de modo que no haya errores de compilación y se produzca el resultado indicado al ejecutar el programa:

package code.jugs.basica.aritmetica;
public class Aritmética {
  public static double hipotenusa(double a, double b) {
    return Math.sqrt((a * a) + (b * b));
  }
}
package code.jugs.basica;
import ___;
public class Main {
  public static void main(String[] args) {
    System.out.println(Aritmética.hipotenusa(3.0, 4.0));
  }
}
5.0
  1. code.jugs.basica.aritmetica.Aritmética
  2. code.jugs.basica.aritmetica
  3. Aritmética
  4. hipotenusa

E5.3

Rellena el hueco con una de las opciones numeradas, de modo que no haya errores de compilación:

package code.jugs.basica.aritmetica;
public class Aritmética {
  public static boolean esMultiplo(int a, int b) {
    return (a % b) == 0;
  }
}
package code.jugs.basica.tiempo;
import ___ code.jugs.basica.aritmetica.Aritmética.esMúltiplo;
  public class AñoUtils {
    public static boolean esAñoBisiesto(int año) {
      return esMultiplo(año, 4)
        && (esMultiplo(año, 400) || !esMúltiplo(año, 100));
  }
}
  1. public
  2. boolean
  3. static
  4. package

© 2022 Carlos Obregón. This work is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0)

Scroll to Top