Java a fondo. Curso de programación - Pablo Augusto Sznajdleder - E-Book

Java a fondo. Curso de programación E-Book

Pablo Augusto Sznajdleder

0,0
24,99 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.
Mehr erfahren.
Beschreibung

Descubra el arte y la ciencia de programar en Java y desarrollar aplicaciones. Programar en Java y desarrollar aplicaciones Java son cosas diferentes. Si está interesado en adentrase en ambos caminos, ha llegado al libro indicado. En él conocerá no solo el lenguaje de programación Java, sino también conceptos de diseño y herramientas genéricas o frameworks que le facilitarán la automatización de las tareas rutinarias y repetitivas del desarrollo. En Java a fondo encontrará, desde cero, todas las explicaciones indispensables para navegar por el ecosistema Java. Partirá desde los fundamentos del lenguaje de programación y profundizará hasta aprender el desarrollo de aplicaciones Java que respeten los alineamientos de diseño recomendados por los expertos de la industria. Entre los temas que este libro recoge para desarrollar una aplicación Java, distribuida, basada en microservicios y con acceso a bases de datos, destacan los siguientes: "El lenguaje Java "La programación orientada a objetos "El JDBC (acceso a base de datos) "Los patrones de diseño, archivos, networking, multithreading y reflection (introspección de clases y objetos) "El frontend y el backend; este último dividido entre las capas de negocio (façade) y de acceso a datos (DAO). Además, este libro pone en evidencia la necesidad de utilizar frameworks para automatizar ciertas tareas del desarrollo y permitir que, como programador, se enfoque en resolver el problema de su negocio. Por ello, encontrará en esta lectura cómo diseñar, programar y utilizar emuladores de los frameworks más importantes del mercado: Hibernate (MyHibernate), Spring (MySpring) y Spring Boot (MySpringBoot). Sin duda, esta obra le proporcionará las herramientas necesarias para que destaque en el mundo del desarrollo Java, pues cubre todo lo necesario para trabajar con este lenguaje de programación más allá de la versión vigente, y le otorga especial atención a las funciones implementadas en Java 10 y posteriores. Sea un programador principiante o un desarrollador experimentado, este libro es una inversión muy valiosa si desea profundizar en su comprensión y habilidades en Java, y le preparará para los desafíos de programación del mañana.

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern

Seitenzahl: 335

Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



 

 

 

Java a fondo. Curso de programación

Pablo Augusto Sznajdleder

Derechos reservados © Alfaomega Grupo Editor Argentino S.A.

Quinta edición: 2023

ISBN: 978-987-8983-77-6

Quinta edición: MARCOMBO, S.L. 2024

© 2024 MARCOMBO, S.L.

www.marcombo.com

Cualquier forma de reproducción, distribución, comunicación pública o transformación de esta obra solo puede ser realizada con la autorización de sus titulares, salvo excepción prevista por la ley. Diríjase a CEDRO (Centro Español de Derechos Reprográficos, www.cedro.org) si necesita fotocopiar o escanear algún fragmento de esta obra

ISBN del libro en papel: 978-84-267-3830-1

ISBN del libro electrónico: 978-842-6738-32-5

Producción del ePub: booqlab

 

 

Este trabajo está dedicado muy especialmente a la memoria de mi amigo, colega y vecino Claudio Algieri.

 

La familia de Pablo, retratada por Lucía Belén Berro @lavidadetontacursi

Acerca del autor

Pablo Augusto Sznajdleder es ingeniero en sistemas de información, licenciado de la Universidad Tecnológica Nacional (UTN.BA, 1999).

Su tesis de maestría (UTN.BA, 2018) describe cómo implementar transferencias de conocimientos asistidas por tecnologías de mediación de interacción.

Profesor en la cátedra de Algoritmos y Estructura de Datos, y director de cátedra en Patrones Algorítmicos para Estructuras Avanzadas, ambas materias en UTN.BA.

Autor de otras obras, además de la presente: Algoritmos a fondo y JEE a fondo, todas publicadas por Alfaomega.

Entre 1996 y 2001 trabajó como instructor Java para Sun Microsystems y Oracle Argentina. Obtuvo en 1997 las certificaciones SCJP y SCJD. Estas fueron las primeras certificaciones Java acreditadas en Argentina y estuvieron entre las primeras logradas en Latinoamérica.

Hoy, con más de veinticinco años de experiencia en tecnología Java, se desempeña en el ámbito profesional como consultor e instructor, proveyendo servicios de coaching y capacitación para las empresas líderes del país.

           /thejavalistener

Antes de comenzar a leer

En este libro se utiliza la tipografía Courier en los casos en los que se hace referencia a código o acciones por realizar en el ordenador, ya sea en un ejemplo o cuando se refiere a alguna función mencionada en el texto. También se usa para indicar menús de programas, teclas, URL, grupos de noticias o direcciones de correos electrónicos.

Los términos o definiciones cuyos significados están muy asociados al inglés se expresan en ese idioma en cursiva.

Estos recursos también están disponibles en www.marcombo.info con el código JAVA24.

Una vez en la página, debe darse de alta y buscar este libro.

Contenido

Prólogo

Agradecimientos

CAPÍTULO 1

Introducción al lenguaje de programación Java

1.1. Introducción

1.1.1. Java en sus inicios

1.1.2.Java Standard Edition y Java Enterprise Edition

1.1.3. Desarrollo de aplicaciones

1.1.4. Hola Mundo!

1.1.5.Integrated Development Environment

1.1.6. Versiones Java

1.2. Elementos del lenguaje de programación

1.2.1. Entrada y salida estándar

1.2.2. Identificadores y declaración de variables

