>>
Lección 04


Tipos de datos básicos y Variables.


En Java hay ocho tipos básicos de variables:

tipo ocupa default valores
boolean 1 bit false false, true
byte 8 bits 0 -128...127
short 16 bits 0 -32768 ... 32767
char 16 bits \u0000 \u0000 ... \uffff
int 32 bits 0 -2147483648 ... 2147483647
long 64 bits 0 -9,22E18 ... 9,22E18 (aprox)
float 32 bits 0.0 reales de 32 bits IEEE 754
double 64 bits 0.0 reales de 64 bits IEEE 754

Todos las demás variables se construyen a partir de éstas usando vectores (arrays) o creando clases.

Para declarar variables se escribe el tipo de la variable que se quiere declarar y luego los nombres de las variables declaradas separados por comas y terminando la lista por punto y coma. Ejemplos:

Como se ve en estos ejemplos se pueden declarar variables sin asignarles valores, es decir, sin inicializarlas. Sin embargo no se pueden declarar variables sin especificar su tipo. Muchas veces es conveniente inicializar las variables en el momento mismo de declararlas. Esto se hace utilizando el operador de asignación =.

Las variables cuyo tipo es uno de los tipos básicos se inicializan simplemente asignándoles un valor explícito mediante una expresión literal adecuada al tipo de la variable. Ejemplos:

Observe que para asignar un float es necesario hacer una conversión de tipo (class casting) al literal pues los literales con punto decimal siempre son de tipo double. En la siguiente sección de esta lección se explica cómo se construyen las expresiones literales de los diversos tipos básicos de variables y de las del tipo String.

Se pueden declarar variables cuyos tipos son datos básicos, pero también se pueden declarar variables cuyos tipos son clases. Cualquier clase de Java puede ser el tipo de una variable. Por ejemplo, se puede declarar una variable de tipo String, que es la clase que se utiliza en Java para las "cadenas" de caracteres. Para inicializar variables cuyos tipos son clases hay que crear un objeto de la clase y asignarlo a la variable. Por ejemplo:

declara una variable de tipo String y crea un objeto de la clase String con valor "valor de la cadena".

Otro ejemplo: podemos declarar una variable de tipo circulo usando la clase definida en la lección 2 así:

y para asignarle un valor a esta variable es necesario construir un objeto de la clase circulo y asignárselo a la variable c, por ejemplo así:

Las variables tienen validez dentro del bloque de expresiones donde se declaran. Normalmente un bloque está determinado por unas llaves { }. El bloque consta de todas las instrucciones que se encuentran dentro de las llaves. Se pueden declarar variables casi en cualquier parte del código. Si se declaran dentro de la definición de una clase son visibles para todos los métodos de la clase y, según el modificador que se le ponga, pueden ser visibles en otras clases. Pero si se declaran dentro de un método de la clase son visibles sólo dentro de ese método y si se declaran dentro de unas llaves { } son visibles sólo dentro del bloque de instrucciones encerrado por esas llaves. Las variables declaradas dentro de un método no admiten modificadores.


Literales.


Las expresiones que se utilizan para definir valores concretos de las variables de tipos básicos se llaman literales . Por ejemplo:

son literales del tipo int mientras que

son literales del tipo boolean.

Hay cuatro tipos de literales: booleanas, numéricas, de caracteres y de cadenas.

Las literales booleanas son solamente true y false . En Java, a diferencia del C, a las variables booleanas no se les pueden asignar valores numéricos.

Las literales numéricas se utilizan tanto para las variables enteras (byte, short, int y long) como para las variables de coma flotante (float y double). Todas ellas se escriben utilizando dígitos y el signo - para indicar cantidades negativas. Para las variables de tipo entero se pueden usar literales decimales (en base 10), hexadecimales (en base 16) y octales (en base 8).

Las literales decimales utilizan como dígitos: 0,1,2,3,4,5,6,7,8 y 9. Ejemplos:

Las literales hexadecimales utilizan como dígitos: 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E y F. Las letras A,B,C,D,E y F pueden ser mayúsculas o minúsculas. Para indicar que una literal es hexadecimal se le escribe como prefijo: 0x. Ejemplos:

Las literales octales utilizan como dígitos: 0,1,2,3,4,5,6 y 7. Para indicar que una literal es octal se le escribe como prefijo un 0 (cero). Ejemplos:

Todas las literales numericas de tipo entero las interpreta el compilador como int, a menos que su valor sea demasiado grande, en cuyo caso la considera de tipo long. Una literal entera puede asignarse a una variable de tipo byte o short si su valor no es demasiado grande. Ejemplos:

