Buscar este blog

8 de febrero de 2010

Bibliografia



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.
Java es un lenguaje orientado a objetos, que se deriva en alto grado de C++, de tal forma que puede ser considerado como un C++ nuevo y modernizado o bien como un C++ al que se le han amputado elementos heredados del lenguaje estructurado C.
B. Tokens
Un token es el elemento más pequeño de un programa que es significativo para el compilador. Estos tokens definen la estructura de Java.
Cuando se compila un programa Java, el compilador analiza el texto, reconoce y elimina los espacios en blanco y comentarios y extrae tokens individuales. Lostokens resultantes se compilan, traduciéndolos a código de byte Java, que es independiente del sistema e interpretable dentro de un entorno Java.
Los códigos de byte se ajustan al sistema de máquina virtual Java, que abstrae las diferencias entre procesadores a un procesador virtual único.
Los tokens Java pueden subdividirse en cinco categorías: Identificadores, palabras clave, constantes, operadores y separadores.
a.) Identificadores
Los identificadores son tokens que representan nombres asignables a variables, métodos y clases para identificarlos de forma única ante el compilador y darles nombres con sentido para el programador.
Todos los identificadores de Java diferencian entre mayúsculas y minúsculas (Java es Case Sensitive o Sensible a mayúsculas) y deben comenzar con una letra, un subrayado(_) o símbolo de dólar($). Los caracteres posteriores del identificador pueden incluir las cifras del 0 al 9. Como nombres de identificadores no se pueden usar palabras claves de Java.
Además de las restricciones mencionadas existen propuestas de estilo. Es una práctica estándar de Java denominar:
  • Las clases: Clase o MiClase.
  • Las interfaces: Interfaz o MiInterfaz.
  • Los métodos: metodo() o metodoLargo().
  • Las variables: altura o alturaMedia.
  • Las constantes: CONSTATE o CONSTANTE_LARGA.
  • Los paquetes: java.paquete.subpaquete.
Sin entrar en más detalle en la siguiente línea de código se puede apreciar la declaración de una variable entera (int) con su correspondiente identificador:
int alturaMedia;
b.) Palabras clave
Las palabras claves son aquellos identificadores reservados por Java para un objetivo determinado y se usan sólo de la forma limitada y específica. Java tiene un conjunto de palabras clave más rico que C o que C++, por lo que sí está aprendiendo Java con conocimientos de C o C++, asegúrese de que presta atención a las palabras clave de Java.
Las siguientes palabras son palabras reservadas de Java:
abstact
boolean
break
byte
byvalue
case
cast
catch
char
class
const
continue
default
do
double
else
extends
false
final
finally
float
for
future
generic
goto
if
implements
import
inner
instanceof
int
interface
long
native
new
null
operator
outer
package
private
protected
public
rest
return
short
static
super
switch
syncroniced
this
throw
throws
transient
true
try
var
void
volatile
while

Tabla 2: Palabras reservadas Java
Las palabras subrayadas son palabras reservadas pero no se utilizan. La definición de estas palabras clave no se ha revelado, ni se tiene un calendario respecto a cuándo estará alguna de ellas en la especificación o en alguna de las implementaciones de Java.

c.) Literales y constantes
Los literales son sintaxis para asignar valores a las variables. Cada variables es de un tipo de datos concreto, y dichos tipos de datos tienen sus propios literales.
Mediante determinados modificadores (static y final) podremos crear variables constantes, que no modifican su valor durante la ejecución de un programa. Las constantes pueden ser numéricas, booleanas, caracteres (Unicode) o cadenas (String).
Las cadenas, que contienen múltiples caracteres, aún se consideran constantes, aunque están implementadas en Java como objetos.
Veamos un ejemplo de constante declarada por el usuario:
final static int ALTURA_MAXIMA = 200;
Se puede observar que utilizamos final static, para que la variable sea total y absolutamente invariable.
d.) Operadores
Conocidos también como operandos, indican una evaluación o computación para ser realizada en objetos o datos, y en definitiva sobre identificadores o constantes. Los operadores admitidos por Java son:
+
^
<=
++
%=
>>>=
-
~
>=
-
&=
.
*
&&
<< 
==
<<=
[
/
||
>> 
+=
^=
]
%
!
>>> 
=
!=
(
&
< 
*=
)
|
> 
?!!
/=
>> 

Tabla 3: Operadores Java
Así por ejemplo el siguiente fragmento de código incrementa el valor de una variable en dos unidades, mediante la utilización del operador aritmético + que se utiliza para la suma:
int miNumero=0;
miNumero = miNumero + 2;
En el apartado "II.3 Operadores" de este tutorial aprenderemos que en Java hay formas más sencillas de hacer esto mismo, y estudiaremos el significado de cada uno de estos operadores.
e.) Separadores
Se usan para informar al compilador de Java de cómo están agrupadas las cosas en el código.
Los separadores admitidos por Java son: { } , : ;
f.) Comentarios y espacios en blanco
El compilador de Java reconoce y elimina los espacios en blanco, tabuladores, retornos de carro y comentarios durante el análisis del código fuente.
Los comentarios se pueden presentar en tres formatos distintos:
Formato
Uso
/*comentario*/
Se ignoran todos los caracteres entre /* */. Proviene del C
//comentario
Se ignoran todos los caracteres detrás de // hasta el fin de línea. Proviene del C++
/**comentario*/
Lo mismo que /* */ pero se podrán utilizar para documentación automática.
Tabla 4: Formatos de comentarios Java
Por ejemplo la siguiente línea de código presenta un comentario:
int alturaMinima = 150; // No menos de 150 centímetros