1.2.3. Comentarios en el código

1.2.4. Tipos de dato

1.2.4.1. Tipos de dato primitivos

1.2.4.2.Wrappers: clases que representan a los tipos primitivos

1.2.4.3.Autoboxing: conversión automática entre tipos primitivos y wrappers

1.2.5. Constantes

1.2.6. Valores literales

1.2.7. Literales expresados en otros sistemas de numeración

1.2.7.1. Números enteros expresados en binario

1.2.7.2. Números enteros expresados en hexadecimal

1.2.7.3. Valores enteros expresados en octal

1.2.8. Caracteres especiales

1.2.9. Estructuras de control

1.2.10. Operadores aritméticos, relacionales y lógicos

1.2.11. Funciones o métodos estáticos

1.2.12. Inferencia de tipo de dato

1.2.13. Clases y objetos

1.3. Cadenas de caracteres

1.3.1. Tratamiento de cadenas de caracteres

1.3.1.1. Determinar la longitud de una cadena

1.3.1.2. Determinar si una cadena es la cadena vacía

1.3.1.3. Acceder a los caracteres de una cadena

1.3.1.4. Comparar cadenas

1.3.1.5. Determinar la posición que ocupa un carácter dentro de una cadena

1.3.1.6. Determinar la posición que ocupa una subcadena dentro de una cadena

1.3.1.7. Convertir a mayúsculas y minúsculas

1.3.1.8. Subcadenas

1.3.1.9. Separar una cadena en varias subcadenas

1.3.1.10. Conversión entre cadenas y números

1.3.1.11. Concatenar cadenas

1.3.2. Invarianza de las cadenas de caracteres

1.3.3. Cadenas de caracteres dinámicas

1.3.3.1. Concatenar cadenas de caracteres

1.3.3.2. Modificar los caracteres de una cadena

1.4. Autoevaluación y ejercicios

1.5. Resumen

CAPÍTULO 2

Programación orientada a objetos

2.1. Introducción

2.2. Clases y objetos

2.2.1. Métodos

2.2.2. Herencia y sobreescritura de métodos

2.2.3. Método toString

2.2.4. Método equals

2.2.5.Annotations

2.2.6. Declarar y crear objetos

2.2.7. Constructores

2.2.8. Breve repaso de lo visto hasta aquí

2.2.9. Convenciones de nomenclatura

2.2.9.1. Nombres de clases

2.2.9.2. Nombres de métodos

2.2.9.3. Nombres de atributos

2.2.9.4. Nombres de variables de instancia

2.2.9.5. Nombres de constantes

2.2.10. Sobrecarga

2.2.11. Encapsulamiento

2.2.12. Clase GregorianCalendar

2.2.13. Métodos obsoletos (deprecated)

2.2.14. Visibilidad de métodos y atributos

2.2.15.Packages (paquetes)

2.2.15.1. Nombre simple de una clase

2.2.15.2. Nombre completo de una clase

2.2.16. Estructura de paquetes y CLASSPATH

2.2.17.Aplication Programming Interface (API)

2.2.18. Representación gráfica UML

2.2.19. Importar clases de otros paquetes

2.3. Herencia y polimorfismo

2.3.1. Polimorfismo

2.3.2. Constructores de subclases

2.3.3. Referencia super

2.3.4. Referencia this

2.3.5. Clase abstracta

2.3.6. Constructores de clases abstractas

2.3.7. Instancias

2.3.8. Variables de instancia

2.3.9. Variables de clase

2.3.10. Gestión dinámica de memoria y garbage collector

2.3.11. Método Finalize

2.3.12. Constantes

2.3.13. Métodos de clase

2.3.14. Clases utilitarias

2.3.15. Referencias estáticas

2.3.16. Bloques estáticos

2.3.17. Colecciones (introducción)

2.3.18. Clases genéricas

2.4.Interfaces y factorías de objetos

2.4.1. Desacoplamiento de clases

2.4.2.Factory method

2.4.3. Abstracción a través de interfaces

2.4.4.InterfaceComparable

2.4.5. Desacoplar todavía más

2.4.6. Expresiones lambda

2.4.7.InterfaceComparator

2.5.Framework de colecciones de Java

2.5.1. Listas y colecciones

2.5.2.For-each

2.5.3. Cambio de implementación

2.5.4. Mapas o diccionarios de datos

2.5.5. Las clases Collections y Arrays

2.5.5.1. Convertir arrays en List y viceversa

2.5.5.2. Ordenar listas y arrays

2.5.6. La clase Properties

2.5.6.1. Grabar properties en un archivo de texto

2.5.6.2. Leer properties almacenadas en un archivo de texto

2.5.6.3. Archivo de propiedades ubicado dentro del CLASSPATH

2.5.6.4. Simplificando el modo en que accedemos a un archivo de propiedades

2.6. Excepciones

2.6.1. Introducción

2.6.2. Ejemplo de uso

2.6.3. Excepciones declarativas y no declarativas

2.6.4.Stack trace

2.6.5. Excepciones propias

2.6.6. Bloque try-catch-finally

2.6.7. Bloque try con recurso

2.7. Autoevaluación y ejercicios

2.8. Resumen

CAPÍTULO 3

Lambda, streams y programación funcional

3.1. Introducción

3.2.Interfaces funcionales

3.2.1. Prototipo de un método o función

3.2.2. Referencias a métodos

3.3. Expresiones lambda

3.4. Funciones, predicados y consumidores

3.4.1. La interface Predicate

3.4.2. La interface BiPredicate

3.4.3. La interface Consumer

3.4.4. La interface BiConsumer

3.4.5. La interface Function

