Aprende Java desde cero

Entonces, ¿quieres programar en Java? Eso es genial, y ha venido al lugar correcto. La serie Java 101 proporciona una introducción autoguiada a la programación Java, que comienza con los conceptos básicos y cubre todos los conceptos básicos que necesita saber para convertirse en un desarrollador Java productivo. Esta serie es técnica, con muchos ejemplos de código para ayudarlo a comprender los conceptos a medida que avanzamos. Asumiré que ya tiene algo de experiencia en programación, pero no en Java.

Este primer artículo presenta la plataforma Java y explica la diferencia entre sus tres ediciones: Java SE, Java EE y Java ME. También aprenderá sobre el rol de la máquina virtual Java (JVM) en la implementación de aplicaciones Java. Le ayudaré a configurar un Java Development Kit (JDK) en su sistema para que pueda desarrollar y ejecutar programas Java, y le ayudaré a comenzar con la arquitectura de una aplicación Java típica. Finalmente, aprenderá a compilar y ejecutar una aplicación Java simple.

Actualizado para Java 12 y el nuevo JShell

Esta serie se ha actualizado para Java 12 e incluye una introducción rápida a lo nuevo jshell: una herramienta interactiva para aprender Java y crear prototipos de código Java.

descargar Obtener el código Descargar el código fuente, por ejemplo, las aplicaciones de este tutorial. Creado por Jeff Friesen para JavaWorld.

¿Que es Java?

Puede pensar en Java como un lenguaje orientado a objetos de propósito general que se parece mucho a C y C ++, pero que es más fácil de usar y le permite crear programas más robustos. Desafortunadamente, esta definición no le da mucha información sobre Java. En 2000, Sun Microsystems (creador de la plataforma Java) describió Java de esta manera: 

Java es un lenguaje de computadora simple, orientado a objetos, experto en redes, interpretado, sólido, seguro, de arquitectura neutral, portátil, de alto rendimiento, multiproceso y dinámico.

Consideremos cada una de estas definiciones por separado.

Java es un lenguaje simple . Java se modeló inicialmente después de C y C ++, menos algunas características potencialmente confusas. Los punteros, la herencia de implementaciones múltiples y la sobrecarga de operadores son algunas de las características de C / C ++ que no forman parte de Java. Una característica que no es obligatoria en C / C ++, pero que es esencial para Java, es una función de recolección de basura que recupera automáticamente objetos y matrices.

Java es un lenguaje orientado a objetos . El enfoque orientado a objetos de Java permite a los desarrolladores trabajar en la adaptación de Java para resolver un problema, en lugar de obligarnos a manipular el problema para cumplir con las limitaciones del lenguaje. Esto es diferente de un lenguaje estructurado como C. Como ejemplo, mientras que Java le permite concentrarse en los objetos de la cuenta de ahorros, C requiere que piense por separado sobre el estado de la cuenta de ahorros (como el saldo) y los comportamientos (como el depósito y el retiro).

Java es un lenguaje experto en redes . La extensa biblioteca de red de Java facilita el manejo de los protocolos de red del Protocolo de control de transmisión / Protocolo de Internet (TCP / IP) como HTTP (Protocolo de transferencia de hipertexto) y FTP (Protocolo de transferencia de archivos), y simplifica la tarea de realizar conexiones de red. Además, los programas Java pueden acceder a objetos a través de una red TCP / IP, a través de localizadores uniformes de recursos (URL), con la misma facilidad que tendría para acceder a ellos desde el sistema de archivos local.

Java es un lenguaje interpretado . En tiempo de ejecución, un programa Java se ejecuta indirectamente en la plataforma subyacente (como Windows o Linux) a través de una máquina virtual (que es una representación de software de una plataforma hipotética) y el entorno de ejecución asociado. La máquina virtual traduce los códigos de bytes del programa Java (instrucciones y datos asociados) a instrucciones específicas de la plataforma mediante la interpretación. La interpretación es el acto de averiguar qué significa una instrucción de código de bytes y luego elegir instrucciones específicas de plataforma "enlatadas" equivalentes para ejecutar. Luego, la máquina virtual ejecuta esas instrucciones específicas de la plataforma.

La interpretación facilita la depuración de programas Java defectuosos porque hay más información disponible en tiempo de compilación en tiempo de ejecución. La interpretación también hace posible retrasar el paso de enlace entre las partes de un programa Java hasta el tiempo de ejecución, lo que acelera el desarrollo.

Java es un lenguaje robusto . Los programas Java deben ser fiables porque se utilizan tanto en aplicaciones de consumo como de misión crítica, que van desde reproductores de Blu-ray hasta sistemas de control aéreo o de navegación de vehículos. Las características del lenguaje que ayudan a que Java sea robusto incluyen declaraciones, verificación de tipos duplicados en tiempo de compilación y tiempo de ejecución (para evitar problemas de desajuste de versiones), arreglos verdaderos con verificación automática de límites y la omisión de punteros. (Consulte "Funciones elementales del lenguaje Java" para comenzar con los tipos, literales, variables y más del lenguaje Java).

