¿Java es antiguo todavía? ¿El tipo de lenguaje de programación utilizado por los veteranos que parlotean sobre paneles frontales con luces parpadeantes y la época de los disquetes? ¿O sigue estando de moda, con las últimas mejoras de lenguaje para una codificación intuitiva y un rendimiento de primer nivel? Quizás Java esté en algún punto intermedio: un lenguaje maduro, pero joven de corazón. Hace cerca de 30 años, el 23 de mayo de 1995, Java entró oficialmente al mundo. Comenzó como una tecnología habilitante llamada “Oak” para un descodificador que Sun Microsystems imaginó que pronto colonizaría los salones estadounidenses. Ese plan no funcionó, al menos no al principio. Pero el lenguaje creció hasta convertirse en una de las bases centrales del software moderno, ejecutándose en todo, desde pequeños chips de sensores hasta grandes servidores. Desde entonces, la idea de Java ha cambiado dramáticamente. Sun y Oracle han hecho un trabajo notable al incorporar características que mantienen el lenguaje fresco sin alterar gran parte de la funcionalidad principal. Quizás Java sea sólo uno de esos lenguajes que continúa funcionando. Una cosa que sabemos con certeza es que muchas de las características que se encuentran dentro de la gran carpa llamada “Java” son diferentes de lo que se imaginó originalmente, a menudo de manera radical. Los programadores están creando código que la gente en 1995, 2005 o incluso 2015 no reconocería, pero el código antiguo aún se ejecuta. Esa es una curación de alta calidad. Oracle, la compañía que compró Sun en 2010, ahora ofrece nuevas versiones con regularidad y agrega funciones que mantienen la relevancia del lenguaje Java. Aquí hay once formas en las que Java ha cambiado, en su mayoría para mejor. Diez formas en que la programación Java es mejor que antes ser (y una de las razones por las que no lo es) Hilos virtuales Concurrencia estructurada Datos inmutables Recolección de basura Coincidencia de patrones Sintaxis optimizada Clases selladas Memoria y funciones ajenas La API vectorial Procesamiento nulo mejorado Gratis como en… ¿licencia paga? Hilos virtuales La versión original de Java brindó a los desarrolladores la oportunidad de crear sus propios objetos Thread y controlar cómo se ejecutaba el código en entornos multiproceso y multinúcleo. Si bien era mejor que nada, los programadores aprendieron rápidamente que los objetos Thread eran bastante grandes y requerían demasiado tiempo para crearlos y destruirlos. La creación de un grupo de subprocesos permanente al inicio de un programa se convirtió en una solución común para los subprocesos torpes. Todo eso cambió en Java 19, con la llegada de los hilos virtuales. Ahora, la JVM maneja gran parte del trabajo de distribuir recursos del sistema en programas Java. Los programadores especifican cuándo está disponible el paralelismo y la JVM en tiempo de ejecución ejecuta el código simultáneamente donde puede. Los subprocesos virtuales son una gran ayuda para las arquitecturas modernas como los microservicios, que son más fáciles de desarrollar y soportar. Concurrencia estructurada. Los subprocesos más livianos son solo el comienzo. Java está agregando un modelo abstracto de paralelismo que facilitará a los programadores y a la JVM procesar cargas de trabajo al mismo tiempo. El nuevo modelo de concurrencia estructurada ofrece al programador la posibilidad de dividir una carga de trabajo de Java en tareas, que luego se agrupan en ámbitos. Los ámbitos se recogen en fibras que trabajan juntas en el mismo hilo. El objetivo es ofrecer a los desarrolladores de Java un modelo estándar y repetitivo para crear programas paralelos, de modo que no necesiten razonar profundamente sobre ello cada vez. La concurrencia estructurada también facilita que la máquina virtual detecte oportunidades de ejecución simultánea y las asigne a los núcleos del procesador. Datos inmutables Al principio, las cadenas eran inamovibles. Una vez creada una cadena, nunca se podrá cambiar. Llamar a una función como toLowerCase crearía una cadena completamente nueva. Esto simplificó para la JVM la gestión de la seguridad y la sincronización entre subprocesos. Ahora, los programadores de Java pueden especificar las mismas reglas inmutables para sus propios objetos llamándolos «Registros». Esto simplifica la seguridad, el almacenamiento en caché y la sincronización de subprocesos múltiples. El código enumera los nombres y tipos de los campos y la JVM se encarga del resto. Los métodos comunes como equals, hashCode y toString se crean automáticamente. El resto del tiempo, la JVM garantiza que los registros sean inmutables, lo que simplifica muchos detalles del programa y acelera la ejecución del código. Recolección de basura Java siempre ha manejado muchos de los detalles de la asignación y recuperación de memoria, una característica que muchos programadores están felices de utilizar. delegar a la JVM. A veces, sin embargo, el recolector de basura original se detenía el tiempo suficiente para que los usuarios notaran cuando el rendimiento disminuía. Hoy en día, los programadores pueden elegir entre cuatro recolectores de basura, que utilizan una variedad de algoritmos de recolección de basura diferentes y están especializados para diferentes tipos de aplicaciones: El recolector de basura Garbage First (G1) es la opción predeterminada y ofrece un mejor rendimiento con pausas más cortas. G1 emplea técnicas que han surgido de las lecciones aprendidas de iteraciones anteriores de recolección de basura de Java, como barajar los bloques más grandes y el reconocimiento preciso de objetos pequeños que cambian con frecuencia. Z Garbage Collector está diseñado para tener una latencia muy baja, un requisito para servidores web, servicios de transmisión y otros trabajos de datos en tiempo real. También puede funcionar bien con un montón muy grande porque fue diseñado para escalar a 16 terabytes de RAM. El recolector de basura concurrente se ejecutará en segundo plano sin detener la aplicación en absoluto. Es mejor para trabajos como aplicaciones interactivas que nunca deberían pausarse, aunque puede que no sea tan eficiente. Finalmente, Parallel Collector utiliza múltiples subprocesos para recopilar datos más rápido, pero las paradas son más impredecibles. Los desarrolladores no están atrapados con un único método de recolección de basura y no tienen que recurrir a otras soluciones como simular su propia administración de memoria mediante la reutilización de objetos. Ahora hay cuatro opciones principales y cada una ofrece opciones para aún más ajustes y experimentación. Coincidencia de patrones con switchEl equipo de Java también ha mejorado el lenguaje en algunos de los niveles sintácticos más bajos, brindando a los desarrolladores más opciones para escribir una lógica más limpia y expresiva. La palabra clave switch, utilizada para crear pilas de condicionales if-then-else, ahora ofrece coincidencia de patrones, lo que significa que la lógica para especificar los distintos casos no se limita a expresiones básicas como iguales. El código Java escrito con estos patrones es especialmente conciso y es capaz de hacer distinciones no solo por el valor de los datos sino también por el tipo de objeto. Se pueden utilizar todos los tipos de referencia y el puntero nulo. Por supuesto, la lógica más tradicional con semántica fallida todavía es compatible, por lo que el código antiguo continúa ejecutándose sin problemas. Sintaxis simplificada Al principio, escribir Java no era muy diferente de escribir C o C++. Las llaves y el punto y coma hacían prácticamente lo mismo en Java que en C. Los bucles se estructuraban con la forma clásica de tres partes. Aunque sus entrañas tenían una profunda conexión con Lisp, la sintaxis básica de Java no era muy diferente de la de C. Sin embargo, las adiciones más recientes se han basado en la simplicidad de los lenguajes de programación como Ruby y Python. Los bucles For no necesitan detallar todos los detalles porque el compilador ahora puede intuirlos cuando recorre una lista o una matriz. Las funciones anónimas y las expresiones lambda también son buenas opciones para los programadores que desean ahorrar pulsaciones de teclas. Parte de la palabrería y el exceso de puntuación de C todavía están ahí, pero los programadores de Java de hoy pueden deletrear estructuras complejas con menos caracteres. Clases selladas Desde el principio, la JVM fue diseñado para evitar muchos agujeros de seguridad comunes que los programadores podrían dejar en sus programas por error. Las versiones más recientes han agregado aún más opciones. Las clases selladas, por ejemplo, permiten al creador de la clase especificar exactamente qué clases pueden ampliarla. Eso evita que otra persona que use una biblioteca extienda una clase y agregue o anule algunas de las funciones originales. Las clases selladas también se ejecutan un poco más rápido que las tradicionales porque permiten una optimización e integración más agresivas. También pueden simplificar el envío de métodos. Funciones externas y memoria La máquina virtual Java fue diseñada para ser un jardín amurallado o una caja de arena con seguridad de tipos. La máquina virtual protege el código y previene muchos ataques generales que son posibles cuando el código se ejecuta de forma nativa. Para los programadores que lo saben, la interfaz nativa de Java (JNI) original era una especie de puerta trasera. El equipo de Java sabía que algunos desarrolladores necesitaban conectarse a bibliotecas y pilas escritas en otros lenguajes, y que algunas llamadas al sistema eran esenciales. Así que abrieron este agujero en la armadura de la JVM, con una simple advertencia sobre los peligros de su uso. Ahora, tenemos la API de función y memoria externa, actualmente un JEP en tercera versión preliminar. Esta API haría que sea más fácil y seguro conectarse con el exterior. Ahora se puede escribir mucho más trabajo en Java puro, lo que abre oportunidades para que los programadores habituales de Java comiencen a conectarse a la memoria general del sistema. La propuesta también agrega mejores barreras de seguridad, como la verificación de tipos, para bloquear algunos de los peores ataques potenciales de desbordamiento. Esta API facilitaría que el código Java asuma más tareas de bajo nivel y procesamiento de datos en la codificación del sistema. Es una forma más segura para que los programadores de Java comiencen a salir del entorno limitado. La API Vector La clase Vector original, conocida por muchos programadores Java veteranos, era más una estructura de datos y menos una herramienta matemática. Era una solución flexible y sincronizada para ocultar objetos que no era muy diferente de List. La nueva API Vector es mucho más. Es una herramienta para el tipo de procesamiento de datos matemáticos que se está volviendo más común a medida que los algoritmos de inteligencia artificial utilizan matrices y vectores más o menos de la misma manera que lo hacen los físicos y los matemáticos. Los elementos individuales pueden ser tipos primitivos y se admiten muchas de las operaciones matemáticas básicas, como productos escalares. Una buena forma de ver la diferencia entre la clase Vector y la API es ver qué hace el método add. En la clase original, simplemente colocaba un objeto al final de la estructura de datos como lo hacían todas las demás clases de Colecciones. En la API, se utiliza para agregar matemáticamente los elementos individuales, más como lo esperaría un ingeniero. La API Vector también promete abrir los poderes computacionales masivos de algunos procesadores SIMD más nuevos, permitiendo a los programadores de Java crear código que pueda procesar muchos procesos largos. vectores. Mejor procesamiento nulo. ¿Ese objeto es un puntero nulo? Gran parte del código Java se dedica a verificar, verificar dos veces y luego verificar tres veces los objetos. Para simplificar el código y acelerar un poco las cosas, Java ha ido agregando lentamente funciones que manejan punteros nulos de una manera más elegante. La API Stream, por ejemplo, puede procesar largos flujos de datos y no se bloqueará si aparece un valor nulo ocasional. El contenedor de clase Opcional puede contener o no un objeto real, lo que permite que el código fluya bien. Y si aún desea verificar la nulidad, existe el operador seguro para nulos (?.) que prueba la nulidad de una manera muy concisa. ¿Gratis como en… licencia paga? Java siempre ha sido prácticamente gratuito, al menos durante programadores. Desde el principio, Sun quiso atraer a los desarrolladores con herramientas y hardware gratuitos, y en 1997 la empresa dio el paso audaz de abrir el código fuente de muchas partes del lenguaje y su máquina virtual. Hasta hace poco, los desarrolladores podían escribir más o menos una vez y ejecutar en cualquier lugar sin pagar un centavo. Ahora, el panorama se vuelve más oscuro. Muchas versiones de Java de Oracle son gratuitas, pero algunas requieren una licencia con términos extraños. Parecería que Oracle quiere que los programadores disfruten de la libertad de crear sin restricciones monetarias, pero también quiere cobrar un impuesto o una renta a las empresas que generan ingresos significativos a largo plazo con Java. En la práctica, esto significa cobrar por lo que Oracle llama funciones de suscripción de Java. Por lo tanto, Java sigue siendo gratuito, a menos que desee actualizarlo para uso comercial. Copyright © 2024 IDG Communications, Inc.

Source link