Tema 19.docx
Document Details
Uploaded by Oganesson93
Universidad de Valladolid
Tags
Full Transcript
***Tema 19. JAVA: fundamentos del lenguaje Java. Objetos y clases. Threads y programación multihilo. Tratamiento de excepciones. Estándares de conectividad. ODBC y JDBC.*** Java es un lenguaje de programación de alto nivel y orientado a objetos que se utiliza para crear aplicaciones y programas en...
***Tema 19. JAVA: fundamentos del lenguaje Java. Objetos y clases. Threads y programación multihilo. Tratamiento de excepciones. Estándares de conectividad. ODBC y JDBC.*** Java es un lenguaje de programación de alto nivel y orientado a objetos que se utiliza para crear aplicaciones y programas en una variedad de plataformas, incluyendo Windows, Mac OS y Linux. Fue desarrollado por Sun Microsystems en la década de 1990 y ahora es propiedad de Oracle Corporation. Java se ha convertido en uno de los lenguajes de programación más populares en todo el mundo, y se utiliza en una variedad de campos, incluyendo la programación de aplicaciones móviles, la programación web y la programación de sistemas de alta tecnología. Algunas de las características más destacadas de Java incluyen: - Portabilidad: Una de las principales ventajas de Java es su capacidad para ser ejecutado en cualquier plataforma que tenga una máquina virtual Java (JVM) instalada. Esto significa que un programa Java escrito en un sistema operativo puede ser ejecutado en otro sistema operativo sin necesidad de modificar el código. - Orientación a objetos: Java es un lenguaje de programación orientado a objetos, lo que significa que se basa en la creación de clases y objetos. Esto permite una programación modular, reutilización de código y mayor eficiencia en el desarrollo de aplicaciones. - Gestión automática de memoria: Java utiliza un sistema de limpieza para liberar la memoria utilizada por objetos que ya no son necesarios en el programa. - Seguridad: Java fue diseñado con la seguridad en mente y proporciona una amplia gama de características de seguridad para proteger contra posibles ataques de malware y virus. - Biblioteca de clases: Java viene con una amplia biblioteca de clases que facilita el desarrollo de aplicaciones. La biblioteca incluye clases para la entrada y salida de datos, manipulación de archivos, conectividad de redes, programación de gráficos y mucho más. - Multi-hilo: Java soporta la programación multi-hilo, lo que permite la ejecución simultánea de varias partes de un programa, lo que puede mejorar el rendimiento y la eficiencia de las aplicaciones. En Java, **los objetos y las clases** son elementos clave en la programación orientada a objetos. Una clase es un modelo o plantilla que define un conjunto de propiedades y métodos comunes que comparten todos los objetos creados a partir de ella. Un objeto es una instancia de una clase. Cada vez que se crea un objeto en Java, se reserva memoria para almacenar sus propiedades y métodos, lo que le permite interactuar con el programa. \[modificadores\] class NombreDeLaClase \[extends OtraClase \|implements Interface\] { } Por ejemplo, si se crea un objeto de la clase \"Rectangulo\", se pueden establecer sus propiedades como base y altura, y luego invocar sus métodos como CalcularArea y CalcularPerimetro. Para crear una clase en Java, se utiliza la palabra clave \"class\" seguida del nombre de la clase. Por ejemplo, la siguiente línea de código crea una clase \"Rectangulo\": *class Rectangulo {* *int base;* *int altura;* *int calcularArea() {* *return base \* altura;* *}* *int calcularPerimetro() {* *return 2 \* base + 2 \* altura;* *}* *}* Dentro de la clase se definen sus propiedades y métodos. Las propiedades son variables que almacenan valores, mientras que los métodos son bloques de código que realizan acciones. Para crear un objeto de la clase \"Rectangulo\", se utiliza la palabra clave \"new\" seguida del nombre de la clase, seguida de paréntesis. Por ejemplo, la siguiente línea de código crea un objeto \"rec\" de la clase \"Rectangulo\": Rectangulo rec = new Rectangulo(); Una vez que se ha creado un objeto, se pueden establecer sus propiedades (darán un estado al objeto) y llamar a sus métodos. Por ejemplo, para establecer la propiedad \"marca\" del objeto \"coche1\" y llamar al método \"encender\", se pueden utilizar las siguientes líneas de código: Existe en toda aplicación java existe una clase principal donde se ejecuta el método especial "main". Esta clase no se puede instanciar y este método será el primero en ser ejecutado. La estructura básica de todo programa Java será: *public class Principal {* *public static void main (String\[\] args){* *// Bloque de sentencias* *}* *}* Java es un lenguaje de programación que soporta la **programación multihilo**, lo que significa que los programas pueden ejecutar múltiples procesos simultáneamente. Un hilo (también conocido como thread) es un subproceso que se ejecuta dentro de un programa y que tiene su propio flujo de control. La programación multihilo en Java permite que los programas realicen tareas simultáneas, lo que puede mejorar significativamente el rendimiento y la eficiencia. Los hilos pueden utilizarse para realizar tareas en segundo plano, mantener una interfaz de usuario sensible al usuario mientras se realizan operaciones de larga duración, y para realizar múltiples tareas simultáneamente. En Java, los hilos se pueden crear utilizando la clase \"Thread\" o implementando la interfaz \"Runnable\". [Clase Thread] La forma más directa para hacer un programa multihilo es extender la clase Thread, y redefinir el método run(). Este método es invocado cuando se inicia el hilo (mediante una llamada al método start() de la clase Thread). El hilo se inicia con la llamada al método run() y termina cuando termina éste. La clase \"Thread\" proporciona métodos que permiten controlar el comportamiento del hilo, como iniciar, detener y pausar. Por ejemplo, el siguiente código crea un hilo utilizando la clase \"Thread\" y lo inicia: *public class Hilo extends Thread {* *public void run() {* *System.out.println(\"Este es un hilo\");* *}* *}* *public class Main {* *public static void main(String\[\] args) {* *Hilo hilo1 = new Hilo();* *hilo1.start();* *}* *}* En este ejemplo, se crea una clase llamada \"Hilo\" que extiende la clase \"Thread\" y proporciona una implementación del método \"run()\". En el método \"main()\" se crea una instancia del hilo y se llama al método \"start()\", lo que inicia la ejecución del hilo. [Ciclo de vida del Thread] Diagrama Descripción generada automáticamente Cuando se instancia la clase Thread (o una subclase) se crea un nuevo Thread que está en su estado inicial (\'New Thread\' en el gráfico). En este estado es simplemente un objeto más. No existe todavía el thread en ejecución. El único método que puede invocarse sobre él es el método start(). Cuando se invoca el método start() sobre el hilo el sistema crea los recursos necesarios, lo planifica (le asigna prioridad) y llama al método run(). En este momento el hilo está corriendo, se encuentra en el estado 'runable'. Si el método run() invoca internamente el método sleep() o wait() o el hilo tiene que esperar por una operación de entrada/salida, entonces el hilo pasa al estado \'no runnable\' (no ejecutable) hasta que la condición de espera finalice. Durante este tiempo el sistema puede ceder control a otros hilos activos. Por último, cuando el método run finaliza el hilo termina y pasa a la situación \'Dead\' (Muerto). Aunque un programa utilice varios hilos y aparentemente estos se ejecuten simultáneamente, el sistema ejecuta una única instrucción cada vez (esto es particularmente cierto en sistemas con una sola CPU), aunque las instrucciones se ejecutan concurrentemente (entremezclándose sus éstas). El mecanismo por el cual un sistema controla la ejecución concurrente de procesos se llama planificación (scheduling). Java soporta un mecanismo simple denominado planificación por prioridad fija (fixed priority scheduling). Esto significa que la planificación de los hilos se realiza en base a la prioridad relativa de un hilo frente a las prioridades de otros. [Interfaz Runnable] La interface Runnable proporciona un método alternativo a la utilización de la clase Thread, para los casos en los que no es posible hacer que la clase definida extienda la clase Thread. Esto ocurre cuando dicha clase, que se desea ejecutar en un hilo independiente deba extender alguna otra clase. Dado que no existe herencia múltiple, la citada clase no puede extender a la vez la clase Thread y otra más. En este caso, la clase debe implantar la interface Runnable, variando ligeramente la forma en que se crean e inician los nuevos hilos. En este caso, se define una clase que implementa la interfaz \"Runnable\" y proporciona una implementación del método \"run()\". El siguiente código muestra un ejemplo: *public class Hilo implements Runnable {* *public void run() {* *System.out.println(\"Este es un hilo\");* *}* *}* *public class Main {* *public static void main(String\[\] args) {* *Hilo hilo1 = new Hilo();* *Thread hilo2 = new Thread(hilo1);* *hilo2.start();* *}* *}* En este ejemplo, se crea una clase llamada \"Hilo\" que implementa la interfaz \"Runnable\" y proporciona una implementación del método \"run()\". En el método \"main()\", se crea una instancia del hilo y se pasa a la clase \"Thread\" para crear un nuevo hilo. Luego, se llama al método \"start()\" para iniciar la ejecución del hilo. El **tratamiento de excepciones** en Java es un mecanismo que permite manejar errores en tiempo de ejecución para evitar que el programa se detenga abruptamente. En lugar de ello, el programa puede manejar la excepción y tomar acciones adecuadas para recuperarse del error. En Java, las excepciones se representan mediante objetos que pertenecen a una clase que extiende la clase \"Throwable\". ![Diagrama Descripción generada automáticamente](media/image2.png) Existen dos tipos de excepciones en Java: - Excepciones verificadas: Las excepciones verificadas son aquellas que son obligatorias manejarlas porque si no, no nos deja compilar. Son todas las que son lanzadas explícitamente por objetos de usuario. Son condiciones excepcionales en el flujo de nuestro programa pero que no son debido a un error del propio programa, generalmente son por problemas de red, problemas con la conexión a las bases de datos. - Excepciones no verificadas: son aquellas donde se deja al programador la decisión de capturarlas o no. Son aquellas que se lanzan cuando hay un error en el programa y poco podemos hacer por arreglarlas. Son todas las clases que derivan de Error (errores graves que la aplicación no puede solucionar, como puede ser falta de memoria, error interno de la JVM,..) y RuntimeException: arithmetic exception, null pointer exception,... El tratamiento de excepciones en Java se realiza mediante el uso de bloques try-catch. Un bloque try-catch se utiliza para rodear el código que puede generar una excepción. Si se produce una excepción dentro del bloque try, se captura por el bloque catch correspondiente y se maneja adecuadamente. Por ejemplo, el siguiente código muestra cómo manejar una excepción de división por cero: *public class Main {* *public static void main(String\[\] args) {* *int num1 = 10;* *int num2 = 0;* *try {* *int resultado = num1 / num2;* *System.out.println(resultado);* *} catch (ArithmeticException e) {* *System.out.println(\"Error: división por cero\");* *}* *}* *}* En este ejemplo, se intenta dividir el número 10 entre cero, lo que generará una excepción de tipo ArithmeticException. El bloque try-catch se utiliza para capturar la excepción y mostrar un mensaje de error adecuado. También es posible utilizar el bloque finally después del bloque catch para ejecutar un código que siempre debe ser ejecutado, independientemente de si se produce una excepción o no. *public class Main {* *public static void main(String\[\] args) {* *try {* *// código que puede generar una excepción* *} catch (Exception e) {* *// manejo de la excepción* *} finally {* *// código que siempre se ejecutará* *}* *}* *}* **Estándares de conectividad: ODBC y JDBC**. En Java, hay varios estándares de conectividad que se utilizan para conectarse a bases de datos y otros sistemas. [ODBC] Es un estándar de acceso a las bases de datos con el objetivo de poder acceder a cualquier dato desde cualquier aplicación, sin importar qué sistema de gestión de bases de datos almacene los datos. Es una especificación creada por Microsoft. [JDBC] Java Database Connectivity (JDBC) es una interfaz de acceso a bases de datos estándar SQL que proporciona un acceso uniforme a una gran variedad de bases de datos relacionales desde el lenguaje de programación Java. Para usar JDBC con un sistema gestor de base de datos en particular, es necesario disponer del driver JDBC apropiado que haga de intermediario entre ésta y JDBC. Dependiendo de varios factores existen varios tipos de drivers. Acceso de JDBC a Bases de Datos [[https://docplayer.es/1953429-Que-es-jdbc-cuatro-tipos-de-drivers-jdbc-uso-de-jdbc.html]](https://docplayer.es/1953429-Que-es-jdbc-cuatro-tipos-de-drivers-jdbc-uso-de-jdbc.html) Existen 4 tipos de drivers JDBC: - Driver JDBC Tipo 1 (también llamado Puente JDBC-ODBC) convierte el método JDBC a una llamada a una función ODBC. Utiliza los drivers ODBC para conectar con la base de datos. Todo se encuentra en el cliente, menos la Base de datos. Los drivers ODBC son dependientes del SO de la máquina cliente. Imagen que contiene Gráfico Descripción generada automáticamente - Driver JDBC Tipo 2 (también llamado driver API-Nativo) convierte el método JDBC a llamadas nativas de la API de la base de datos. Está escrito en Java y en código nativo. Es más rápido que el puente JDBC-ODBC pero se necesita instalar la librería cliente de la base de datos en la máquina cliente y el driver es dependiente de la plataforma. ![Diagrama Descripción generada automáticamente](media/image4.png) - Driver JDBC Tipo 3. Hace uso de un Middleware entre el JDBC y el SGBD. Esta es la opción más flexible, se trata de un driver 100% Java / Protocolo independiente, que requiere la presencia de un intermediario en el servidor. En este caso, el driver JDBC hace las peticiones de datos al intermediario en un protocolo de red independiente del servidor DBMS. El intermediario a su vez, que está ubicado en el lado del servidor, convierte las peticiones JDBC en peticiones nativas del sistema DBMS. La ventaja de este método es inmediata: el programa que se ejecuta en el cliente, y aparte de las ventajas de los drivers 100% Java, también presenta la independencia respecto al sistema de bases de datos que se encuentra en el servidor. Diagrama Descripción generada automáticamente - Driver JDBC Tipo 4 (también llamado Driver Java Puro directo a la base de datos). Es un driver realizado completamente en Java (cada Base de datos debe proporcionar su driver JDBC) que se comunica con el servidor DBMS utilizando el protocolo de red nativo del servidor. De esta forma, el driver no necesita intermediarios para hablar con el servidor y convierte todas las peticiones JDBC en peticiones de red contra el servidor. La ventaja de este tipo de driver es que es una solución 100% Java y, por lo tanto, independiente de la máquina en la que se va a ejecutar el programa. ![Diagrama Descripción generada automáticamente con confianza media](media/image6.png) Se desaconseja el uso de los drivers tipo 1 y tipo 2 al ser dependientes del S.O. de la máquina cliente y por tanto las aplicaciones no serán portables. Se utilizará el tipo 3 si desde la misma aplicación se debe conectar con varias bases de datos. Pero si solo nos vamos a conectar con una base de datos lo recomendable es utilizar el tipo 4 siempre y cuando exista por parte del fabricante de base de datos el driver correspondiente para JDBC. Los ejemplos que hemos visto son para arquitecturas de dos capas (Cliente/Servidor) pero se puede utilizar una arquitectura a tres capas donde se introduce una capa intermedia entre cliente y servidor de Base de Datos donde se situará el controlador JDBC. Todas las aplicaciones con JDBC deben realizar las mismas operaciones: 1. Cargar el driver JDBC 2. Especificación del nombre y ubicación de la Base de datos. 3. Se conectan a la base de datos utilizando un objeto Connection. 4. Se crean objetos Statement y se ejecutan queries SQL 5. Los resultados de un query se guardan en un objeto ResultSet, desde donde se pueden consultar 6. Cerrar los objetos ResultSet, Statement y Connection.