3.4.6. La interface BiFunction

3.5.Streams

3.5.1. Introducción

3.5.2. Fundamentos

3.5.3. Operaciones sobre streams

3.5.3.1. Operaciones intermedias

3.5.3.2. Operaciones finales

3.5.4. Ejemplos

3.5.4.1. Filtrar elementos de una colección

3.5.4.2. Buscar un elemento dentro de una colección

3.5.4.3. Iterar y mostrar los elementos de la colección

3.5.4.4. Procesar los elementos de la colección

3.6. Autoevaluación y ejercicios

3.7. Resumen

CAPÍTULO 4

Acceso a bases de datos (JDBC)

4.1. Introducción

4.1.1.Driver y la cadena de conexión URL

4.1.2.Queries y updates

4.1.3. Estructura de un programa que usa JDBC

4.1.4. Conexión cerrada frente a conexión nula

4.2. Ejecutar sentencias SQL

4.2.1.Queries

4.2.1.1. Obtener múltiples filas

4.2.1.2. Obtener una o ninguna fila

4.2.1.3.Queries con JOIN

4.2.1.4.Queries de funciones de la base de datos

4.2.1.5.Queries parametrizados

4.2.1.6.Queries con fechas

4.2.1.7. Funciones propietarias de la base de datos

4.2.2.Updates

4.2.2.1. Insertar una fila

4.2.2.2. Valores autoincrementales

4.2.2.3. Modificar una fila

4.2.2.4. Borrar una fila

4.2.2.5. Transacciones

4.3. Administrar la conexión JDBC

4.3.1. Factoría para instanciar la conexión

4.3.2. Singleton para garantizar una única instancia de la conexión

4.3.3.Properties para parametrizar los atributos de la conexión

4.3.4. Bloque estático para registrar el driver una única vez

4.3.5.Shutdown hook para cerrar la conexión

4.4. Encapsular el acceso a los datos

4.4.1. Modelo de objetos o modelo de dominio

4.4.2.Data Access Object (DAO)

4.4.2.1. Buscar una fila (método buscar o find)

4.4.2.2. Acceso a los datos foráneos

4.4.2.3. Representación orientada a objetos (composición)

4.4.2.4. Recuperar todas las filas (método buscarTodo o findAll)

4.4.2.5. Recuperar solo un conjunto de filas (métodos buscarPor o findBy)

4.4.2.6. Insertar una fila

4.4.2.7.Update

4.4.2.8.Delete

4.4.3. Encapsular la transacción

4.5. Separar el acceso a los datos en API e implementación

4.5.1. Escribir los DAO como interfaces

4.5.2. Implementar las interfaces según una determinada tecnología

4.5.3.Factory method para abstraernos de la implementación

4.5.4.Factory method dinámico

4.6. Poniendo todo en práctica

4.6.1. Unificar las clases utilitarias de acceso a datos

4.6.2. Ejemplo completo

4.7. Autoevaluación y ejercicios

4.8. Resumen

CAPÍTULO 5

Diseño de aplicaciones Java

5.1. Introducción

5.2. Arquitectura de una aplicación Java

5.2.1. Atributos no funcionales

5.2.2.Backend y frontend

5.2.3. Capas lógicas y físicas de la aplicación

5.3. Análisis y desarrollo de una aplicación completa

5.3.1.Façade y DAO

5.3.2. Cliente

5.4. Autoevaluación y ejercicios

5.5. Resumen

CAPÍTULO 6

Introspección de clases y objetos

6.1. Introducción

6.2. Comenzando con introspección

6.2.1. Clase Class

6.2.1.1. Acceder al nombre de la clase

6.2.1.2. Acceder a los campos de la clase (variables de instancia y variables de clase)

6.2.1.3. Acceder a los métodos

6.2.1.4. Acceder a los constructores

6.2.2. Crear objetos dinámicamente

6.2.3. Invocar métodos dinámicamente

6.3.JavaBeans

6.3.1. Qué son los beans

6.3.2. Instrospectando beans

6.3.2.1. Conocer los atributos de un bean

6.3.2.2. Invocar dinámicamente los métodos de acceso

6.4.Annotations

6.5. Autoevaluación y ejercicios

6.6. Resumen

CAPÍTULO 7

Generalizaciones y desarrollo de frameworks

7.1. Introducción

7.1.1. ¿Qué es un framework?

7.1.2. ¿Frameworks propios o frameworks de terceros?

7.1.3. Sobre este capítulo

7.2.Framework de persistencia basado en ORM

7.2.1. Representación del modelo de datos relacional mediante un modelo de objetos

7.2.2. Funcionalidad y modo de uso

7.2.3. Desarrollando el método find

7.2.4. Desarrollando el método findAll

7.2.5. Otros métodos de la clase MyHibernate

7.2.5.1. Método findBy

7.2.5.2. Método insert

7.2.5.3. Método update

7.2.5.4. Método delete

7.3.Framework de inyección de dependencias

7.3.1. Funcionalidad y modo de uso

7.3.2. Desarrollo del framework

7.4. Poniendo a funcionar todo junto

7.5. Autoevaluación y ejercicios

7.6. Resumen

CAPÍTULO 8

Streams: flujos de entrada y salida de datos

8.1. Introducción

8.2. Entrada y salida estándar

8.2.1. System.out, System.in y System.err

8.2.2. Redireccionar la entrada, la salida y la salida de error estándar

8.3. Archivos

8.3.1. Escribir un archivo

8.3.2. Leer un archivo

8.3.3. Archivos de acceso aleatorio

8.3.4. Las clases java.io.File y java.nio.Files

8.4. Serialización de objetos

