Índice 1. Declaración y uso de constantes y variables

Datos
H. Tejeda
Noviembre 2016
Índice
1. Declaración y uso de constantes y variables
1
2. Tipos de datos enteros
7
3. Tipo de dato boolean
8
4. Tipos de datos de punto flotante
9
5. Tipo de dato char
10
6. Clase Scanner para entrada desde el teclado
12
7. Uso de la clase JOptionPane para entrada desde la GUI
15
8. Aritmética
17
9. Conversión de tipos
18
1.
Declaración y uso de constantes y variables
Un elemento de datos es constante cuando su valor no puede ser cambiado durante la
ejecución de un progroma. Por ejemplo, cuando se incluye la siguiente sentencia en una clase
Java, el número 1234 es una constante:
1
System.out.println(1234);
Cada vez que la aplicación sea ejecutada el valor 1234 es mostrado. Los programadores se
refieren al 1234 como constante literal porque su valor es tomado literalmente en cada
uso. El número 1234 es también llamado una constante numérica como opuesto a una
constante carácter o cadena. Además, es una constante sin nombre como opuesta a una
con nombre, porque no hay un identificador asociado con esta.
Se puede configurar un elemento de datos para ser variable. Una variable es una localidad
de memoria que puede guardar un valor. Una variable puede tener sólo un valor a la vez,
pero el valor que tiene puede cambiar.
Ya sea que el elemento de datos sea variable o constante, en Java este siempre tiene un tipo de
dato. El tipo de dato de un elemento indica el tipo de dato que puede ser guardado, cuanta
memoria ocupa, y que tipos de operaciones pueden hacerse con el dato. Java proporciona
ocho tipos primitivos de datos. Un tipo primitivo es el tipo de dato más simple. Enseguida
se describen los ocho tipos:
Palabra
reservada
byte
short
int
long
float
double
char
boolean
Descripción
entero tamaño byte
entero corto
entero (defecto)
entero largo
punto flotante, precisión simple
punto flotante, precisión doble (defecto)
un sólo carácter
un valor boolean (true o false)
Los tipos primitivos también sirven como ladrillos para tipos de datos más complejos, llamados tipos referencia, los cuales guardan direcciones de memoria. Las clases que serán
creadas son ejemplos de tipos de referencias, como la clase Scanner que es revisada más
adelante.
1.1.
Declaración de variables
Una declaración de variable es una sentencia que reserva una localidad nombrada de
memoria e tiene lo siguiente:
Un tipo de dato que identifica el tipo de dato que la variable guardará.
Una identificador que es el nombre de la variable.
2
Un operador de asignación opcional y un valor asignado, si se quiere que la variable
contenga un valor inicial.
Un punto y coma como terminador.
Los nombres de variables observan las mismas reglas para nombrar identificadores legales de
clase, esto es, inician con una letra y no pueden ser una palabra reservada. Se debe declarar
una variable antes de poder usarla. Se puede declarar una variable en cualquier punto antes
de usarla, pero es una práctica declarar primero las variables en un método y luego poner
las sentencias ejecutables. Java es un lenguaje fuertemente tipado, o uno en el cual cada
variable tiene un tipo de dato bien definido que limita las operaciones que se pueden realizar
con este: esto también ı́mplica que todas las variables deben ser declaradas antes de que
puedan usarse.
Por convención los nombres de la variables inician con letras minúsculas para distinguirlas
de los nombres de las clases. Se emplea también el estilo caja camello superior donde se
pone se capitalizan las siguientes palabras del identificador.
El siguiente ejemplo declara una tipo de variable int llamado miEdad y le asigna un valor
inicial de 18:
int miEdad = 18;
Esta declaración es una sentencia completa y ejecutable, por lo que termina con punto y
coma. El sı́mbolo de igual (=) es el operador de asignación. Cualquier valor a la derecha
del signo de igual es asignado a la variable a la izquierda del signo igual. Una asignación
hecha cuando se declara una variable es una inicialización; darle el valor después es sólo
una asignación. Para el siguiente código, la primera sentencia es una inicialización, y la
segunda es una asignación:
int miEdad = 18;
miEdad = 21;
Se declara una variable una sola vez, pero se le podrı́an asignar valores nuevos las veces que
se requiera.
Observar que una expresión con una literal a la izquierda del operador de asignación, como en
21 = miEdad, es ilegal. El operador de asignación tiene una asociatividad derecha-izquierda.
La asociatividad indica el orden en el cual los operadores son usados con operadores. La
asociatividad puede ser derecha-izquierda o izquierda-derecha. Un identificador que puede
aparecer en el lado izquierdo de un operador de asignación en ocasiones es referido como un
lvalue. Una constante númerica como 18 no es un lvalue; sólo es un rvalue, o un dato que
puede aparecer sólo en el lado derecho de un operador de asignación. Una variable puede ser
usada como un lvalue o un rvalue.
3
Cuando se declara una variable dentro de un método pero no se le asigna valor, es una
variable no inicializada, Por ejemplo, la siguiente declaración de variable indica un tipo
int con el nombre miEdad, pero no hay valor asignado al momento de su creación:
int miEdad;
Una variable no inicializada contiene un valor desconocido llamado un valor basura. Java
protege de usar inadvertidamente el valor basura que está guardado en una variable no
inicializada, ya que se recibe, al compilar, un error indicando que la variable podrı́a no estar
inicializada.
Nota. Las variables declaradas en una clase, fuera de cualquier método, son inicializadas
automáticamente.
Se pueden declarar variables múltiples del mismo tipo en sentencias separadas. También
se puede declarar dos, o más, variables del mismo tipo en una sola sentencia separando la
declaraciones de variable con una coma, como se muestra enseguida:
int miEdad = 18, tuEdad = 15;
Por convención, los programadores declaran la mayorı́a de las variables en variables separadas. Se deberı́an declarar variables múltiples en la misma sentencia sólo si están relacionadas
estrechamente.
En el caso de que se quieran declarar variables de tipos diferentes, se debe usar una sentencia
separada para cada tipo.
1.2.
Constantes con nombre
Una variable es una localidad nombrada de memoria para la cual el contenido puede cambiar.
Si un valor de una localidad no deberı́a cambiar en la ejecución de un programa, esta puede
ser creada para ser una constante con nombre. También es conocida com una constante
simbólica. Una constante con nombre es parecida a una variable en cuanto a que tiene un
tipo de dato, un nombre y un valor. Una constante con nombre difiere de una variable en:
En la sentencia de declaración, el tipo de dato de una constante con nombre es precedida
por la palabra reservada final.
A una constante con nombre sólo se le puede asignar un valor una sola vez, y luego este
nunca puede ser cambiado. Se inicializa la constante con nombre usualmente cuando
se declara, si no se hace, se le conoce como final blanco, y se puede asignar un valor
después, pero antes de ser usada.
4
Por convención los identificadores de las constantes con nombres usan sólo mayúsculas,
y los guiones bajos se usan para separar palabras, como en el siguiente ejemplo.
final
final
final
final
int CANT_DE_SALONES = 20;
double PI = 3.14159;
double IMPUESTO = 0.15;
string UNIVERSIDAD = "UMSNH";
Las razones para usar una constante con nombre en vez de una literal son:
Usar constantes con nombre hace la lectura y la comprensión de los programas más
fácil.
Es más fácil cambiar sólo el valor de una constante con nombre que un conjunto de
literales que aparezcan en un programa.
El uso de constantes con nombre reduce la cantidad de errores tipográficos.
Cuando se usa una constante con nombre en una expresión, esta destaca de una variable.
1.3.
Alcance de variables y constantes
El alcance de un elemento de datos es el área en el cual es visible a un programa y en el
cual se puede referir a este usando un identificador simple. Una variable o constante está en
el alcance desde el lugar donde está declarado hasta el final del bloque de código en la cual
la declaración se encuentra. Un bloque de código es el código contenido entre un conjunto
de llaves. Ası́, si se declara una variable o constante dentro de un método, este puede ser
usado desde su declaración hasta el final del método, no importando que el método contengo
conjuntos múltiples de llaves. Entonces, un elemento de datos es usable sólo hasta el final
del bloque que tiene la declaración.
1.4.
Concatenar cadenas a variables y constantes
Se puede mostrar una variable o una cadena en una sentencia print() o println() sola o
en combinación con una cadena. Por ejemplo, la clase MostrarNumeros, código 1, declara
un entero diaDeCorte, inicializado a 5 en la lı́nea 3, luego este es enviado sólo al método
print() en la lı́nea 5; en las lı́neas 7-8 es combinado, o concatenado, a un String. En
Java, cuando una variable numérica es concantenada a un String con el sı́mbolo más, la
expresión completa es convertida a una String
5
1
2
3
4
5
6
7
8
9
10
public c l a s s MostrarNumeros {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
int diaDeCorte = 5 ;
System . out . p r i n t ( ” Las f a c t u r a s son mandadas e l dı́a ” ) ;
System . out . p r i n t ( diaDeCorte ) ;
System . out . p r i n t l n ( ” d e l mes” ) ;
System . out . p r i n t l n ( ” S i g u i e n t e f a c t u r a : d i c i e m b r e ” +
diaDeCorte ) ;
}
}
Código 1: clase MostrarNumeros
La salida del código anterior debe mostrar algo como lo siguiente:
Las facturas son mandadas el dı́a 5 del mes
Siguiente factura: diciembre 5
Cuando se concatena un String con números, la expresión entera es un String. Por lo
tanto la expresión "A" + 3 + 4 da el String "A34". Si la intención es crear el String A7,
entonces se deben agregar paréntesis para escribir "A" + (3 + 4).
La clase DialogoNumeros, código 2, usa el método showMessageDialog() dos veces para
mostrar un entero declarado como diasCredito e inicializada a 30. En cada sentencia de
las lı́neas 5 y 6, la variable numérica es concatenada a un String, haciendo que el segundo
argumento un String. En la lı́nea 5, el String concatenado es un String vacı́o, o String
null, creado con un conjunto de comillas dobles sin nada dentro de estas. El primer cuadro
de diálogo sólo muestra el valor 30, y el segundo muestra la concatenación con cadenas no
nulas.
1
2
3
4
5
6
7
8
9
import j a v a x . swing . JOptionPane ;
public c l a s s DialogoNumeros {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
int d i a s C r e d i t o = 3 0 ;
JOptionPane . showMessageDialog ( null , ” ” + d i a s C r e d i t o ) ;
JOptionPane . showMessageDialog
( null , ”Cada f a c t u r a e s por ” + d i a s C r e d i t o + ” d i a s ” ) ;
}
}
Código 2: clase DialogoNumeros
1.5.
Error al intercambiar valores
Cada constante sólo puede tener un valor en la duración del programa; cada variable puede
tener sólo un valor a la vez. En el siguiente extracto de código, se tiene en cuenta lo anterior,
6
para intercambiar los valores que tienen las variables x e y, usando como variable auxiliar a
z.
int
z =
x =
y =
2.
x = 2, y = 10, z;
x;
y;
z;
Tipos de datos enteros
Se pueden usar variables de tipo byte, short, int, y long para guardar enteros en Java; un
entero puede representar un subconjunto finito de los números enteros.
El tipo de dato int es el tipo de entero más usado. Una variable de tipo int puede contener
cualquier valor entero desde -2,147,483,648 hasta +2,147,483,647. Cuando se asigna un valor
a una variable int, no se ponen comas ni puntos, se ponen sólo dı́gitos y un signo más o
ménos opcional para indicar o entero positivo y negativo.
Nota. Los valores enteros legales están de −231 hasta 231 − 1. Estos son los valores más
grandes y mas bajos que se pueden guardar en cuatro bytes de memoria,el cual es el tamaño
de una variable int.
Los tipos byte, short, y long son variaciones del tipo entero. Los tipos byte y short ocupan
menos memoria y puede contener sólo valores pequeños; el tipo long ocupa más memoria y
puede manejar valores más grandes. La siguiente tabla muestra el lı́mite superior e inferior
de estos tipos.
Tipo
Valor
Mı́nimo
byte
-128
short -32,768
int
−2,147,483,648
long
−9,223,372,036,854,775,808
Valor
Máximo
127
32,767
2,147,483,647
−9,223,372,036,854,775,807
Tamaño
en bytes
1
2
4
8
Se debe escoger apropiadamente los tipos para las variables que serán usadas en una aplicación. Si se intenta asignar un valor que más grande para el tipo de dato de la variable, el
compilador emite un mensaje de error, por lo que la aplicación no se ejecuta. Si se escoge
un tipo de dato que es mayor que el que se ocupa, se desperdicia memoria. Por ejemplo,
una aplicación personal podrı́a usar una variable byte para la cantidad de dependientes, un
short para las horas trabajadas en un mes, 127 no es suficiente, y un int para un salario
anual.
7
Si una aplicación usa un entero constante literal, como 987, el número es un int por defecto.
Si se necesita usar una constante mayor que 2,147,483,647, o menor que -2,147,483,648, se
debe seguir el número con la letra L, o l, para indicar tipo long. Se prefiere L para evitar
confusión con el dı́gito 1. Por ejemplo, la siguiente sentencia guarda un número que es mayor
que el lı́mite máximo para el tipo int.
long mosquitosEnBosquesDelNorte = 2444555999L;
No se requiere algún caracter para guardar una constante numérica en un int, byte, o short.
3.
Tipo de dato boolean
La lógica de Boole o booleana está basada en comparaciones falso-verdadero. Una variable
booleana puede contener sólo uno de dos valores, true o false. Las siguientes sentencias
declaran y asignan valores apropiados a variables booleanas:
boolean esDı́aDePago = false;
boolean estásQuebrado = true;
También se pueden asignar valores obtenidos de comparaciones a variables booleanas. Se
soportan seis operadores relacionales en Java para realizar comparaciones. Un operador
relacional compara dos elementos; es también llamado a veces operador de comparación.
Una expresión que contenga un operador relacional da un valor booleano. En la siguiente
tabla se describen los operadores relacionales.
Operador
<
>
==
<=
>=
!=
Descripción
Ejemplo Ejemplo
verdadero
falso
menor que
1<2
2<1
mayor que
10 > 3
3 > 10
igual a
5 == 5
5 == 6
menor que o igual a
7 <= 7
9 <= 8
mayor que o igual a
7 >= 4
1 >= 3
diferente a
5!=6
5 == 5
Cuando se usa alguno de los operadores relacionales con dos sı́mbolos, como ==, <=, >=, o !=,
no se puede poner ningún espacio blanco entre los dos sı́mbolos. Tampoco se puede invertir
el orden de los sı́mbolos, ası́ =<, => y =! no son operadores válidos.
Sentencias válidas de declaración podrı́an incluir expresiones con operadores relacionales:
8
boolean esCincoMenorOIgual = (5 <= 3);
// valor guardado será false
Las expresiones booleanas tienen más sentido cuando variables, a las cuales se le han asignado
valores, son usadas en las comparaciones, como en los siguientes ejemplos.
boolean esHorasExtras = (horas > 40);
boolean esLimiteSuperiorImpuesto = (ingreso > 1000000);
boolean esPrimerPuntuaciónMayor = (puntuación1 > puntuación2);
4.
Tipos de datos de punto flotante
Un número punto flotante contiene posiciones decimales. Java soporta dos tipos de dato
punto flotante: float y double. Un tipo de dato float puede guardar valores punto flotante
hasta con una precisión de 6 o 7 dı́gitos significativos. Un tipo de dato double requiere más
memoria que un float y puede contener de 14 a 15 dı́gitos significativos de precisión. El
término dı́gitos significativos se refiere a la precisión matemática de un valor. Por ejemplo,
un float dado con el valor de 0.324516789 es mostrado como 0.324517 porque el valor es
preciso solo hasta la sexta posición decimal. El valor máximo para un double es 3.4x1038 .
Nota. Un float dado con el valor 324516789 es mostrado como 3.24617e+008, lo cual
es 324517000. La e en el valor mostrado es para el exponente; el +008 indica que el punto
decimal está ocho posiciones a la derecha de donde fue muestrado. En caso de ser negativo
indica que el punto decimal está a la izquierda, indicando un número muy pequeño. Este
formato es llamado notación cientı́fica.
Nota. Un programador podrı́a escoger guardar un valor como float en vez de double
para ahorrar memoria. Sin embargo, si niveles altos de precisión son necesarios, se deberı́a
escoger double.
Una constante punto flotante, como 15.67, es un double por defecto. Para indicar que una
constante numérica punto flotante es un float, se puede poner la letra F, o f, después del
numero, como en:
float monedero = 23.50F;
Se puede también poner D o d después de una constante de punto flotante para indicar
que es un double, pero como es el tipo por defecto en puntos flotantes, si no se pone
ası́ será guardada.
9
5.
Tipo de dato char
Se usa el tipo de dato char para guardar un solo carácter cualquiera. Se encierran los
valores de caracteres constantes entre comillas simples. Las siguientes son declaraciones de
caracteres:
char inicialPaterno = ’L’;
char calificaciónComputaciónI = ’A’;
char unaEstrella = ’*’;
Un carácter puede ser cualquier letra, signo de puntuación, o dı́gito. Un carácter que es un
dı́gito es guardado en la memoria de forma diferente a un valor numérico que represente el
mismo dı́gito. Por ejemplo, las siguientes dos sentencias son legales:
char unValorChar = ’7’;
int unValorInt = 7;
Si se muestran cada uno de estos valores usando el método println(), se verá un 7. Pero,
sólo el valor numérico, unValorInt, puede ser usado para representar el valor 9 en sentencias
aritméticas.
Una constante numérica puede ser guardada en una variable carácter y un carácter que
represente un número puede ser guardado en una variable numérica. Las siguientes dos
sentencias son legales, pero al menos que se entienda su significado, podrı́an dar resultados
no deseados:
char unValorChar = 7;
int unValorInt = ’7’;
Si estas variables son mostradas con println(), entonces el resultado de la salida será un
blanco para unValorChar y el número 55 para unValorInt. El sistema operativo Linux
guarda cada carácter como un número o código; a cada carácter se le asigna un código
numérico único usando Unicode. Por ejemplo, el carácter A es guardado usando el valor 65,
y B con el valor 66.
Una variable de tipo char puede guardar sólo un carácter. Para guardar un cadena de
caracteres, tales como el nombre de una persona, se debe usar una estructura de datos
llamada String. En Java, String es una clase incorporada que da los medios para guardar
y manipular cadenas de caracteres. Las constantes String son escritas entre comillas dobles.
Por ejemplo, la expresión que guarda el nombre Miguel como una cada en una variable
llamada primerNombre es:
String primerNombre = "Miguel";
10
También se puede guardar caracteres no imprimibles, como retroceso o tabulador, en una
variable char. Para estos carácteres se tiene que usar una secuencia de escape, la cual
inicia con una diagonal invertida seguida por un carácter, ası́ la pareja representa un sólo
carácter. El siguiente código guarda un carácter de nueva lı́nea y de tabulador:
char unCarNuevaLı́nea = ’\n’;
char unCarTabulador = ’\t’;
En la siguiente tabla se describe algunas secuencias de escape comunes que se pueden usar
en la salida de la ventana de comandos en Java.
Secuencia
de escape Descripción
\b
Retroceso; mueve el cursor un espacio a la izquierda
\t
Tabulador; mueve el cursor a la siguiente parada de tabulación
\n
Nueva lı́nea; mueve el cursor al inicio de la siguiente lı́nea
\r
Retorno de carro; mueve el cursor al inicio de la lı́nea actual
\"
Comillas dobles; muestra el sı́mbolo de comillas dobles
\’
Comilla simple, muestra el sı́mbolo de comilla simple
\\
Diagonal invertida; muestra el carácter diagonal invertida
Nota. Cuando se muestran valores con cuadros de diálogo JOptionPane en vez de la
ventana de comandos, la secuencias de escape nueva lı́nea, comillas dobles y diagonal
invertida funcionan como se espera, pero retroceso, tabulador, y retorno de carro no lo
hacen.
Cuando se quieren generar salida en lı́neas múltiples en la ventana de comandos, se puede
hacer de dos formas. Se puede usar la secuencia de escape nueva lı́nea, o se puede usar el
método println() varias veces. Las siguientes dos clases producen el mismo resultado.
public class HolaMundoNuevaLinea {
public static void main(String[] args) {
System.out.println("Hola\nmundo");
}
}
public class HolaMundoDosPrintln {
public static void main(String[] args) {
System.out.println("Hola");
System.out.println("mundo");
}
}
11
De las dos clases anteriores, la clase HolaMundoNuevaLinea es más eficiente, desde el punto
de vista de tecleado de código, ya que el método System.out.println() aparece una sola
vez, y desde el punto de vista del compilador también porque el método es llamado una sola
vez. pero quizás la clase HolaMundoDosPrintln es más fácil de leer y entender.
Nota. El método println() usar el carácter terminador de lı́nea de la plataforma local, el
cual podrı́a ser o no el caracter nueva lı́nea.
6.
Clase Scanner para entrada desde el teclado
Se pueden asignar valores a las variables al ser declaradas, pero los programas son más útiles
cuando el usuario puede dar valores diferentes a las variables cada vez que el programa se
ejecuta. Para crear programas interactivos que acepten la entrada de un usuario, se puede
usar System.in, la cual se refiere al dispositivo de entrada estándar (el teclado).
El objeto System.in no es tan flexible como los métodos println() o print(), los cuales
pueden mostrar diferentes tipos de datos (double, int, o String). System.in está diseñado
sólo para leer bytes, pero usando conjuntamente la clase Scanner se hace más flexible.
Para crear un objeto Scanner y conectarlo con el objeto System.in, se escribe una sentencia
como la siguiente:
Scanner dispositivoEntrada = new Scanner(System.in);
En esta sentencia se declara un objeto de tipo Scanner con el nombre dispositivoEntrada
y se le asigna el objeto creado Scanner. El objeto Scanner está conectado al dispositivo de
entrada por defecto.La palabra clave new se requiere siempre que se crean objetos a diferencia
de cuando se usan tipos primitivos.
La clase Scanner contiene métodos que recuperan valores de un dispositivo de entrada.
Cada valor recuperado es un token, el cual es un conjunto de caracteres que está separado
del siguiente conjunto por un blanco. Frecuentemente esto significa que el dato es aceptado
cuando el usuario presiona la tecla Intro, pero podrı́a significar también que el token sea
aceptado después del espacio o el tabulador. La tabla siguiente resume algunos de los métodos
más útiles que leen diferentes tipos de datos desde el dispositivo de entrada por default.
12
Metodo
next()
nextBoolean()
nextByte()
nextDouble()
nextFloat()
nextInt()
nextLine()
nextLong()
nextShort()
Descripción
Recupera el siguiente token completo como un String.
Recupera la entrada como un boolean.
Recupera la entrada como un byte.
Recupera la entrada como un double.
Recupera la entrada como un float.
Recupera la entrada como un int.
Recupera la siguiente lı́nea de datos y la regresa como un String.
Recupera la entrada como un long.
Recupera la entrada como un short.
La clase Scanner no tiene un método nextChar(). Para recuperar el primer caracter desde
el teclado, usar nextLine().charAt(0).
El código 3 de la clase ObtenerInfoUsuario usa dos métodos de la clase Scanner. El programa lee una cadena y un entero desde el teclado y los muestra. La clase Scanner está involucrada en:
Lı́nea 1 La sentencia importa la clase Scanner del paquete java.util y es requerida para
poder usar la clase.
Lı́nea 6 Declara y crea un objeto Scanner.
Lı́nea 8 Usa el método nextLine() para recuperar una lı́nea de texto desde el teclado y lo
guarda en la variable nom.
Lı́nea 10 Usa el método nextInt() para recuperar un entero desde el teclado y lo guarda
en la variable edad.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import j a v a . u t i l . Scanner ;
public c l a s s O b t e n e r I n f o U s u a r i o {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
S t r i n g nom ;
int edad ;
Scanner d i s p E n t r = new Scanner ( System . i n ) ;
System . out . p r i n t ( ” I n g r e s a tu nombre : ” ) ;
nom = d i s p E n t r . n e x t L i n e ( ) ;
System . out . p r i n t ( ” I n g r e s a tu edad : ” ) ;
edad = d i s p E n t r . n e x t I n t ( ) ;
System . out . p r i n t l n ( ”Tu nombre e s ” + nom +
” y t i e n e s ” + edad + ” añ o s . ” ) ;
}
}
Código 3: clase ObtenerInfoUsuario
13
Si se usa algún método de la clase Scanner y el siguiente token no puede ser convertido, se
recibe un mensaje de error.
Las cadenas literales contenidas en las sentencias print() que aparecen antes de cada sentencia de entrada son ejemplos de prompts (mensajes). Un prompt es un mensaje mostrado
para el usuario que pide y describe la entrada. No son necesarios pero hacen la aplicación
amigable.
Se puede escribir un solo prompt que pida múltiples valores de entrada —por ejemplo, “Por
favor ingresa tu edad, peso, código postal”. El usuario debera entonces ingresar tres valores
separados con espacios, tabuladores o presionando la tecla Intro.
Nota. Pidiendo al usuario que ingrese valores múltiples hace que se cometan errores. Es
una mejor práctica separar cada prompt por cada valor de entrada pedido.
6.1.
nextLine() después de otros métodos de Scanner
Se puede presentar un problema cuando se usa alguno de los métodos de recuperación de
tipo numérico de Scanner antes del método nextLine().
Cuando se ingresan caracteres usando el teclado, estos son guardados temporalmente en
una localidad de memoria llamada el búfer del teclado, también se le conoce como búfer
adelantado. Todas las teclas presionadas son guardadas en el búfer, incluyendo la tecla Intro.
La forma como los métodos de recuperación de la clase Scanner difieren entre ellos son:
Los métodos, como next(), nextInt(), y nextDouble() recuperan el siguiente token
en el búfer hasta antes del siguiente blanco, el cual puede ser un espacio, tabulador, o
Intro.
El método nextLine() lee todos los datos incluyendo el carácter de la tecla Intro.
Por lo anterior, cuando se pide al usuario un entero, y este ingresa 28 e Intro. La llamada
del método nextInt() recupera el 28 y deja el Intro en el búfer del teclado. Si enseguida
se pide una cadena y se llama al método nextLine() se recupera el Intro que estaba en el
búfer, y entonces el usuario ya no puede ingresar nada.
Para arreglar la situación descrita, después de cada llamada a next(), nextInt(), o nextDouble() se puede agregar una llamada al método nextLine() que recupere el Intro que se
quedó en el búfer del teclado.
14
7.
Uso de la clase JOptionPane para entrada desde la
GUI
Se puede aceptar entrada en un cuadro de diálogo GUI (Graphical User Interface) interfaz
gráfica de usuario) usando la clase JOptionPane.
Los dos cuadros de diálogo que pueden ser usados para aceptar la entrada del usuario son:
InputDialog pide al usuario un texto de entrada.
ConfirmDialog pide al usuario responder una pregunta usando botones (Si, No, Cancelar) para responder.
7.1.
Cuadros de diálogo de entrada
Un cuadro de diálogo de entrada hace una pregunta y proporciona un campo de texto para
que el usuario pueda dar su respuesta. Se crean los cuadros de diálogo de entrada usando el
método showInputDialog(). Hay seis versiones disponibles de este método, pero la versión
más simple usa un sólo argumento que es el mensaje que se quiere mostrar dentro del cuadro
de diálogo.
Por ejemplo, el código 4 de la clase DialogoHolaNombre es una aplicación que crea un cuadro
de diálogo de entrada con un mensaje para pedir el nombre. Después de que el usuario ingresa
el nombre y pulsa el botón Aceptar o la tecla Intro, se concatena un saludo con el nombre y
se muestra en cuadro de diálogo.
1
2
3
4
5
6
7
8
import j a v a x . swing . JOptionPane ;
public c l a s s DialogoHolaNombre {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
String resultado ;
r e s u l t a d o = JOptionPane . s ho wI np ut Dia lo g ( null , ”¿Cómo t e l l a m a s ? ” ) ;
JOptionPane . showMessageDialog ( null , ” Hola , ¡” + r e s u l t a d o +” ! ” ) ;
}
}
Código 4: clase DialogoHolaNombre
Una versión del método showInputDialog() permite controlar la apariencia del cuadro de
diálogo de entrada. Esta versión es la que requiere cuatro argumentos, y son para lo siguiente:
El componente padre, el cual es el componente pantalla, como una ventana, en frente
del cual aparecerá el cuadro de diálogo. Si este argumento es null, el cuadro de diálogo
estará centrado en la pantalla.
15
El mensaje que se muestra al usuario usando un String pero puede ser cualquier tipo
de objeto.
El tı́tulo que será mostrado en la barra de tı́tulo del cuadro de diálogo de entrada.
Un campo de clase describiendo el tipo de cuadro de diálogo; pudiendo ser alguno de los
siguientes: ERROR MESSAGE, INFORMATION MESSAGE, PLAIN MESSAGE, QUESTION MESSAGE,
y WARNING MESSAGE,
El código 5 muestra el uso del cuadro de diálogo con cuatro argumentos.
1
2
3
4
JOptionPane . sh ow In put Di al og ( null ,
”¿Qué edad t i e n e s ? ” ,
” I n f o r m a c i ón p e r s o n a l ” ,
JOptionPane .QUESTION MESSAGE ) ;
Código 5: cuadro de diálogo con 4 argumentos
Los cuadros de diálogo de entrada regresan un objeto String. Si se quiere usar el valor que
el usuario ingreso como un número, entonces el String deberá ser convertido. Para convertir
un String a un tipo int o double, se deben usar métodos de las clases Integer y Double.
Estas dos últimas clases son llamadas type-wrapper (tipo envoltura). Para obtener un valor
double se usa el método Double.parseDouble(String), y para obtener un int el método
Integer.parseInt(String).
7.2.
Cuadros de diálogo de confirmación
Si se quiere que la entrada del usuario no sea con el teclado, se pueden presentar botones para que el usuario pulse sobre alguno de estos para confirmar una opción. Un cuadro
de diálogo de confirmación presenta los botones Si , No , y Cancelar , el cual puede ser
creado usando algunas de las cuatro versiones del método showConfirmDialog() de la clase
JoptionPane. Este método devuelve un entero siendo alguno de los siguientes tres valores posibles: JOptionPane.YES OPTION, JOptionPane.NO OPTION, o JOptionPane.CANCEL OPTION.
El código 6 de la clase DialogoAerolinea muestra una aplicación que pide al usuario contestar una pregunta. La sentencia que inicia en la lı́nea 6 y termina en la lı́nea 7 muestra el cuadro
de diálogo. La respuesta del usuario se guarda en la variable entera llamada seleccion.
16
1
2
3
4
5
6
7
8
9
10
11
12
import j a v a x . swing . JOptionPane ;
public c l a s s D i a l o g o A e r o l i n e a {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
int s e l e c c i o n ;
boolean e s S i ;
s e l e c c i o n = JOptionPane . showConfirmDialog ( null ,
”¿Desea a s c e n d e r a p r i m e r a c l a s e ? ” ) ;
e s S i = ( s e l e c c i o n == JOptionPane . YES\ OPTION ) ;
JOptionPane . showMessageDialog ( null ,
” Usted r e s p o n d i ó ” + e s S i ) ;
}
}
Código 6: cuadro de diálogo con 4 argumentos
8.
Aritmética
La tabla siguiente describe los cinco operadores aritméticos estándar que se usan para realizar
cálculos con valores. Un valor usado en cada lado de un operador es un operando. Los
operadores mostrados son operadores binarios.
Operador
+
*
/
%
Descripción Ejemplo
Suma
17 + 3, el resultado es 20
Resta
17 − 3, el resultado es 14
Producto
17 ∗ 3, el resultado es 51
División
17.0/3, el resultado es 5.666667
17/3, el resultado es 5
Residuo
17 %3, el resultado es 2
Las operaciones son hechas siempre por Java con operandos del mismo tipo y el resultado es
del mismo tipo de los operandos. Por ejemplo, 17/3 es 5 porque se realiza una división entera
(sin ninguna parte fraccional), y 17.0/3 antes de que sea realizada, Java ajusta la precisión
a la del operando de mayor precisión, de esta forma se hace 17.0/3.0 y devuelve 5.6666667.
8.1.
Asociatividad y precedencia
La asociatividad de los operadores aritméticos con la misma precedencia es de izquierda a
derecha. En la sentencia respuesta = x + y + z; la x e y son sumados primero, obteniendo
un resultado temporal, que después es agregado a z, y esta suma es la que se asigna a
respuesta.
La precedencia del operador se refiere al orden en el cual partes de la expresión matemática
son evaluadas. La multiplicación, la división, y el residuo tienen la misma precedencia, y su
17
precedencia es mayor que la suma y la resta. La suma y la resta tienen la misma precedencia.
La precedencia se puede modificar usando paréntesis, es decir, tienen el mismo uso que en
las matemáticas.
2+3*4
(2+3)*4
2*(3+(4*5))
25/8*3
8.2.
Imprecisión de los números flotantes
Los valores enteros en Java son exactos, pero los números de punto flotante frecuentemente
son sólo aproximaciones ya que no pueden ser representados de forma precisa en formato
binario en los sistemas de cómputo. Estas imprecisiones llevan a varios problemas:
Cuando se genera salida de punto flotante, no podrı́a ser lo que se esperarı́a ver.
Cuando se hacen comparaciones con números de punto flotante, no podrı́an ser lo que
se esperarı́a obtener.
Por ejemplo, el código 7 de la clase DemoImprecision muestra un respuesta cuando es calculado 2.20 - 2.00. El resultado matemático debe ser 0.20, pero la salida es 0.20000000000000018.
Si se quieren eliminar las imprecisiones se pueden usar algunas de las varias técnicas para
redondear valores.
1
public c l a s s DemoImprecision {
2
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
double r e s p u e s t a = 2 . 2 0 − 2 . 0 0 ;
boolean e s I g u a l = r e s p u e s t a == 0 . 2 0 ;
System . out . p r i n t l n ( ” r e s p u e s t a e s ” + r e s p u e s t a ) ;
System . out . p r i n t l n ( ” e s I g u a l e s ” + e s I g u a l ) ;
}
3
4
5
6
7
8
9
}
Código 7: Programa DemoImprecision
9.
Conversión de tipos
Cuando se realiza aritmética con variables y constantes del mismo tipo, el resultado de la
operación retiene el mismo tipo. Frecuentemente se quiere realizar operaciones matemáticas
con operandos de tipos diferentes. El proceso de convertir de un tipo de datos a otro es la
18
conversión de tipo. Java realiza algunas conversiones automáticamente o implı́citamente,
pero otras conversiones deben ser pedidas explı́citamente por el programador.
9.1.
Conversión automática de tipo
Al realizar operaciones aritméticas con operando de tipos diferentes, Java escoge un tipo
unificado para el resultado. El tipo unificado es el tipo para el cual todos los operandos
en una expresión son convertidos para que estos sean compatibles con el resto. Java realiza
una conversión implı́cita, es decir, Java convierte automáticamentee operandos diferentes
al tipo unificado. Las conversiones implı́citas son también llamadas promociones. En la
siguiente tabla se muestra el orden o rango para establecer tipos unificados entre valores. Los
tipos short y byte son convertidos automáticamente a int cuando son usados en expresiones.
double Más alto
float
^
long
|
int
Más bajo
Cuando dos tipos diferentes son usados en una expresión, el tipo unificado es aquel que
esté más alto en la tabla, es decir, cuando un operando que es un tipo menor en la lista es
combinado con un tipo que es mayor, el operando tipo menor es convertido al mayor. Por
ejemplo, la suma de un double y un int da un double, y la resta de un long de un float
da un float.
Nota. Los valores booleanos no pueden ser convertidos a otro tipo.
El resultado de la multiplicación, en el siguiente código, es un double porque un double y
un int son multiplicados, el int es promovido al tipo unificador de rango más alto (double).
Por lo que la asignación del resultado a pagoBruto es legal.
int horasTrabajadas = 36;
double pagoHora = 234.56;
double pagoBruto = horasTrabajadas * pagoHora;
El siguiente extracto de código no compilará porque horasTrabajadas por pagoHora es
un double, y Java no permite la pérdida de precisión que ocurre si se intenta guardar el
resultado double calculado en un int.
int horasTrabajadas = 36;
double pagoHora = 234.56;
int pagoBruto = horasTrabajadas * pagoHora;
19
Los tipos de dato char, short, y byte son promovidos a int cuando se usan en sentencias
con tipos diferentes, por lo que un cálculo que incluya cualquier combinación de los tipos
anteriores dará un resultado int por defecto.
9.2.
Conversiones explı́citas
Se puede anular a propósito el tipo unificado impuesto por Java haciendo una conversión de
tipo. La conversión de tipo forza un valor de un tipo de dato para ser usado como un valor
de otro tipo. Para realizar lo anterior se usa el operador de conversión, el cual es creado
poniendo el tipo del resultado deseado entre paréntesis. Usando un operador de conversión es
una operación explı́citia. El operador de conversión es seguido por la constante, variable
o expresión a ser convertida. En el siguiente código un conversión de tipo es hecha:
double saldoBancario = 12345.67;
float presupuestoSemanal = (float) (saldoBancario / 4);
Sin la conversión, la sentencia que asigna el resultado a presupuestoSemanal no compiları́a.
Nota. El operador de conversión es también llamado completamente operador de conversión unario. Este operador sólo usa un operando, que es el que sigue al operador de
conversión.
En el siguiente código ocurre una conversión de float a int:
float miDinero = 543.21f;
int pesos = (int) miDinero;
Es fácil perder datos cuando se realiza una conversión. Por ejemplo, el valor byte más
grande es 127 y el valor int mas grande es 2,147,483,647 ası́ que las siguientes sentencias da
resultados distorsionados;
int unEnteroCorrecto = 200;
byte unMalByte = (byte)unEnteroCorrecto;
Un tipo byte está formado por ocho valores uno ó cero, o dı́gitos binarios. El primer dı́gito
binario, o bit, guarda un 0 o un 1 para indicar positivo o negativo respectivamente. Los siete
bits restantes guardan el valor actual. Cuando el valor entero 200 es guardado en la variable
byte, su valor más gran consume el octavo bit, poniendo un 1, y forzando a la variable
unMalByte para que guarde el valor -72, el cual es inexacto y engañoso.
No es necesario realizar una operación de conversión cuando se asigna un valor a un tipo
unificador mayor. En la siguiente sentencia Java automáticamente promueve la constante
entera 123 a un double para que pueda ser guardada en la variable pagoHora:
20
double pagoHora = 123;
Sin embargo, por claridad, para una asignación como la anterior, se podrı́a preferir escribir
lo siguiente:
double pagoHora = 123.0;
21