Otro aspecto de la solidez de Java es que los bucles deben ser controlados por expresiones booleanas en lugar de expresiones enteras donde 0 es falso y un valor distinto de cero es verdadero. Por ejemplo, Java no permite un bucle de estilo C, por ejemplo, while (x) x++;porque el bucle podría no terminar donde se esperaba. En su lugar, debe proporcionar explícitamente una expresión booleana, como while (x != 10) x++;(lo que significa que el ciclo se ejecutará hasta que sea xigual a 10).

Java es un lenguaje seguro . Los programas Java se utilizan en entornos distribuidos o en red. Debido a que los programas Java pueden migrar y ejecutarse en las diversas plataformas de una red, es importante proteger estas plataformas de códigos maliciosos que podrían propagar virus, robar información de tarjetas de crédito o realizar otros actos maliciosos. Las características del lenguaje Java que admiten la solidez (como la omisión de punteros) funcionan con características de seguridad como el modelo de seguridad de la zona de pruebas de Java y el cifrado de clave pública. Juntas, estas características evitan que los virus y otros códigos peligrosos causen estragos en una plataforma desprevenida.

En teoría, Java es seguro. En la práctica, se han detectado y explotado varias vulnerabilidades de seguridad. Como resultado, Sun Microsystems y Oracle ahora continúan lanzando actualizaciones de seguridad.

Java es un lenguaje de arquitectura neutral . Las redes conectan plataformas con diferentes arquitecturas basadas en varios microprocesadores y sistemas operativos. No puede esperar que Java genere instrucciones específicas de la plataforma y que todas las plataformas que forman parte de una red "comprendan" estas instrucciones. En cambio, Java genera instrucciones de código de bytes independientes de la plataforma que son fáciles de interpretar para cada plataforma (a través de su implementación de la JVM).

Java es un lenguaje portátil . La neutralidad de la arquitectura contribuye a la portabilidad. Sin embargo, la portabilidad de Java es más que instrucciones de código de bytes independientes de la plataforma. Tenga en cuenta que los tamaños de los tipos de números enteros no deben variar. Por ejemplo, el tipo de entero de 32 bits siempre debe estar firmado y ocupar 32 bits, independientemente de dónde se procese el entero de 32 bits (por ejemplo, una plataforma con registros de 16 bits, una plataforma con registros de 32 bits o una plataforma con registros de 64 bits). Las bibliotecas de Java también contribuyen a la portabilidad. Cuando es necesario, proporcionan tipos que conectan el código Java con capacidades específicas de la plataforma de la manera más portátil posible.

Java es un lenguaje de alto rendimiento . La interpretación produce un nivel de desempeño que suele ser más que adecuado. Para escenarios de aplicación de muy alto rendimiento, Java utiliza la compilación justo a tiempo, que analiza las secuencias de instrucciones de código de bytes interpretadas y compila las secuencias de instrucciones interpretadas con frecuencia en instrucciones específicas de la plataforma. Los intentos posteriores de interpretar estas secuencias de instrucciones de código de bytes dan como resultado la ejecución de instrucciones equivalentes específicas de la plataforma, lo que aumenta el rendimiento.

Java es un lenguaje multiproceso . Para mejorar el rendimiento de los programas que deben realizar varias tareas a la vez, Java admite el concepto de ejecución por subprocesos . Por ejemplo, un programa que administra una interfaz gráfica de usuario (GUI) mientras espera la entrada de una conexión de red utiliza otro hilo para realizar la espera en lugar de utilizar el hilo GUI predeterminado para ambas tareas. Esto mantiene la GUI receptiva. Las primitivas de sincronización de Java permiten que los subprocesos comuniquen datos entre ellos de forma segura sin dañarlos. (Consulte la programación con subprocesos en Java que se analiza en otra parte de la serie Java 101).

Java es un lenguaje dinámico . Debido a que las interconexiones entre el código del programa y las bibliotecas ocurren dinámicamente en tiempo de ejecución, no es necesario vincularlas explícitamente. Como resultado, cuando un programa o una de sus bibliotecas evoluciona (por ejemplo, para corregir un error o mejorar el rendimiento), un desarrollador solo necesita distribuir el programa o la biblioteca actualizados. Aunque el comportamiento dinámico da como resultado menos código para distribuir cuando se produce un cambio de versión, esta política de distribución también puede provocar conflictos de versiones. Por ejemplo, un desarrollador elimina un tipo de clase de una biblioteca o le cambia el nombre. Cuando una empresa distribuye la biblioteca actualizada, los programas existentes que dependen del tipo de clase fallarán. Para reducir en gran medida este problema, Java admite un tipo de interfaz, que es como un contrato entre dos partes. (Consulte interfaces, tipos y otras características del lenguaje orientado a objetos que se analizan en otra parte de la serie Java 101).