En caso contrario para realizar la asignación es necesario hacer explícitamente una conversión de tipo. Esto se hace escribiendo el tipo entre paréntesis antes de la literal. Ejemplos:

En todos los casos del ejemplo anterior los valores resultan negativos. (Esto se debe a que el bit principal en todos estos casos queda "encendido".)

Para que una literal represente un valor de tipo long, hay que agregar una L (mayúscula) al final. Por ejemplo:

es una expresión literal hexadecimal de un long.

Las literales de caracteres, es decir las que pueden asignarse a variables de tipo char, se escriben entre comillas simples. Por ejemplo:

son literales de caracteres. Hay algunos caracteres especiales que no se pueden escribir con el teclado o que juegan un papel especial, y que se representan con una diagonal invertida seguida de una letra u otro símbolo. Estos caracteres especiales son los siguientes:

retroceso '\b'
alimentación de forma '\f'
paso de línea '\n'
retorno de carro '\r'
tabulador '\t'
diagonal invertida '\\'
doble comilla '\"'
comilla sencilla '\''

La diagonal invertida también se puede utilizar para representar los caracteres usando números. Por ejemplo:

Son dos representaciones del caracter espacio '  ' utilizando números. La primera es octal y la segunda es la representación unicode.

La representación unicode '\udddd', donde las d son dígitos hexadecimales, corresponde al código ascii cuando los primeros dos dígitos son cero. Pero la representación unicode permite representar diferentes alfabetos. Por ejemplo los códigos unicode '\u0600' al '\u06ff' se usan para el alfabeto árabe y los del '\u2200' al '\u22ff' para operadores matemáticos. En este curso sólo usaremos los códigos unicode '\u0000' al '\u00ff' que corresponden a los caracteres ascii extendidos que se usan normalmente en una PC.

Las literales de cadenas se escriben entre comillas dobles. Las cadenas son los objetos de la clase String. Por lo tanto las cadenas no constituyen un tipo básico, sin embargo en muchos sentidos se tratan como si lo fueran. En particular, hay expresiones literales para las cadenas. Estos son ejemplos de literales de cadenas:

Como puede verse en el segundo ejemplo, dentro de la expresión para una cadena se pueden insertar las representaciones de los carateres especiales usando diagonales invertidas y de todos los caracteres usando representaciones octales o unicode.

El programa variables declara algunas variables y les asigna valores usando las literales presentadas en esta sección. Se sugiere al alumno estudiar el archivo variables.java y modificarlo declarando algunas otras variables, asignándoles valores y, con ayuda del compilador javac, verificar que sus declaraciones sean correctas. También se sugiere que use los métodos System.out.print y System.out.println para hacer que el programa escriba los valores de las variables que ha declarado.


Nombres de variables, métodos y clases.


Los nombres de las variables, de los métodos y de las clases pueden constar de letras mayúsculas (incluyendo Ñ,Ç,Á,É,Ü, etc...), letras minúsculas (incluyendo ñ,ç,á,é,ü, etc...), dígitos y algunos símbolos que no representan operadores. Se recomienda utilizar únicamente letras, dígitos y los los caracteres '_' y '$' para evitar posibles conflictos. Los nombres deben comenzar con una letra o con uno de los caracteres '_' o '$', en particular, no pueden comenzar con un dígito.

Java es sensible a mayúsculas y minúsculas, es decir, a y A son nombres diferentes y también lo son tbl y TbL.

En la práctica, casi siempre se utilizan sólo letras no acentuadas y dígitos. En particular no es conveniente dar nombres con caracteres raros a una clase pues este caracter raro pasará a formar parte del nombre del archivo de la clase y esto puede ocasionar problemas al sistema operativo. Muchas veces los nombres constituyen toda una frase, como por ejemplo: valorMedioRelativo o abscisaInicial. Ambos ejemplos muestran también otra de las costumbres en la nomenclatura de las variables y los métodos en Java, y es que cuando dichos nombres constituyen frases, la primera palabra se escribe en minúsculas y en todas las siguientes la primera letra es mayúscula y las demás son minúsculas.

Hay algunas palabras reservadas al lenguaje Java que no pueden utilizarse como nombres de variables, clases o métodos.

Esta es la lista de todas las palabras reservadas en Java.

abstract boolean break byte case
catch char class const * continue
default do double else extends
final finally float for goto *
if implements import instanceof int
interface long native new package
private protected public return short
static super switch synchronized this
throw throws transient try void
volatile while      

* señala dos palabras reservadas que no se usan: const y goto.