C. Expresiones
Los operadores, variables y las llamadas a métodos pueden ser combinadas en secuencias conocidas como expresiones. El comportamiento real de un programa Java se logra a través de expresiones, que se agrupan para crear sentencias.
Una expresión es una serie de variables, operadores y llamadas a métodos (construida conforme a la sintaxis del lenguaje) que se evalúa a un único valor.
Entre otras cosas, las expresiones son utilizadas para realizar cálculos, para asignar valores a variables, y para ayudar a controlar la ejecución del flujo del programa. La tarea de una expresión se compone de dos partes: realiza el cálculo indicado por los elementos de la expresión y devuelve el valor obtenido como resultado del cálculo.
Los operadores devuelven un valor, por lo que el uso de un operador es una expresión.
Por ejemplo, la siguiente sentencia es una expresión:
int contador=1;
contador++;
La expresión contador++ en este caso particular se evalúa al valor 1, que era el valor de la variable contador antes de que la operación ocurra, pero la variablecontador adquiere un valor de 2.
El tipo de datos del valor devuelto por una expresión depende de los elementos utilizados en la expresión. La expresión contador++ devuelve un entero porque ++devuelve un valor del mismo tipo que su operando y contador es un entero. Otras expresiones devuelven valores booleanos, cadenas...
Una expresión de llamada a un método se evalúa al valor de retorno del método; así el tipo de dato de la expresión de llamada a un método es el mismo que el tipo de dato del valor de retorno de ese método.
Otra sentencia interesante sería:
in.read( ) != -1 // in es un flujo de entrada
Esta sentencia se compone de dos expresiones:
  1. La primera expresión es una llamada al método in.read(). El método in.read() ha sido declarado para devolver un entero, por lo que la expresión in.read()se evalúa a un entero.
  2. La segunda expresión contenida en la sentencia utiliza el operador !=, que comprueba si dos operandos son distintos. En la sentencia en cuestión, los operandos son in.read() y -1. El operando in.read() es válido para el operador != porque in.read() es una expresión que se evalúa a un entero, así que la expresión in.read()!=-1 compara dos enteros. El valor devuelto por esta expresión será verdadero o falso dependiendo del resultado de la lectura del ficheroin.
Como se puede observar, Java permite construir sentencias (expresiones compuestas) a partir de varias expresiones más pequeñas con tal que los tipos de datos requeridos por una parte de la expresión concuerden con los tipos de datos de la otra.
D. Bloques y ámbito
En Java el código fuente está dividido en partes separadas por llaves, denominas bloques. Cada bloque existe independiente de lo que está fuera de él, agrupando en su interior sentencias (expresiones) relacionadas.
Desde un bloque externo parece que todo lo que está dentro de llaves se ejecuta como una sentencia. Pero, ¿qué es un bloque externo?. Esto tiene explicación si entendemos que existe una jerarquía de bloques, y que un bloque puede contener uno o más subbloques anidados.
El concepto de ámbito está estrechamente relacionado con el concepto de bloque y es muy importante cuando se trabaja con variables en Java. El ámbito se refiere a cómo las secciones de un programa (bloques) afectan el tiempo de vida de las variables.
Toda variable tiene un ámbito, en el que es usada, que viene determinado por los bloques. Una variable definida en un bloque interno no es visible por el bloque externo.
Las llaves de separación son importantes no sólo en un sentido lógico, ya que son la forma de que el compilador diferencie dónde acaba una sección de código y dónde comienza otra, sino que tienen una connotación estética que facilita la lectura de los programas al ser humano.
Así mismo, para identificar los diferentes bloques se utilizan sangrías. Las sangrías se utilizan para el programador, no para el compilador. La sangría (también denominada indentación) más adecuada para la estética de un programa Java son dos espacios:
{
 
  // Bloque externo
 
  int x = 1;
 
  {
 
    // Bloque interno invisible al exterior
 
    int y = 2;
 
  }
 
  x = y; // Da error: Y fuera de ámbito
 
}
Diferencia de C++ y Java

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 tipoString (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
C++ 
Sencillez
No
Robustez
No
Seguridad
No
Interpretado
No
Dinamicidad
No
Portabilidad
No
Neutralidad
No
Threads
No
Garbage Colection
No
Excepciones
Algunas
Representación
Alta
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 publicprivate 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 mallocnew,freedelete...) 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.