Analizar esta definición nos enseña mucho sobre Java. Más importante aún, revela que Java es tanto un lenguaje como una plataforma. Aprenderá más sobre los componentes de la plataforma Java, es decir, la máquina virtual Java y el entorno de ejecución de Java, más adelante en este tutorial.

Tres ediciones de Java: Java SE, Java EE y Java ME

Sun Microsystems lanzó el kit de desarrollo de software Java 1.0 (JDK) en mayo de 1995. El primer JDK se utilizó para desarrollar aplicaciones de escritorio y subprogramas, y posteriormente Java evolucionó para abarcar la programación de dispositivos móviles y servidores empresariales. El almacenamiento de todas las bibliotecas necesarias en un solo JDK habría hecho que el JDK fuera demasiado grande para distribuirlo, especialmente porque la distribución en la década de 1990 estaba limitada por CD de tamaño pequeño y velocidades de red lentas. Dado que la mayoría de los desarrolladores no necesitaban hasta la última API (un desarrollador de aplicaciones de escritorio difícilmente necesitaría acceder a las API empresariales de Java), Sun dividió Java en tres ediciones principales. Estos eventualmente se conocieron como Java SE, Java EE y Java ME:

  • Java Platform, Standard Edition (Java SE) es la plataforma Java para desarrollar aplicaciones del lado del cliente (que se ejecutan en equipos de escritorio) y subprogramas (que se ejecutan en navegadores web). Tenga en cuenta que, por razones de seguridad, los subprogramas ya no son compatibles oficialmente.
  • Java Platform, Enterprise Edition (Java EE ) es la plataforma Java construida sobre Java SE, que se utiliza exclusivamente para desarrollar aplicaciones de servidor orientadas a la empresa. Las aplicaciones del lado del servidor incluyen servlets Java , que son programas Java que son similares a los applets pero que se ejecutan en un servidor en lugar de un cliente. Los servlets se ajustan a la API de Java Servlet.
  • Java Platform, Micro Edition (Java ME) también se basa en Java SE. Es la plataforma Java para desarrollar MIDlets , que son programas Java que se ejecutan en dispositivos de información móviles, y Xlets , que son programas Java que se ejecutan en dispositivos integrados.

Java SE es la plataforma básica de Java y es el foco de la serie Java 101. Los ejemplos de código se basarán en la versión más reciente de Java en el momento de escribir este artículo, Java 12.

La plataforma Java y JVM

Java es tanto un lenguaje de programación como una plataforma para ejecutar código Java compilado. Esta plataforma consiste principalmente en la JVM, pero también incluye un entorno de ejecución que admite la ejecución de la JVM en la plataforma subyacente (nativa). La JVM incluye varios componentes para cargar, verificar y ejecutar código Java. La Figura 1 muestra cómo se ejecuta un programa Java en esta plataforma. 

Jeff Friesen

En la parte superior del diagrama hay una serie de archivos de clase de programa, uno de los cuales se indica como el archivo de clase principal. Un programa Java consta al menos del archivo de clase principal, que es el primer archivo de clase que se carga, verifica y ejecuta.

La JVM delega la carga de clases en su componente cargador de clases. Los cargadores de clases cargan archivos de clases de varias fuentes, como sistemas de archivos, redes y archivos de almacenamiento. Aíslan la JVM de las complejidades de la carga de clases.

Un archivo de clase cargado se almacena en la memoria y se representa como un objeto creado a partir de la Classclase. Una vez cargado, el verificador de código de bytes verifica las diversas instrucciones de código de bytes para asegurarse de que sean válidas y no comprometan la seguridad.

Si los códigos de bytes del archivo de clase no son válidos, la JVM termina. De lo contrario, su componente de intérprete interpreta el código de bytes una instrucción a la vez. La interpretación identifica instrucciones de código de bytes y ejecuta instrucciones nativas equivalentes.

Algunas secuencias de instrucciones de código de bytes se ejecutan con más frecuencia que otras. Cuando el intérprete detecta esta situación, el compilador Just-In-Time (JIT) de JVM compila la secuencia de código de bytes en código nativo para una ejecución más rápida.

Durante la ejecución, el intérprete normalmente encuentra una solicitud para ejecutar el código de bytes de otro archivo de clase (que pertenece al programa o a una biblioteca). Cuando esto sucede, el cargador de clases carga el archivo de clase y el verificador de código de bytes verifica el código de bytes del archivo de clase cargado antes de que se ejecute. También durante la ejecución, las instrucciones de código de bytes pueden solicitar que la JVM abra un archivo, muestre algo en la pantalla, emita un sonido o realice otra tarea que requiera cooperación con la plataforma nativa. La JVM responde utilizando su tecnología de puente Java Native Interface (JNI) para interactuar con la plataforma nativa para realizar la tarea.