8.4.1. Escribir objetos en un archivo

8.4.2. Leer objetos desde un archivo

8.5.Readers y writers

8.6. Autoevaluación y ejercicios

8.7. Resumen

CAPÍTULO 9

Networking

9.1. Introducción

9.2. Conceptos básicos de networking

9.2.1.Transmission control protocol

9.2.2.User datagram protocol

9.2.3. Puertos

9.2.4. Dirección IP

9.2.5. Aplicaciones cliente/servidor

9.3. TCP

9.3.1.Socket

9.3.2. Un cliente/servidor sencillo en Java

9.3.2.1. El server

9.3.2.2. El cliente

9.4. UDP

9.5. Autoevaluación y ejercicios

9.6. Resumen

CAPÍTULO 10

Threads: multiprogramación

10.1. Introducción

10.2. Programar con threads

10.2.1. La interface runnable

10.2.2. Esperar hasta que finalice un thread

10.2.3. Ciclo de vida de un thread

10.2.4. Prioridad de ejecución

10.3. Sincronización de threads

10.3.1. Monitores y sección crítica

10.3.2. Productor / consumidor

10.4. Autoevaluación y ejercicios

10.5. Resumen

CAPÍTULO 11

Ponemos todo en práctica

11.1. Introducción

11.2. MySpringBoot

11.2.1.Server

11.2.1.1. Componentes y servicios

11.2.1.2. Ejecutar el servidor

11.2.2. Cliente

11.2.3.Request y response

11.3. Exponer los servicios del backend de una aplicación empresarial

11.3.1.Server

11.3.2. Cliente

11.3.2.1.Business delegate

11.3.2.2. La aplicación

11.4. Desarrollo de MySpringBoot

11.4.1.Server

11.4.1.1.registerComponent

11.4.1.2.runServer

11.4.2. Cliente

11.5. Autoevaluación y ejercicios

11.6. Resumen

Prólogo

Java sigue siendo un lenguaje de programación vigente, se usa ampliamente en el desarrollo de aplicaciones informáticas. También constituye un elemento importante que se aborda en la enseñanza dentro de los planes de estudio de las carreras del área de la computación.

Java es un lenguaje que obedece al paradigma orientado a objetos. Es compatible con diferentes sistemas operativos, lo que lo hace versátil. En Java se pueden implementar los patrones de diseño, elementos esenciales para el desarrollo de aplicaciones.

Este libro, Java a fondo, nos lleva de la mano de manera concisa y puntual. Presenta los elementos del lenguaje de programación y conceptos esenciales del paradigma orientado a objetos, como herencia y el polimorfismo, y conceptos clave, como las clases abstractas y las interfaces.

El libro también aborda lo relativo al acceso a bases de datos, el uso de frameworks, hilos y comunicaciones en red, patrones de diseño que siguen las recomendaciones o buenas prácticas de las aplicaciones Java.

Al final de la obra, se muestra una aplicación integral, que consiste en el desarrollo de un framework, con el fin de que el lector comprenda de mejor manera la arquitectura de una aplicación Java integral que incluye todo el contenido de este libro.

Otro punto relevante es el diseño y formato que tiene el libro. Contiene explicaciones breves, resaltando en gran manera los códigos fuente, donde la tipografía marca las palabras clave de Java. Se presenta la información relevante de varias maneras: en tablas y figuras; en códigos QR, para ayudar a descargar, instalar y configurar el entorno de desarrollo Eclipse; como enlaces a vídeos, en los que el autor se explica él mismo.

Desde el punto de vista pedagógico, es de suma importancia destacar el uso de materiales, como el libro y sus complementos en vídeo desarrollados por el autor, códigos fuente de los ejemplos y demás recursos educativos, que brindan al lector un conjunto de herramientas para reforzar lo aprendido.

Esta quinta edición es una gran herramienta, recomendable sin lugar a duda como una excelente referencia para la inmersión completa en el mundo de Java y como plataforma para el desarrollo de aplicaciones empresariales relacionadas con este lenguaje.

 

ISC. Juan Vicente García Sales, docente a tiempo completo de la Escuela Superior de Computo (Instituto Politécnico Nacional)

Agradecimientos

A mi esposa Analía, a mi hijo Octaviano y a mis amigos.

Un especial agradecimiento para Adrián Stravitz, incluido en mis amigos, por haber conservado durante 30 años mi primera publicación; y a Damián Fernández, también incluido en mis amigos, por el aguante como editor de todos mis trabajos.

CAPÍTULO 1

INTRODUCCIÓN AL LENGUAJE DE PROGRAMACIÓN JAVA

1.1. INTRODUCCIÓN

1.1.1. JAVA EN SUS INICIOS

El lenguaje de programación Java apareció en 1995. Desde entonces se caracterizó por marcar tendencia, gracias a sus aportes e innovaciones.

Durante los primeros años, la principal característica del lenguaje fue la posibilidad de programar applets, pequeños programas Java que podían ser incrustados en las páginas web para hacerlas más dinámicas e interactivas.

Pero, con el tiempo, Java se fue reconvirtiendo y posicionando más del lado del server. Gracias a esta reconversión, dejó de ser un simple lenguaje de programación para convertirse en una verdadera plataforma de desarrollo y ejecución de aplicaciones empresariales, las cuales, por supuesto, se programan en Java.

1.1.2.JAVA STANDARD EDITION Y JAVA ENTERPRISE EDITION

Para diferenciar entre el lenguaje de programación Java y la plataforma de desarrollo de aplicaciones empresariales, en 1998 se lanzó al mercado el recordado Java2, que materializó esta separación entre dos distribuciones independientes: J2SE (Java2 Standard Edition) y J2EE (Java2 Enterprise Edition).

