A. Introducción
En este apartado se va a comparar Java con otros lenguajes de programación orientados a objeto.
En principio Java fue diseñado tomando C y C++ como base para la creación de un nuevo lenguaje con la
modificación de todos aquellos aspectos que no eran útiles o dificultosos para la programación de componentes electrónicos
de bajo costo. Para ello el nuevo lenguaje debía incluir interfaces cómodas, debía ser fiable y fácil de desarrollar y los
programas debían ser portables de un sistema a otro sin ningún tipo de problema.
B. Comparación de los tipos de
datos
a.) Tipos de datos simples (primitivos)
Java es muy parecido a C++ en el juego básico de tipos de datos con algunas pequeñas modificaciones.
En Java se distingue entre tipos de datos primitivos y clases, aunque existen unas clases especiales
(envoltorios o wrappers) que permiten modificar los tipos de datos primitivos.
Los tipos de datos primitivos (o simples) pueden ser numéricos, booleanos o caracteres.
b.) Datos numéricos
Hay cuatro tipos numéricos: byte de 1 byte, short de 2 bytes, int de 4 bytes,
y los long de 8 bytes. El tipo más habitual de los cuatro es el tipo int. El byte viene a sustituir el
tipo char de C++, ya que Java introduce una interpretación diferente al tipo de datos char.
Las principales diferencias con C++ son:
- No existe un tipo sin signo (unsigned) para
los números en Java.
- Los tipos numéricos reales son el float (8
bytes) y el double (16 bytes).
- Los números que utilizan coma flotante (por ejemplo
18.96) son considerados double por defecto, y habrá que realiza un moldeado (casting) explícito para que sean
float.
c.) Caracteres
Los datos carácter en Java se basan en los de C++ que a su vez son heredados de C. Los caracteres son
Unicode de 2 bytes. Los caracteres Unicode son valores de 2 bytes sin signo, con lo que se define obtiene un
rango de 65535 caracteres diferentes, que son suficientes para las los diferentes lenguajes y sistemas de representación del
planeta.
El carácter de datos del lenguaje Java proviene del tradicional C. Hay que señalar que los caracteres
en C++ eran de sólo 1 byte, con lo que en Java podremos representar muchos más caracteres que en C++.
d.) Datos booleanos
En Java se definen para las variables con valores Verdadero/Falso o Sí/No, en definitiva, valores bi-estado.
Una variable booleana puede tener los valores true (verdadero) o false (falso). Son parecidos a los de C++,
aunque en cualquier caso, y a diferencia de C++ estas variables no pueden ser convertidas a datos numéricos, y es un tipo
de datos básico.
C. Operadores relacionales y aritméticos.
Se permite en Java los mismos operadores que C++, con la variación de >>> (desplazamiento
sin signo) y la utilización del operador + para la concatenación de cadenas de caracteres.
D. Vectores
Los vectores en Java, a diferencia de C++, son una clase de objetos. Un vector es un objeto real con
una representación en tiempo real. Se pueden declarar y almacenar vectores de cualquier tipo, y almacenar también vectores
de vectores para obtener matrices (vectores con varias dimensiones). En este último aspecto no existe diferencia con C++.
E. Cadenas
Las cadenas en Java son objetos del lenguaje, no existen seudo-arrays de caracteres (cadenas) como era
el caso de C++. Existen dos tipos de cadenas de objetos:
Las que se obtienen de la clase String, para cadenas de sólo lectura.
Las que se obtienen de la clase StringBuffer para cadenas que se pueden modificar.
Al igual que C++, el compilador de Java entiende que una cadena de caracteres rodeada de dobles comillas
es una cadena, y es iniciada como un objeto de tipo String (en C++ sería como vector de caracteres con el carácter
fin de cadena ‘\0’ al final de la misma).
F. Otras características
a.) Introducción
En este apartado se va a comparar Java con los lenguajes C++ y Smalltalk (primer lenguaje que presentaba
un modelo de objeto).
Característica |
Java |
Smalltalk |
C++ |
Sencillez |
Sí |
Sí |
No |
Robustez |
Sí |
Sí |
No |
Seguridad |
Sí |
Algo |
No |
Interpretado |
Sí |
Sí |
No |
Dinamicidad |
Sí |
Sí |
No |
Portabilidad |
Sí |
Algo |
No |
Neutralidad |
Sí |
Algo |
No |
Threads |
Sí |
No |
No |
Garbage Colection |
Sí |
Sí |
No |
Excepciones |
Sí |
Sí |
Algunas |
Representación |
Alta |
Media |
Alta |
Tabla 1: Comparación entre Java,
SmallTalk y C++
b.) Sencillez
Java tiene una sencillez que no posee C++ aunque sí Smalltalk. Esto es debido a que una de las razones
de la creación de Java es la de obtener un lenguaje parecido a C++ pero reduciendo los errores más comunes de la programación,
algo que se logra con mucho éxito puesto que Java reduce un 50% los errores que se comenten en C++ entre los que destacan:
- Eliminación de la aritmética de punteros y de las
referencias.
- Desaparecen los registros (struct), heredados
del paradigma estructurado.
- No se permite ni la definición de tipos (typedef)
ni la de macros (#define).
- Ya no es necesario liberar memoria (free o delete).
De todas formas, lo que Java hace, en realidad, es la eliminación de palabras reservadas, y la utilización
de un intérprete bastante pequeño.
c.) Robustez
Java realiza verificaciones en busca de problemas tanto en tiempo de compilación como en tiempo de ejecución,
lo que hace que se detecten errores lo antes posible, normalmente en el ciclo de desarrollo. Algunas de estas verificaciones
que hacen que Java sea un lenguaje robusto son:
- Verificación del código de byte.
- Gestión de excepciones y errores.
- Comprobación de punteros y de límites de vectores.
Se aprecia una clara diferencia con C++ quién no realiza ninguna de estas verificaciones.
d.) Seguridad
En Java no se permite los accesos ilegales a memoria, algo que sí se permitía en C++. Esto es algo muy
importante puesto que este tipo de problema puede ocasionar la propagación de virus y otras clases de programas dañinos por
la red.
El código Java pasa muchos tests antes de ejecutarse en una máquina. El código se pasa a través de un
verificador de código de byte que comprueba el formato de los fragmentos de código y aplica un probador de teoremas
para detectar fragmentos de código ilegal, código que falsea punteros, viola derechos de acceso sobre objetos o intenta cambiar
el tipo o clase de un objeto.
Algunos de los conocimientos que podemos obtener de los códigos de byte si pasan la verificación sin
generar ningún mensaje de error son:
- El código no produce desbordamiento de operandos
en la pila.
- El tipo de los parámetros de todos los códigos de
operación es conocido y correcto.
- No ha ocurrido ninguna conversión ilegal de datos,
tal como convertir enteros en punteros.
- El acceso a los campos de un objeto se sabe si es
legal mediante las palabras reservadas public, private y protected.
- No hay ningún intento de violar las reglas de acceso
y seguridad establecidas.
Por todo esto, y por no permitirlo mediante Java la utilización de métodos de un programa sin los privilegios
del núcleo (kernel) del sistema operativo, la obligación de autentificación por clave pública para la realización de
modificaciones, se considera Java un lenguaje seguro. Todo esto no lo incorporan ni C++ ni Smalltalk, por lo que Java es el
único de los tres considerable como seguro.
e.) Lenguaje interpretado
Java es un lenguaje que puede ejecutar el código directamente, es decir es un "lenguaje interpretado".
Esto es una característica que sí que posee Smalltalk, aunque no C++. No obstante, y aunque en teoría se consumen menos recursos
siendo los lenguajes interpretados, el actual compilador que existe es bastante lento, unas 20 veces menos rápido que C++.
Esto normalmente no es vital para la aplicación ni demasiado apreciable por el usuario, y además esta diferencia se está reduciendo
con los nuevos compiladores JIT (Just In Time).
f.) Dinamicidad
Para la obtención de un mayor provecho de la tecnología orientada a objetos, Java no intenta conectar
todos los módulos que comprenden una aplicación hasta el tiempo de ejecución. Esta característica ya es contemplada por Smalltalk,
aunque no C++, que enlaza todos los módulos cuando se compila.
g.) Portabilidad
Un programa Java puede ser ejecutado en diferentes entornos, algo imposible para C++.
h.) Neutralidad
Se dice que Java tiene una arquitectura neutra puesto que compila su código a un fichero objeto de formato
independiente de la arquitectura de la máquina en que se ejecutará.
Cualquier máquina que tenga el sistema de ejecución (JRE o Java Runtime Enviroment) puede
ejecutar ese código objeto, sin importar en modo alguno la máquina en que ha sido generado.
Actualmente existen sistemas de ejecución (JRE) para Solaris 2.x, SunOs 4.1.x, Windows 95, Windows
NT, Linux, Irix, Aix, Mac, Apple y probablemente haya grupos de desarrollo trabajando el portado a otras plataformas.
No es así para C++ y para Smalltalk, donde el código generado podrá ejecutarse únicamente en la plataforma
en la que se generó.
i.) Threads
Java permite múltiples hilos (multithreading) antes de su ejecución y en tiempo de ejecución.
La posibilidad de construir pequeños procesos o piezas independientes de un gran proceso permite programar de una forma más
sencilla y es una herramienta muy potente que no se ofrece en C++.
j.) Recolección automática de
basura (Garbage colection)
Java modifica completamente la gestión de la memoria que se hace en C/C++. En C/C++ se utilizan punteros,
reservas de memoria (con las ordenes malloc, new, free, delete...) y otra serie de elementos que
dan lugar a graves errores en tiempo de ejecución difícilmente depurables.
Java tiene operadores nuevos para reservar memoria para los objetos, pero no existe ninguna función explícita
para liberarla.
La recolección de basura (objetos ya inservibles) es una parte integral de Java durante la ejecución
de sus programas. Una vez que se ha almacenado un objeto en el tiempo de ejecución, el sistema hace un seguimiento del estado
del objeto, y en el momento en que se detecta que no se va a volver a utilizar ese objeto, el sistema vacía ese espacio de
memoria para un uso futuro.
Esta gestión de la memoria dinámica hace que la programación en Java sea más fácil.
k.) Representación
Uno de los objetivos perseguidos en el desarrollo de Java era la obtención de programas con interfaces
cómodas e intuitivas. Esto también se permite en C++, aunque con unos métodos más costosos, y en ningún caso con interfaces
portables como los que Java crea.
Tanto en Java como en C++ se logran unas interfaces con una representación mejor que la que se puede
alcanzar con Smalltalk.
La principal diferencia entre Java
y los demás lenguajes de programación por objetos es que con estos últimos es posible programar por objetos, mientras que
con Java se tiene absolutamente que programar por objetos. En concreto la programación se desarrolla de la misma forma que
los lenguajes "normales", pero tanto los datos como las funciones que los trabajan se organizan en estructuras llamadas clases.
Diferencia
entre estos dos lenguajes (Javascript y Java) con un origen común.
Queremos
que quede claro que Javascript no tiene nada que ver con Java, salvo en sus orígenes, como se ha podido leer hace unas líneas.
Actualmente son productos totalmente distintos y no guardan entre si más relación que la sintaxis idéntica y poco más. Algunas
diferencias entre estos dos lenguajes son las siguientes:
- Compilador. Para programar en Java necesitamos un Kit de desarrollo y un compilador.
Sin embargo, Javascript no es un lenguaje que necesite que sus programas se compilen, sino que éstos se interpretan por parte
del navegador cuando éste lee la página.
- Orientado a objetos. Java es un lenguaje de programación orientado a objetos. (Más tarde
veremos que quiere decir orientado a objetos, para el que no lo sepa todavía) Javascript no es orientado a objetos, esto quiere
decir que podremos programar sin necesidad de crear clases, tal como se realiza en los lenguajes de programación estructurada
como C o Pascal.
- Propósito. Java es mucho más potente que Javascript, esto es debido a que Java es un
lenguaje de propósito general, con el que se pueden hacer aplicaciones de lo más variado, sin embargo, con Javascript sólo
podemos escribir programas para que se ejecuten en páginas web.
- Estructuras fuertes. Java es un lenguaje de programación fuertemente tipado, esto quiere
decir que al declarar una variable tendremos que indicar su tipo y no podrá cambiar de un tipo a otro automáticamente. Por
su parte Javascript no tiene esta característica, y podemos meter en una variable la información que deseemos, independientemente
del tipo de ésta. Además, podremos cambiar el tipo de información de una varible cuando queramos.
- Otras características. Como vemos
Java es mucho más complejo, aunque también más potente, robusto y seguro. Tiene más funcionalidades que Javascript y las diferencias
que los separan son lo suficientemente importantes como para distinguirlos fácilmente.
__________________________________________________________________________________________
INFORMACION DEL LIBRO
Este apéndice contiene una descripción
de la mayoría de las diferencias principales entre C, C++ y el lenguaje Java. Si usted es un programador familiarizado con
C o C++, tal vez desee revisar este apéndice para darse cuenta de algunos de los errores comunes y suposiciones que los programas
realizan cuando usan Java.
Apuntadores
Java no cuenta con un tipo de apuntador
explícito. En lugar de apuntadores, todas las referencias a objetos (incluso asignación de variables, argumentos pasados a
métodos y elementos de arreglos) se logran con el uso de regencias implícitas. Las referencias son en esencia lo mismo, a
excepción de que no puede realizar aritmética de apuntadores en referencia (aunque, de hecho, no lo necesita).
Las referencias permiten crear con
facilidad estructuras como listas enlazadas en Java sin apuntadores explícitos; sólo cree un nodo de lista con variables que
apunten al siguiente y al anterior nodo. Después, para insertar elementos en lista, asigne esas variables a otros objetos
tipo nodo.
Arreglos
Los arreglos en Java son objetos
de primera clase, y las referencias a arreglos y su contenido se logran mediante referencias implícitas en lugar de aritmética
de puntos. Los límites del arreglo son forzados en forma escrita; intentar leer más allá del final de un arreglo es un error
en compilación o a tiempo de ejecución. Al igual que con otros objetos, al pasar un arreglo a un método se envía una referencia
al arreglo original, así que cambiar el contenido de esa referencia de arreglo cambia el objeto de arreglo original.
Los arreglos de objetos son arreglos
de referencias que no se inicializan en forma automática para contener objetos reales. Usar el siguiente código Java produce
un arreglo de tipo MYObject con diez elementos, aunque ese arreglo en un inicio contenía sólo valores nulos:
MYObject arroyofobjs [ ] = new MYObject [ 10 ] ;
Ahora debe agregar objetos MYObject
reales a ese arreglo:
For (int i=0; i< arroyofobjs.length(i++) {
arroyofobjs [ i ] = new MYObject
( );
Java no respalda los arreglos multidimencionales
como la base C y C++. En Java, debe crear arreglos que contengan otros arreglos.
Cadenas
Las cadenas en C y C++ son arreglos
de caracteres terminados con un carácter nulo (`/10`). Para operara y manejar cadenas, tratelas como lo haría con cualquier
otro arreglo con las dificultades inherentes de rastrear la aritmética de apuntador y con el cuidado de no perder el fin del
arreglo.
Las cadenas en Java son objetos;
todos los métodos que operan en las cadenas tratan a la cadena como una entidad completa. Las cadenas no se terminan con un
valor nulo, tampoco puede sobrepasar en forma el final de una cadena (como los arreglos y los límites de cadenas forzados
de manera escrita).
Administración de la memoria
La administración de la memoria
en Java es automática; la memoria se asigna de forma automática al crear un objeto y un recolector de basura a tiempo de ejecución
(el “ge”) libera esa memoria cuando ese objeto ya no se usa. Las funciones de C malloc ( ) y free ( ) no existen
en Java.
Para “forzar” la liberación
de un objeto, elimine todas las referencias de este (asigne todas las variables y elementos del arreglo que lo contienen a
nulo). La siguiente vez que se ejecute ge, ese objeto será requerido.
Tipos de datos
Como se mencionó en la primera parte
de este libro, los tipos de datos primitivos de Java (char, int, long, entre otros) cuentan con tamaños y comportamiento que
consiste en varias plataformas y sistemas operativos. No existen tipos de datos sin signo como en C y C++ (a excepción de
char, que es un entero sin identificación de 16 bits).
El tipo de dato primitivo boolean
tiene dos valores: true y false. El tipo booleano no es un entero, tampoco debe tratarlo como si lo fuera, aunque puede forzar
0 o 1 (enteros) a tipo booleanos en Java.
Los tipos de datos compuestos se
logran en Java de manera exclusiva mediante el uso de definiciones de clase. Las palabras clave struct, union y typedef se
han suprimido a favor de las clases.
El forzado entre tipos de datos
esta mas controlado en Java; el forzado automático ocurre solo cuando no existe pérdida de información. Los demás forzados
deberán ser explícitos. Los tipos primitivos (int, flota, long. Char, boolean, entre otros) no podrán forzarse objetos o viceversa;
existen métodos y clases “envolventes” especiales para convertir valores entre enteros y tipo primitivos.
Operadores
El orden de ejecución de los operadores
y su asociación se comporta igual que en C. Advierta sin embargo que la palabra clave new (para crear un objeto nuevo) se
alza de forma mas estrecha que la notación de punto (.), la cual tiene un comportamiento distinto en C++.
La sobrecarga de operadores al igual
que en C++, no se puede realizar en Java; el operador de C se ha eliminado.
El operador >>> produce
un desplazamiento lógico a la derecha sin signo (recuerde, no existen tipos de
datos enteros sin signo).
El operador + se utiliza para encadenar
cadenas.
Flujo de control
Aunque los enunciados if, while,
for y do en Java son iguales en cuanto a la sintaxis, en contraposición con C y C++, existe un diferencia significativa. La
expresión de prueba para cada construcción de flujo de control debe regresar un valor booleano (true o false). En C y C++,
la expresión puede regresar un entero.
Argumentos
Java no acepta mecanismos para listas
de argumentos de longitud variable para funciones como en C y C++. Todas las definiciones de métodos deben tener un número
específico de argumentos.
Los argumentos de la línea de comando
en Java se comportan de modo diferente de los de C y C++. El primer elemento en el vector de argumentos (argv [0] ) en C y
C++ es el nombre del programa mismo; en Java, ese argumento inicial es el primero de los adicionales. En otras palabras, en
Java, argv [0] es argv [1] en C y C++; no hay manera de sujetar el nombre real
del programa Java.
Otras diferencias
Existen las siguientes diferencias
menores de C y C++ con Java:
Java no cuenta con un procesador
y por ello, no ostenta # defines o macros. Las constantes pueden crearse mediante el modificador final al declarar variables
de clase y de instancia.
Java no cuenta con una clase de
plantillas como el C++.
Java no incluye la palabra clave
de C const o la capacidad de pasar por la referencia const en forma explícita.
Las clases Java son de herencia
sencilla, son algunas características de herencia múltiple provistas por medio de interfaces.
Todas las funciones deben ser métodos.
No existen funciones que no estén enlazados a clases.
La palabra clave goto no existe
en Java, en una palabra reservada pero en la actualidad no esta implementada). Usted puede utilizar breake y continues orientadas
para salirse y continuar la ejecución de complejas conmutaciones o construcciones de ciclo.