El nombre externo de una clase es el nombre del paquete al que pertenece, seguido de un punto y del nombre de la clase. Los paquetes y el papel que juegan los nombres externos se explica en la lección 2.


Vectores y matrices (Arrays)


Para declarar un vector (array de una dimensión) se escribe el tipo de las variables que van a formar el vector, a continuación se escriben unos corchetes [] y después de un espacio, el nombre que se desea dar al vector. Por ejemplo:

declara un vector de enteros cuyo nombre es a. Con tal declaración no se ha dicho todavía cuántos elementos tendrá el vector a ni se han dicho cuáles son tales elementos.

Tales declaraciones sólo dicen que cierta palabra será el nombre de un vector con elementos de cierto tipo. El tipo puede ser cualquier tipo básico de datos o cualquier clase de Java.

Para inicializar un vector se hacen dos cosas: primero se le da un tamaño y luego se crea cada uno de los elementos. Por ejemplo:

determina que a es un vector de 4 enteros. En la lección anterior se estudió el uso de new para crear un objeto de una clase. En el caso de vectores new no crea un objeto de una clase sino un vector cuyos elementos serán de la clase indicada, pero esos objetos aún no se han creado. Es decir, la expresión int[] a=new int[4]; solamente aparta espacio en memoria para contener los "apuntadores", "punteros" o "manejadores" (pointers) de los objetos, pero los objetos mismos aún no están determinados.

El siguiente paso en la definición de un vector es asignar valores a sus elementos. Por ejemplo:

asigna valores enteros, en este caso expresados en formato hexadecimal, a los cuatro elementos del vector a.

Si el tipo del vector corresponde a una clase, la asignación de valores debe hacerse con objetos de la clase y el programador debe cuidar de crear tales objetos o asignar objetos que ya existan, no basta simplemente asignar variables del tipo adecuado. Por ejemplo:

crea un vector de dos circulos.

crea dos circulos y los asigna a los elementos del vector mc. Cabe aclarar que en este ejemplo la expresión mc=new circulo[2] no es una aplicación del constructor de la clase circulo, pero en cambio mc[0]=new circulo(25,20,8) sí lo es.

A veces ambos pasos en la construcción de un vector pueden realizarse simultánemaente. Por ejemplo:

crea un vector a de cuatro elementos enteros cuyos valores son

a[0]=0x000000, a[1]=0x0000ff, a[2]=0x00ff00 y a[3]=0xff0000

respectivamente.

Otro ejemplo:

crea simultáneamente el vector de dos círculos y sus dos elementos.

Se pueden crear matrices multidimensionales de manera muy parecida a como se crean los vectores y sus elementos. Por ejemplo

crea una matriz de 2x4 números reales. Para asignar valores a tal matriz se asignan valores a cada uno de los elementos M[i][j] con i entre 0 y 1 y j entre 0 y 3. Una manera de crear dicha matriz y asignarle valores al mismo tiempo sería esta:

El programa matrices.class muestra tres maneras diferentes de crear una matriz cuadrada de 3x3 con los mismos valores. Compile matrices.java, ejecute matrices.class y compruebe que las tres construcciones son equivalentes.


Variables estáticas y constantes.


Una variable de una clase puede declararse como static. Esto hace que sea una variable de la clase y no de sus objetos o instancias. Por ejemplo, si se define una clase prueba así:

y se crean dos objetos a y b de dicha clase:

Entonces a.s, b.s y prueba.s se refieren exactamente a la misma variable y por tanto siempre son iguales, mientras que a.t y b.t son variables diferentes y pueden tener valores diferentes y además prueba.t no existe.

Cuando se crea un objeto de una clase se aparta espacio en memoria para todas sus variables no estáticas. El espacio de memoria para las variables estáticas se aparta cuando se utiliza por primera vez una clase, y no se usa más espacio para ellas aunque se creen muchos objetos de la clase.

También un método de una clase puede declararse como static. En ese caso, el método sólo tiene acceso a las variables estáticas de la clase, es decir, no puede usar las otras variables. Para acceder a una variable estática s o un método estático m() de una clase C se utilizan las expresiones C.s y C.m() respectivamente. Si c es un objeto de la clase C también puede hacerse referencia a s y a m usando las expresiones c.s y c.m() respectivamente pero no se recomienda esta práctica, es mejor usar el nombre de la clase en estos casos.

Una variable estática puede declararse como final. En tal caso es necesario asignarle en la misma declaración un valor y será imposible asignarle otro valor. En otras palabras, las variables que se declaran como static final son constantes.