Casi treinta años después, JSE y JEE se mantienen permanentemente actualizadas y adaptadas a las nuevas tendencias de mercado y a las realidades tecnológicas.

La edición estándar incluye el lenguaje de programación propiamente dicho, el compilador, las bibliotecas básicas y una serie de herramientas adicionales.

Por su parte, la edición empresarial se compone de un conjunto de bibliotecas que se usan en las compañías. También forman parte de esta edición una serie de lineamientos denominados patrones de diseño y un grupo de especificaciones técnicas que estandarizan la construcción de servidores.

1.1.3. DESARROLLO DE APLICACIONES

Aunque Java es un lenguaje de programación de propósitos generales, los desarrolladores solemos apegarnos fuertemente a los lineamientos y patrones de diseño recomendados en la edición empresarial.

El objetivo de este libro no es solo enseñar un lenguaje de programación, sino explicar las buenas prácticas del diseño de las aplicaciones Java, los principales patrones de diseño, el desarrollo en capas y la separación entre el frontend y el backend de la aplicación.

1.1.4. HOLA MUNDO!

En el siguiente programa, escribimos en la consola la cadena: “Hola Mundo!”.

package demo;

public class HolaMundo

{

public static void main(String args[])

{

// Escribimos en la consola

System.out.println("Hola Mundo!");

}

}

Analizaremos el código del programa línea por línea.

Comienza con la sentencia package, que indica en qué paquete (carpeta) quedará ubicado el programa.

package demo;

Los packages establecen un espacio de nombres (namespace) que hace posible que dos o más clases tengan el mismo nombre, siempre y cuando estén localizadas en diferentes paquetes. Sobre esto, así como sobre clases y objetos, hablaremos más adelante.

En la siguiente línea de código se indica el nombre de la clase:

public class HolaMundo

{

Luego, el código continúa con la función main. Cuando una clase la contiene, se convierte en un programa que se puede ejecutar.

public static void main(String args[])

{

// Escribimos en la consola

System.out.println("Hola Mundo!");

}

}

Los comentarios del programador comienzan con // (doble barra). Finalmente, la sentencia System.out.println escribe una cadena de caracteres en la consola.

Los bloques de código comienzan con { (llave que abre) y finalizan con } (llave que cierra). De este modo, el primer grupo de llaves delimita dónde comienza y dónde finaliza la clase HolaMundo. El segundo grupo de llaves establece dónde comienza y dónde finaliza la función main.

Todas las sentencias que no precedan a un bloque de código deben finalizar con ; (punto y coma).

1.1.5.INTEGRATED DEVELOPMENT ENVIRONMENT

Generalmente, para programar utilizamos una herramienta de programación que se denomina IDE, iniciales de Integrated Development Enviroment (entorno de desarrollo integrado).

La IDE nos asiste durante todo el proceso de programación, permitiéndonos editar el código fuente del programa, compilarlo, ejecutarlo, depurarlo y documentarlo, entre otras cosas.