Las palabras reservadas static y final son ejemplos de modificadores. En la lección 2 se presentó una tabla con todos los modificadores de Java.


Operadores.


Los operadores y la sintaxis de Java se heredan en gran medida del lenguaje C++ .

Hay cinco operadores aritméticos que actúan sobre variables numéricas:

operador significado
+ suma
- resta
* multiplicación
/ división
% módulo

Además el operador suma actúa sobre cadenas (Strings) realizando una concatenación. Por ejemplo:

escribirá:

primera cadena segunda cadena

Más aún, si se "suma" un número a una cadena, se obtiene una cadena. Por ejemplo;

escribirá:

cadena 1 cadena 2

Los operadores aritméticos pueden combinarse con el de asignación para crear unos operadores mixtos que tienen estos significados:

operador significado
+= x += y significa x = x + y
-= x -= y significa x = x - y
*= x *= y significa x = x * y
/= x /= y significa x = x / y
%= x %= y significa x = x % y

Hay seis operadores de comparación que actúan sobre variables primitivas:

operador significado
== igual
!= distinto
< menor que
> mayor que
<= menor o igual a
>= mayor o igual a

El resultado de estos operadores es un valor booleano, por lo que, si se desea, pueden asignarse a variables booleanas. Por ejemplo:

hace que la variable booleana b tenga valor true si x es diferente de y y false si x es igual a y.

Nota: Los primeros dos operadores de la tabla anterior pueden aplicarse también a objetos de cualquier clase, pero en ese caso la igualdad se da sólo cuando se trata del mismo objeto, es decir, aunque todas las variables de dos objetos distintos tengan el mismo valor, los objetos no son iguales en el sentido del operador = = . Por ello, para determinar si dos objetos son iguales en el sentido de que sus contenidos son idéntidos, se utiliza el método "equals". Por ejemplo, si s1 y s2 son dos cadenas (Strings), la expresión  s1.equals(s2)  da valor true si el contenido de s1 es igual al contenido de s2.

Hay seis operadores lógicos que actúan sobre expresiones booleanas:

operador significado valor
&& AND de corto circuito true sólo si ambos operandos son true
& AND evaluando ambos miembros true sólo si ambos operandos son true
|| OR de corto circuito true sólo si alguno de los dos operandos es true
| OR evaluando ambos miembros true sólo si alguno de los dos operandos es true
^ XOR (OR exclusivo)) true sólo si ambos operandos son diferentes
! NOT (negación) true sólo si el operando es false

Todos estos operadores son binarios (tiene dos operandos) excepto el de negación que es unario (tiene un sólo operando).

Un operador es de corto circuito si cuando el valor del primer operando determina el resultado, el segundo operando no se evalúa. La diferencia entre operadores de corto circuito y los que evalúan siempre ambos operandos es importante y debe tenerse presente cuando se escribe un programa. Los operadores de corto circuito hacen que la ejecución sea más rápida porque se salta pasos innecesarios, pero a veces el programa se escribe aprovechando el segundo operando para realizar alguna función que debe realizarse siempre, aunque el resultado de la operación no sea necesario en la evaluación. En tales casos no deben emplearse los operadores de corto circuito. El Ejercicio 03.3 puede servir para aclarar este concepto.

Hay 7 operadores a nivel de bits que actúan sobre enteros, es importante saber que estos operadores no actúan sobre bytes ni sobre short ni long. Esto hace que el tipo int sea el tipo numérico más utilizado en Java.

operador significado
~ NOT (complemento)
& AND
| OR
^ XOR
<< desplazamiento a la izquierda
>> desplazamiento a la derecha conservando el signo
>>> desplazamiento a la derecha con relleno de ceros

Estos operadores (excepto ~ que es unario), pueden combinarse con la asignación, igual que los operadores aritmético binarios:

operador significado
&= x &= y significa x = x & y
|= x |= y significa x = x | y
^= x ^= y significa x = x ^ y
<<= x <<= y significa x = x << y
>>= x >>= y significa x = x >> y
>>>= x >>>= y significa x = x >>> y

En Java, a diferencia de C++, los operadores no se pueden extender por sobrecarga. En Java sólo pueden sobrecargarse los métodos. La sobrecarga de métodos se estudió en la lección 2.

El programa operadores muestra el uso de los operadores. Se sugiere al alumno estudiar el archivo operadores.java y modificarlo realizando otras operaciones y verificar los resultados usando el método System.out.println para escribirlos.


Índice

Ejercicios de la Lección 04.


José Luis Abreu y Marta Oliveró