Existen diversas IDE para trabajar con Java. Destacan principalmente las siguientes: Eclipse, NetBeans e IntelliJ IDEA. Las dos primeras son open source (gratuitas; la segunda es una herramienta de pago.

El lenguaje de programación Java es totalmente independiente de todas estas herramientas. Gracias a esto, podemos utilizar la IDE que más nos agrade.

1.1.6. VERSIONES JAVA

Desde el inicio, las versiones del lenguaje Java se denominaron JDK (iniciales de Java Development Kit). La primera fue JDK1.0.2 y la siguiente fue JDK1.1.x. A partir de JDK1.2 se comenzó a hablar de Java2. La siguiente fue Java5, Java7, Java8, Java10... La versión actual es Java19.

Cada una agrega nuevas características de programación, corrige bugs y mejora la performance de la versión anterior. Sin embargo, no todas las versiones han agregado agreguen algo significativo, en el párrafo anterior solo he incluido aquellas versiones que sí introdujeron cambios relevantes.

A partir de Java10 se tomó la decisión de liberar una nueva versión cada seis meses. De este modo, los aportes que podremos observar al pasar de una versión del lenguaje a la versión siguiente serán mínimos, en la mayoría de los casos innecesarios si los observamos desde el punto de vista del programador —y más aún desde el punto de vista de un programador con poca experiencia—.

El siguiente cuadro resume cómo se fueron incorporando las herramientas y características en cada nueva versión.

Versión

JDK

Aportes

JDK1.0.2

JDK1.0.2

Clases básicas, IO, AWT, networking, Applet

JDK1.1.x

JDK1.1.x

JDBC, tecnología de beans, RMI

Java2

JDK1.2.x

Swing

Java5

JDK1.5.x

Annotations, generics, enumeraciones

Java7

JDK1.7.x

try con recurso, inferencia de tipos genéricos

Java8

JDK1.8.x

Expresiones lambda, streams

Java10

JDK10.x

Inferencia de tipo de dato

Tabla 1.1. Evolución del lenguaje de programación Java.

Cada nueva versión es inclusiva respecto de las anteriores. Esto significa que podemos compilar con Java19 utilizando solo los recursos de Java2 o alguna versión todavía más antigua.

1.2. ELEMENTOS DEL LENGUAJE DE PROGRAMACIÓN

En este apartado estudiaremos los principales elementos de este lenguaje: estructuras de control, tipos de dato y sintaxis.

1.2.1. ENTRADA Y SALIDA ESTÁNDAR

Por defecto, la entrada estándar es el teclado y la salida, la consola. Para escribir un texto en la consola utilizamos System.out.println.

System.out.println("Hola Mundo");

En esta línea de código estamos invocando el método println sobre el objeto out, declarado como público y estático en la clase System. Todos estos conceptos los estudiaremos más adelante.

La entrada de datos a través del teclado lo hacemos con la clase Scanner, como se muestra a continuación. (Para simplificar la lectura de los ejemplos, optaremos por omitir la línea que indica el package donde la clase esté ubicada.)

En el ejemplo anterior utilizamos la sentencia import para importar la clase Scanner. Aunque hablaremos de este asunto posteriormente, podemos anticipar que con import le indicamos al compilador dónde debe ir a buscar las clases que utilizamos en el programa.

Tengamos en cuenta que ciertas clases como String y System no requieren ser importadas, porque pertenecen al core del lenguaje, con lo cual eso se hace automáticamente.

Es importante subrayar la diferencia que existe entre System.out.print y System.out.println. Ambos imprimen una cadena, pero el segundo agrega un salto de línea al final.

La clase Scanner permite ingresar datos de diferentes tipos a través de la consola. Algunos ejemplos:

1.2.2. IDENTIFICADORES Y DECLARACIÓN DE VARIABLES

Podemos declarar variables en cualquier parte del código del programa, indicando el tipo de dato y el nombre de la variable o identificador. Por ejemplo:

// Tipo: int. Variable o identificador: a

int a;

Nombres de variables válidas son fecha, iFecha, fecha3, fechaNacimiento, _fecha y fecha_nacimiento...

Nombres de variable NO válidas son fecha-nacimiento, fecha+nacimiento,

3fecha, -fecha...

1.2.3. COMENTARIOS EN EL CÓDIGO

Como en todos los lenguajes de programación, podemos incluir comentarios que nos ayuden a entender el código del programa.

Comentarios en una sola línea

Comentarios de varias líneas

// Esto es un comentario

// Esto es otro comentario

/*

Todo este parrafo esta

comentado y puede contener

tantas lineas como quiera

*/

1.2.4. TIPOS DE DATO

Aunque Java es un lenguaje de programación orientado a objetos, existen tipos de dato primitivos que conviven con las clases.

1.2.4.1. Tipos de dato primitivos

Estos son los tipos de dato. Sus longitudes, expresadas en bytes, se indican en la columna de la derecha:

Tabla 1.2. Tipos de dato primitivos y sus longitudes.

Además, existe la clase String (aunque no es un tipo de dato primitivo, se utiliza como si lo fuera).

A diferencia del lenguaje C, que permite indicar si queremos que una variable de tipo entero sea signada o no, en Java todos los tipos enteros son signados. Salvo el tipo char, que es unsigned.

1.2.4.2.Wrappers: clases que representan a los tipos primitivos

Para cada uno de los tipos primitivos existe una clase que lo representa. Permite realizar diferentes operaciones relacionadas con el tipo de dato en cuestión. A estas clases las llamaremos wrappers o envoltorios.

 

Tipo primitivo

Wrapper

 

byte

Byte

char

Character

short

Short

int

Integer

long

Long

float

Float

double

Double

boolean

Boolean

Tabla 1.3. Tipos de dato primitivos con sus correspondientes wrappers.

Algunos ejemplos sobre cómo se utilizan los wrappers:

1.2.4.3.Autoboxing: conversión automática entre tipos primitivos y wrappers

La conversión entre un tipo de dato y su correspondiente wrapper es automática. Esta característica se denomina autoboxing.

Veamos algunos ejemplos:

Como norma general, para declarar variables utilizamos los tipos de dato primitivos. Usamos los wrappers para realizar las operaciones vinculadas a cada uno de estos. Los wrappers, al ser objetos, pueden contener el valor null, lo cual, como veremos más adelante, en ocasiones puede resultar de gran utilidad.

1.2.5. CONSTANTES

Para declarar un valor constante utilizamos el modificador final. Generalmente, lo acompañamos con public y static. De este modo, lo habitual es declarar las constantes como se ilustra en el siguiente ejemplo:

1.2.6. VALORES LITERALES

Podemos expresar valores literales para todos los tipos de dato primitivos. Por ejemplo, en el siguiente código veremos cómo expresar valores de tipo char, int, boolean, double y String (este último, como sabemos ya, no es un tipo primitivo).

Como por defecto, los valores literales numéricos con decimales son double. Para expresar un valor literal de tipo float tenemos que agregarle el sufijo f.

En la práctica, resulta poco frecuente usar el tipo float. Incluso, como el tipo double suele presentar problemas de aproximación, los programadores con experiencia utilizan la clase BigDecimal en lugar del tipo primitivo double.

1.2.7. LITERALES EXPRESADOS EN OTROS SISTEMAS DE NUMERACIÓN

1.2.7.1. Números enteros expresados en binario

Anteponiendo el prefijo 0b (cero b) podemos expresar un valor literal numérico entero mediante su representación en el sistema binario. Opcionalmente, el carácter _ (guion bajo) puede ayudarnos visualmente a separar los dígitos del número.

Por cuestiones de claridad, completamos el número binario del ejemplo anterior con ceros a la izquierda. Estos ceros podrían no estar y el número seguiría siendo el mismo, como en el siguiente ejemplo (donde omitimos poner los ceros a la izquierda).

1.2.7.2. Números enteros expresados en hexadecimal

Si queremos expresar un valor numérico entero mediante su representación hexadecimal, debemos anteponer el prefijo 0x (cero equis).

1.2.7.3. Valores enteros expresados en octal

También podemos representar valores enteros como números octales, utilizando el prefijo 0 (cero).

1.2.8. CARACTERES ESPECIALES

Llamamos carácter especial a aquellos que en el código fuente de un programa tienen otro uso que no es la representación del carácter en sí mismo.

Por ejemplo, el carácter " (comilla doble) se utiliza en los programas para delimitar cadenas de caracteres; o el carácter ' (comilla simple) se utiliza para encerrar valores literales de tipo char.

Los caracteres salto de línea y tabulador, por ejemplo, al presionar sus teclas en el editor de texto producen sus respectivas acciones, pero no tienen una representación directa en forma de carácter; es decir, vemos que el texto del programa salta de una línea a otra, pero no vemos representado el carácter en sí mismo.

Todos los caracteres especiales tienen una representación literal y, por ende, pueden ser utilizados como char o parte de una cadena de caracteres.

Por ejemplo, el carácter salto de línea se representa así: \n (barra ene). En el siguiente código, incluimos un carácter salto de línea dentro de una cadena literal:

La salida será:

Esto es una cadena

que sigue en la otra linea

Análogamente, el carácter \" (barra comilla) representa a la comilla doble.

La salida será:

El lenguaje "Java" es muy bueno

El carácter \ (carácter barra) se llama carácter de escape. Para usarlo como valor literal debemos anteponerle otro carácter barra. Esto, en la jerga, se dice escapearlo.

La salida será:

El caracter \ es el caracter de escape

La siguiente tabla resume los caracteres especiales:

 

Carácter

Descripción

 

\n

Salto de línea

\b

Retorno de carro

\t

Tabulador

\"

Comilla doble

\'

Comilla simple

\\

Barra

\udddd

Cualquier carácter expresado mediante su código Unicode

Tabla 1.4. Caracteres especiales que deben ser precedidos por el carácter de escape.

1.2.9. ESTRUCTURAS DE CONTROL

A continuación, veremos las diferentes estructuras de control.

If

while

if(condicion)

{

// ...

}

else

{

// ...

}

while(condicion)

{

// ...

}

For

do-while

for(int i=0; condicion; i++)

{

// ...

}

do

{

// ...

}while(condicion);

Adicionalmente, existe el ifinline, que puede expresarse en una sola línea.

Expresión lógica ?

valor por true:

valor por false

Expresión lógica cuyo valor de verdad se debe determinar.

Resultado en caso de que la expresión resulte verdadera.

Resultado en caso de que la expresión resulte ser falsa.

En el siguiente código le pedimos al usuario que introduzca su edad. Posteriormente emitiremos un mensaje, que será diferente según cuál sea la edad que ingresó.

También podemos utilizar la estructura de decisión múltiple: switch.

En el siguiente ejemplo, el usuario tecleará el número de un día de la semana y el programa le mostrará qué día es.

El switch también puede utilizarse con cadenas de caracteres.

1.2.10. OPERADORES ARITMÉTICOS, RELACIONALES Y LÓGICOS

A continuación, veremos el resumen de los principales operadores aritméticos, relacionales y lógicos disponibles en Java.

Operadores lógicos

Sean las variables b, p y q, todas de tipo boolean. Entonces:

1.2.11. FUNCIONES O MÉTODOS ESTÁTICOS

Aunque Java es un lenguaje de programación orientada a objetos, podemos declarar métodos (funciones) e invocarlos desde el método main o cualquier otro, siempre y cuando sean métodos estáticos.

En el siguiente ejemplo vemos el código de la clase Funciones, que declara y resuelve las funciones factorial y esPrimo, que ilustran cómo se utilizan las estructuras de control que estudiamos más arriba (while, for, if) y algunos de los operadores aritméticos y lógicos.

public class Funciones

{

// Calcula el factorial de n

public static double factorial(int n)

{

double r=1;

for(int i=2; i<=n; i++)

{

r=r*i;

}

return r;

}

// Determina si n es un numero primo o no

public static boolean esPrimo(int n)

{

int i=2;

while( n%i!=0 && i<n )

{

i++;

}

return i==n; // Retorna true si son iguales

}

// Sigue mas abajo

// :

Un método (o función) estático (static) es un método de la clase. Más adelante nos ocuparemos de esta cuestión.

Ahora, continuando con el ejemplo, veamos el código del método main, que invoca las funciones (o métodos) factorial y esPrimo.

1.2.12. INFERENCIA DE TIPO DE DATO

Desde Java10 se puede prescindir de declarar el tipo de dato de las variables, pues el compilador podrá inferirlo a partir del valor que le hayamos asignado por primera vez. Aunque no es frecuente hacer uso de esta característica, pero veamos cómo se hace:

Que el tipo de dato pueda ser inferido no significa que la variable no sea tipada. El tipo de la variable se establece una vez que le asignamos su valor inicial. Luego, no podremos asignarle valores de otros tipos.

Esto lo mencionamos solo a título ilustrativo, pues en esta obra siempre trabajaremos declarando explícitamente los tipos de dato de las variables.

1.2.13. CLASES Y OBJETOS

Aunque este asunto será abordado con mayor profundidad en otro capítulo, considero importante explicar, aunque sea superficialmente, algunos conceptos, para que nos ayuden a comprender los siguientes ejemplos.

Las clases son tipos de dato definidos por el programador. Algo similar a las estructuras (struct) de C. Los objetos son variables cuyo tipo de dato es una clase.

Por lo anterior, como String es una clase, las cadenas de caracteres son objetos.

En el siguiente ejemplo, declaramos la variable a (int) y el objeto s (String).

int a;

String s;

En realidad, los objetos son punteros, o sea, que son variables cuyo contenido es una dirección de memoria. Es muy importante tenerlo en cuenta, porque muchas veces, al comparar objetos, obtendremos resultados diferentes al esperado.

Por ejemplo:

En el cuadro anterior, en la parte izquierda, observamos que las variables a y b tienen el mismo valor (5). Luego, al compararlas, el resultado será true, que es exactamente lo que hubiésemos esperado.

Sin embargo, en la parte derecha vemos un código similar, pero con cadenas. Pese a que x e y tienen el mismo valor ("Hola"), al comparar las cadenas el resultado será false, porque el primer "Hola" y el segundo están ubicados en diferentes espacios de memoria.

En el siguiente ejemplo, la comparación entre dos cadenas sí será verdadera. Esto se debe a que solo existe una única cadena "Hola", ubicada a partir de una única dirección de memoria. Y ambos punteros, x e y, contienen esta dirección.

Las clases son estructuras que agrupan datos y funciones. Por esta razón, decimos que los objetos (que son variables cuyo tipo de dato es una clase) guardan en su interior los datos y las funciones que su propia clase agrupa y declara.

Por ejemplo, la clase Auto, que veremos a continuación, tiene datos (color) y funciones (asignarColor).

En un programa podemos utilizar la clase Auto de la siguiente manera.

Justamente, el operador new (que gestiona memoria dinámicamente) retorna la dirección de la memoria obtenida. Esta dirección se la asignamos al objeto a.

1.3. CADENAS DE CARACTERES

Como ya dijimos, String no es un tipo de dato primitivo sino una clase. Por tal razón, muchas funciones para el tratamiento de las cadenas de caracteres ya están contenidas dentro de las mismas cadenas. Esto significa que un objeto string es capaz de determinar si contiene un determinado carácter, convertir sus caracteres a mayúsculas, obtener una subcadena e indicar si concuerda o no con una determinada expresión regular (regex), entre muchas otras cosas.

1.3.1. TRATAMIENTO DE CADENAS DE CARACTERES

A continuación, analizaremos las principales funciones para operar con cadenas.

1.3.1.1. Determinar la longitud de una cadena

Llamamos longitud de una cadena a la cantidad de caracteres que la componen.

1.3.1.2. Determinar si una cadena es la cadena vacía

Llamamos cadena vacía a la que no contiene ningún carácter. La cadena vacía literal se representa así: "" (comilla comilla).

1.3.1.3. Acceder a los caracteres de una cadena

Los caracteres de una cadena se enumeran según la posición que ocupan, comenzando desde cero. Luego, el método charAt retorna el carácter que se encuentra en una determinada posición. Lo llamaremos el i-ésimo carácter de la cadena.

1.3.1.4. Comparar cadenas
1.3.1.5. Determinar la posición que ocupa un carácter dentro de una cadena

El método indexOf retorna la posición de la primera ocurrencia de un determinado carácter dentro de la cadena de caracteres. Análogamente, lastIndexOf devuelve la posición de la última ocurrencia del carácter indicado.

1.3.1.6. Determinar la posición que ocupa una subcadena dentro de una cadena

Los métodos indexOf y lastIndexOf también pueden utilizarse para determinar en qué posición comienza la primera o la última ocurrencia de una determinada subcadena, dentro de la cadena de caracteres.

1.3.1.7. Convertir a mayúsculas y minúsculas

Los métodos toUpperCase y toLowerCase retornan respectivamente una copia de la cadena de caracteres en mayúsculas o en minúsculas.

1.3.1.8. Subcadenas

El método substring recibe las posiciones desde (inclusive) y hasta (no inclusive), entre las cuales se ubica la subcadena que queremos obtener. Si le pasamos un único parámetro, substring retornará la subcadena comprendida entre esta posición y el final de la cadena de caracteres.

1.3.1.9. Separar una cadena en varias subcadenas

El método split permite extraer subcadenas que se encuentran separadas entre sí por una regex.

1.3.1.10. Conversión entre cadenas y números

La clase Integer (wrapper de int) nos permite obtener un int a partir de una cadena de caracteres con formato numérico y viceversa. Análogamente, la clase Double (wrapper de double) hace lo propio entre cadenas y números con decimales.

1.3.1.11. Concatenar cadenas

Podemos utilizar el operador + (más) para concatenar cadenas de caracteres.

1.3.2. INVARIANZA DE LAS CADENAS DE CARACTERES

La clase String es invariante, es decir, que su contenido no puede ser modificado. Veamos el siguiente ejemplo:

Aunque pareciera que sí hemos modificado el contenido de s, en realidad no lo hicimos. Lo que realmente ocurre en este programa es lo siguiente:

1. Se crea la cadena "Hola" y (su dirección de memoria) se asigna a s.

2. Luego se crea la cadena "chau" y (su dirección de memoria) se asigna a s.

3. Como s ahora tiene la dirección de "chau", la cadena "Hola" quedó desreferenciada, y ya no podremos acceder a ella, porque su dirección de memoria no quedó guardada en ninguna variable (objeto).

Algo similar sucede en el siguiente caso:

Aunque parece que le concatenamos caracteres a la cadena s, en realidad le hemos asignado a s la dirección de una nueva cadena,"Hola, chau", dejando desreferenciada la cadena "Hola".

Más adelante veremos que existe un proceso llamado garbage collector, que se ocupa de liberar la memoria que vamos dejando desreferenciada.

En general, no debe preocuparnos demasiado que al concatenar cadenas se creen nuevos objetos y otros queden desreferenciados, pero sí debemos ser conscientes de esto, sobre todo si en nuestro programa haremos un uso intensivo de este tipo de situaciones. En tal caso, debemos usar la clase StringBuilder.

1.3.3.