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

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. Descripción.
234KB Größe 10 Downloads 79 vistas
Datos H. Tejeda Noviembre 2016

´Indice 1. Declaraci´ on 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´ etica

17

9. Conversi´ on de tipos

18

1.

Declaraci´ on y uso de constantes y variables

Un elemento de datos es constante cuando su valor no puede ser cambiado durante la ejecuci´on de un progroma. Por ejemplo, cuando se incluye la siguiente sentencia en una clase Java, el n´ umero 1234 es una constante: 1

System.out.println(1234); Cada vez que la aplicaci´on 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´ umero 1234 es tambi´en llamado una constante num´ erica como opuesto a una constante car´acter o cadena. Adem´as, 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´olo 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´as simple. Enseguida se describen los ocho tipos: Palabra reservada byte short int long float double char boolean

Descripci´ on entero tama˜ no byte entero corto entero (defecto) entero largo punto flotante, precisi´on simple punto flotante, precisi´on doble (defecto) un s´olo car´acter un valor boolean (true o false)

Los tipos primitivos tambi´en sirven como ladrillos para tipos de datos m´as complejos, llamados tipos referencia, los cuales guardan direcciones de memoria. Las clases que ser´an creadas son ejemplos de tipos de referencias, como la clase Scanner que es revisada m´as adelante.

1.1.

Declaraci´ on de variables

Una declaraci´ on 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´a. Una identificador que es el nombre de la variable. 2

Un operador de asignaci´on 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´actica declarar primero las variables en un m´etodo 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´en ´ımplica que todas las variables deben ser declaradas antes de que puedan usarse. Por convenci´on los nombres de la variables inician con letras min´ usculas para distinguirlas de los nombres de las clases. Se emplea tambi´en 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´on es una sentencia completa y ejecutable, por lo que termina con punto y coma. El s´ımbolo de igual (=) es el operador de asignaci´ on. Cualquier valor a la derecha del signo de igual es asignado a la variable a la izquierda del signo igual. Una asignaci´on hecha cuando se declara una variable es una inicializaci´ on; darle el valor despu´es es s´olo una asignaci´ on. Para el siguiente c´odigo, la primera sentencia es una inicializaci´on, y la segunda es una asignaci´on: 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´on con una literal a la izquierda del operador de asignaci´on, como en 21 = miEdad, es ilegal. El operador de asignaci´on 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´on en ocasiones es referido como un lvalue. Una constante n´ umerica como 18 no es un lvalue; s´olo es un rvalue, o un dato que puede aparecer s´olo en el lado derecho de un operador de asignaci´on. Una variable puede ser usada como un lvalue o un rvalue. 3

Cuando se declara una variable dentro de un m´etodo pero no se le asigna valor, es una variable no inicializada, Por ejemplo, la siguiente declaraci´on de variable indica un tipo int con el nombre miEdad, pero no hay valor asignado al momento de su creaci´on: int miEdad; Una variable no inicializada contiene un valor desconocido llamado un valor basura. Java protege de usar inadvertidamente el valor basura que est´a 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´etodo, son inicializadas autom´aticamente.

Se pueden declarar variables m´ ultiples del mismo tipo en sentencias separadas. Tambi´en se puede declarar dos, o m´as, 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´on, los programadores declaran la mayor´ıa de las variables en variables separadas. Se deber´ıan declarar variables m´ ultiples en la misma sentencia s´olo si est´an 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´on de un programa, esta puede ser creada para ser una constante con nombre. Tambi´en es conocida com una constante simb´ olica. 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´on, el tipo de dato de una constante con nombre es precedida por la palabra reservada final. A una constante con nombre s´olo 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´es, pero antes de ser usada. 4

Por convenci´on los identificadores de las constantes con nombres usan s´olo may´ usculas, 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´on de los programas m´as f´acil. Es m´as f´acil cambiar s´olo 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´aficos. Cuando se usa una constante con nombre en una expresi´on, esta destaca de una variable.

1.3.

Alcance de variables y constantes

El alcance de un elemento de datos es el a´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´a en el alcance desde el lugar donde est´a declarado hasta el final del bloque de c´odigo en la cual la declaraci´on se encuentra. Un bloque de c´ odigo es el c´odigo contenido entre un conjunto de llaves. As´ı, si se declara una variable o constante dentro de un m´etodo, este puede ser usado desde su declaraci´on hasta el final del m´etodo, no importando que el m´etodo contenga conjuntos m´ ultiples de llaves. Entonces, un elemento de datos es usable s´olo hasta el final del bloque que tiene la declaraci´on.

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´on con una cadena. Por ejemplo, la clase MostrarNumeros, c´odigo 1, declara un entero diaDeCorte, inicializado a 5 en la l´ınea 3, luego este es enviado s´olo al m´etodo 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´erica es concantenada a un String con el s´ımbolo m´as, la expresi´on 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´odigo 1: clase MostrarNumeros La salida del c´odigo 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´ umeros, la expresi´on completa es un String. Por lo tanto la expresi´on "A" + 3 + 4 da el String "A34". Si la intenci´on es crear el String A7, entonces se deben agregar par´entesis para escribir "A" + (3 + 4). La clase DialogoNumeros, c´odigo 2, usa el m´etodo 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´erica 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´alogo s´olo muestra el valor 30, y el segundo muestra la concatenaci´on 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´odigo 2: clase DialogoNumeros

1.5.

Error al intercambiar valores

Cada constante s´olo puede tener un valor en la duraci´on del programa; cada variable puede tener s´olo un valor a la vez. En el siguiente extracto de c´odigo, 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´ umeros enteros. El tipo de dato int es el tipo de entero m´as 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´olo d´ıgitos y un signo m´as o menos opcional para indicar o entero positivo y negativo. Nota. Los valores enteros legales est´an de −231 hasta 231 − 1. Estos son los valores m´as grandes y mas bajos que se pueden guardar en cuatro bytes de memoria,el cual es el tama˜ no 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´olo valores peque˜ nos; el tipo long ocupa m´as memoria y puede manejar valores m´as 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´ aximo 127 32,767 2,147,483,647 −9,223,372,036,854,775,807

Tama˜ no en bytes 1 2 4 8

Se debe escoger apropiadamente los tipos para las variables que ser´an usadas en una aplicaci´on. Si se intenta asignar un valor que m´as grande para el tipo de dato de la variable, el compilador emite un mensaje de error, por lo que la aplicaci´on 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´on 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´on usa un entero constante literal, como 987, el n´ umero 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´ umero con la letra L, o l, para indicar tipo long. Se prefiere L para evitar confusi´on con el d´ıgito 1. Por ejemplo, la siguiente sentencia guarda un n´ umero que es mayor que el l´ımite m´aximo para el tipo int. long mosquitosEnBosquesDelNorte = 2444555999L; No se requiere alg´ un caracter para guardar una constante num´erica en un int, byte, o short.

3.

Tipo de dato boolean

La l´ogica de Boole o booleana est´a basada en comparaciones falso-verdadero. Una variable booleana puede contener s´olo uno de dos valores, true o false. Las siguientes sentencias declaran y asignan valores apropiados a variables booleanas: boolean esD´ ıaDePago = false; boolean est´ asQuebrado = true; Tambi´en 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´en llamado a veces operador de comparaci´ on. Una expresi´on que contenga un operador relacional da un valor booleano. En la siguiente tabla se describen los operadores relacionales. Operador < > == = !=

Descripci´ on

Ejemplo Ejemplo verdadero falso menor que 1 10 igual a 5 == 5 5 == 6 menor que o igual a 7 = 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´ un espacio blanco entre los dos s´ımbolos. Tampoco se puede invertir el orden de los s´ımbolos, as´ı = y =! no son operadores v´alidos. Sentencias v´alidas de declaraci´on podr´ıan incluir expresiones con operadores relacionales:

8

boolean esCincoMenorOIgual = (5 40); boolean esLimiteSuperiorImpuesto = (ingreso > 1000000); boolean esPrimerPuntuaci´ onMayor = (puntuaci´ on1 > puntuaci´ on2);

4.

Tipos de datos de punto flotante

Un n´ umero 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´on de 6 o 7 d´ıgitos significativos. Un tipo de dato double requiere m´as memoria que un float y puede contener de 14 a 15 d´ıgitos significativos de precisi´on. El t´ermino d´ıgitos significativos se refiere a la precisi´on matem´atica 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´on decimal. El valor m´aximo 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´a ocho posiciones a la derecha de donde fue muestrado. En caso de ser negativo indica que el punto decimal est´a a la izquierda, indicando un n´ umero muy peque˜ no. Este formato es llamado notaci´ on 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´on 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´erica punto flotante es un float, se puede poner la letra F, o f, despu´es del numero, como en: float monedero = 23.50F; Se puede tambi´en poner D o d despu´es 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´a guardada. 9

5.

Tipo de dato char

Se usa el tipo de dato char para guardar un solo car´acter cualquiera. Se encierran los valores de caracteres constantes entre comillas simples. Las siguientes son declaraciones de caracteres: char inicialPaterno = ’L’; char calificaci´ onComputaci´ onI = ’A’; char unaEstrella = ’*’; Un car´acter puede ser cualquier letra, signo de puntuaci´on, o d´ıgito. Un car´acter que es un d´ıgito es guardado en la memoria de forma diferente a un valor num´erico 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´etodo println(), se ver´a un 7. Pero, s´olo el valor num´erico, unValorInt, puede ser usado para representar el valor 9 en sentencias aritm´eticas. Una constante num´erica puede ser guardada en una variable car´acter y un car´acter que represente un n´ umero puede ser guardado en una variable num´erica. 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´a un blanco para unValorChar y el n´ umero 55 para unValorInt. El sistema operativo Linux guarda cada car´acter como un n´ umero o c´odigo; a cada car´acter se le asigna un c´odigo num´erico u ´nico usando Unicode. Por ejemplo, el car´acter A es guardado usando el valor 65, y B con el valor 66. Una variable de tipo char puede guardar s´olo un car´acter. 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´on que guarda el nombre Miguel como una cadena en una variable llamada primerNombre es: String primerNombre = "Miguel"; 10

Tambi´en se puede guardar caracteres no imprimibles, como retroceso o tabulador, en una variable char. Para estos car´acteres se tiene que usar una secuencia de escape, la cual inicia con una diagonal invertida seguida por un car´acter, as´ı la pareja representa un s´olo car´acter. El siguiente c´odigo guarda un car´acter 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´ on \b Retroceso; mueve el cursor un espacio a la izquierda \t Tabulador; mueve el cursor a la siguiente parada de tabulaci´on \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´acter diagonal invertida Nota. Cuando se muestran valores con cuadros de di´alogo 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´ ultiples 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´etodo 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´as eficiente, desde el punto de vista de tecleado de c´odigo, ya que el m´etodo System.out.println() aparece una sola vez, y desde el punto de vista del compilador tambi´en porque el m´etodo es llamado una sola vez. pero quiz´as la clase HolaMundoDosPrintln es m´as f´acil de leer y entender. Nota. El m´etodo println() usar el car´acter 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´as u ´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´andar (el teclado). El objeto System.in no es tan flexible como los m´etodos println() o print(), los cuales pueden mostrar diferentes tipos de datos (double, int, o String). System.in est´a dise˜ nado s´olo para leer bytes, pero usando conjuntamente la clase Scanner se hace m´as 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´a 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´etodos que recuperan valores de un dispositivo de entrada. Cada valor recuperado es un token, el cual es un conjunto de caracteres que est´a 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´en que el token sea aceptado despu´es del espacio o el tabulador. La tabla siguiente resume algunos de los m´etodos m´as u ´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´ on 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´etodo nextChar(). Para recuperar el primer caracter desde el teclado, usar nextLine().charAt(0). El c´odigo 3 de la clase ObtenerInfoUsuario usa dos m´etodos de la clase Scanner. El programa lee una cadena y un entero desde el teclado y los muestra. La clase Scanner est´a 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´etodo nextLine() para recuperar una l´ınea de texto desde el teclado y lo guarda en la variable nom. L´ınea 10 Usa el m´etodo 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˜ nos . ” ) ; } }

C´odigo 3: clase ObtenerInfoUsuario

13

Si se usa alg´ un m´etodo 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´on amigable. Se puede escribir un solo prompt que pida m´ ultiples valores de entrada —por ejemplo, “Por favor ingresa tu edad, peso, c´odigo 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´ ultiples hace que se cometan errores. Es una mejor pr´actica separar cada prompt por cada valor de entrada pedido.

6.1.

nextLine() despu´ es de otros m´ etodos de Scanner

Se puede presentar un problema cuando se usa alguno de los m´etodos de recuperaci´on de tipo num´erico de Scanner antes del m´etodo nextLine(). Cuando se ingresan caracteres usando el teclado, estos son guardados temporalmente en una localidad de memoria llamada el b´ ufer del teclado, tambi´en se le conoce como b´ ufer adelantado. Todas las teclas presionadas son guardadas en el b´ ufer, incluyendo la tecla Intro. La forma como los m´etodos de recuperaci´on de la clase Scanner difieren entre ellos son: Los m´etodos, como next(), nextInt(), y nextDouble() recuperan el siguiente token en el b´ ufer hasta antes del siguiente blanco, el cual puede ser un espacio, tabulador, o Intro. El m´etodo nextLine() lee todos los datos incluyendo el car´acter de la tecla Intro. Por lo anterior, cuando se pide al usuario un entero, y este ingresa 28 e Intro. La llamada del m´etodo nextInt() recupera el 28 y deja el Intro en el b´ ufer del teclado. Si enseguida se pide una cadena y se llama al m´etodo nextLine() se recupera el Intro que estaba en el b´ ufer, y entonces el usuario ya no puede ingresar nada. Para arreglar la situaci´on descrita, despu´es de cada llamada a next(), nextInt(), o nextDouble() se puede agregar una llamada al m´etodo nextLine() que recupere el Intro que se qued´o en el b´ ufer del teclado.

14

7.

Uso de la clase JOptionPane para entrada desde la GUI

Se puede aceptar entrada en un cuadro de di´alogo GUI (Graphical User Interface) interfaz gr´afica de usuario) usando la clase JOptionPane. Los dos cuadros de di´alogo 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´ alogo de entrada

Un cuadro de di´alogo 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´alogo de entrada usando el m´etodo showInputDialog(). Hay seis versiones disponibles de este m´etodo, pero la versi´on m´as simple usa un s´olo argumento que es el mensaje que se quiere mostrar dentro del cuadro de di´alogo. Por ejemplo, el c´odigo 4 de la clase DialogoHolaNombre es una aplicaci´on que crea un cuadro de di´alogo de entrada con un mensaje para pedir el nombre. Despu´es de que el usuario ingresa el nombre y pulsa el bot´on Aceptar o la tecla Intro, se concatena un saludo con el nombre y se muestra en cuadro de di´alogo. 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´omo t e l l a m a s ? ” ) ; JOptionPane . showMessageDialog ( null , ” Hola , ¡” + r e s u l t a d o +” ! ” ) ; } }

C´odigo 4: clase DialogoHolaNombre Una versi´on del m´etodo showInputDialog() permite controlar la apariencia del cuadro de di´alogo de entrada. Esta versi´on 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´a el cuadro de di´alogo. Si este argumento es null, el cuadro de di´alogo estar´a 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´a mostrado en la barra de t´ıtulo del cuadro de di´alogo de entrada. Un campo de clase describiendo el tipo de cuadro de di´alogo; pudiendo ser alguno de los siguientes: ERROR MESSAGE, INFORMATION MESSAGE, PLAIN MESSAGE, QUESTION MESSAGE, y WARNING MESSAGE, El c´odigo 5 muestra el uso del cuadro de di´alogo con cuatro argumentos. 1 2 3 4

JOptionPane . sh ow In put Di al og ( null , ”¿Qu´e edad t i e n e s ? ” , ” Informaci´ on p e r s o n a l ” , JOptionPane .QUESTION MESSAGE ) ;

C´odigo 5: cuadro de di´alogo con 4 argumentos Los cuadros de di´alogo de entrada regresan un objeto String. Si se quiere usar el valor que el usuario ingreso como un n´ umero, entonces el String deber´a ser convertido. Para convertir un String a un tipo int o double, se deben usar m´etodos de las clases Integer y Double. Estas dos u ´ltimas clases son llamadas type-wrapper (tipo envoltura). Para obtener un valor double se usa el m´etodo Double.parseDouble(String), y para obtener un int el m´etodo Integer.parseInt(String).

7.2.

Cuadros de di´ alogo de confirmaci´ on

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´on. Un cuadro de di´alogo de confirmaci´on presenta los botones Si , No , y Cancelar , el cual puede ser creado usando algunas de las cuatro versiones del m´etodo showConfirmDialog() de la clase JoptionPane. Este m´etodo devuelve un entero siendo alguno de los siguientes tres valores posibles: JOptionPane.YES OPTION, JOptionPane.NO OPTION, o JOptionPane.CANCEL OPTION. El c´odigo 6 de la clase DialogoAerolinea muestra una aplicaci´on 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´alogo. 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 ´ o ” + esSi ); } }

C´odigo 6: cuadro de di´alogo con 4 argumentos

8.

Aritm´ etica

La tabla siguiente describe los cinco operadores aritm´eticos est´andar que se usan para realizar c´alculos con valores. Un valor usado en cada lado de un operador es un operando. Los operadores mostrados son operadores binarios. Operador + * / %

Descripci´ on Ejemplo Suma 17 + 3, el resultado es 20 Resta 17 − 3, el resultado es 14 Producto 17 ∗ 3, el resultado es 51 Divisi´on 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´on entera (sin ninguna parte fraccional), y 17.0/3 antes de que sea realizada, Java ajusta la precisi´on a la del operando de mayor precisi´on, de esta forma se hace 17.0/3.0 y devuelve 5.6666667.

8.1.

Asociatividad y precedencia

La asociatividad de los operadores aritm´eticos 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´es 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´on matem´atica son evaluadas. La multiplicaci´on, la divisi´on, 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´entesis, es decir, tienen el mismo uso que en las matem´aticas. 2+3*4 (2+3)*4 2*(3+(4*5)) 25/8*3

8.2.

Imprecisi´ on de los n´ umeros flotantes

Los valores enteros en Java son exactos, pero los n´ umeros de punto flotante frecuentemente son s´olo aproximaciones ya que no pueden ser representados de forma precisa en formato binario en los sistemas de c´omputo. 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´ umeros de punto flotante, no podr´ıan ser lo que se esperar´ıa obtener. Por ejemplo, el c´odigo 7 de la clase DemoImprecision muestra un respuesta cuando es calculado 2.20 - 2.00. El resultado matem´atico debe ser 0.20, pero la salida es 0.20000000000000018. Si se quieren eliminar las imprecisiones se pueden usar algunas de las varias t´ecnicas para redondear valores. 1 2 3 4 5 6 7 8

public c l a s s DemoImprecision { 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 ) ; } }

C´odigo 7: Programa DemoImprecision

9.

Conversi´ on de tipos

Cuando se realiza aritm´etica con variables y constantes del mismo tipo, el resultado de la operaci´on retiene el mismo tipo. Frecuentemente se quiere realizar operaciones matem´aticas con operandos de tipos diferentes. El proceso de convertir de un tipo de datos a otro es la conversi´ on de tipo. Java realiza algunas conversiones autom´aticamente o impl´ıcitamente, pero otras conversiones deben ser pedidas expl´ıcitamente por el programador. 18

9.1.

Conversi´ on autom´ atica de tipo

Al realizar operaciones aritm´eticas 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´on son convertidos para que estos sean compatibles con el resto. Java realiza una conversi´ on impl´ıcita, es decir, Java convierte autom´aticamentee operandos diferentes al tipo unificado. Las conversiones impl´ıcitas son tambi´en 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´aticamente a int cuando son usados en expresiones. double M´as alto float ^ long | int M´as bajo Cuando dos tipos diferentes son usados en una expresi´on, el tipo unificado es aquel que est´e m´as 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´on, en el siguiente c´odigo, es un double porque un double y un int son multiplicados, el int es promovido al tipo unificador de rango m´as alto (double). Por lo que la asignaci´on del resultado a pagoBruto es legal. int horasTrabajadas = 36; double pagoHora = 234.56; double pagoBruto = horasTrabajadas * pagoHora; El siguiente extracto de c´odigo no compilar´a porque horasTrabajadas multiplicado por pagoHora es un double, y Java no permite la p´erdida de precisi´on que ocurre si se intenta guardar el resultado double calculado en un int. int horasTrabajadas = 36; double pagoHora = 234.56; int pagoBruto = horasTrabajadas * pagoHora; 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´alculo que incluya cualquier combinaci´on de los tipos anteriores dar´a un resultado int por defecto. 19

9.2.

Conversiones expl´ıcitas

Se puede anular a prop´osito el tipo unificado impuesto por Java haciendo una conversi´on de tipo. La conversi´ on 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´ on, el cual es creado poniendo el tipo del resultado deseado entre par´entesis. Usando un operador de conversi´on es una operaci´ on expl´ıcitia. El operador de conversi´on es seguido por la constante, variable o expresi´on a ser convertida. En el siguiente c´odigo un conversi´on de tipo es hecha: double saldoBancario = 12345.67; float presupuestoSemanal = (float) (saldoBancario / 4); Sin la conversi´on, la sentencia que asigna el resultado a presupuestoSemanal no compilar´ıa. Nota. El operador de conversi´ on es tambi´en llamado completamente operador de conversi´ on unario. Este operador s´ olo usa un operando, que es el que sigue al operador de conversi´ on.

En el siguiente c´odigo ocurre una conversi´on de float a int: float miDinero = 543.21f; int pesos = (int ) miDinero; Es f´acil perder datos cuando se realiza una conversi´on. Por ejemplo, el valor byte m´as 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´a formado por ocho valores uno o´ 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´as 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˜ noso. No es necesario realizar una operaci´on de conversi´on cuando se asigna un valor a un tipo unificador mayor. En la siguiente sentencia Java autom´aticamente promueve la constante entera 123 a un double para que pueda ser guardada en la variable pagoHora: double pagoHora = 123; 20

Sin embargo, por claridad, para una asignaci´on como la anterior, se podr´ıa preferir escribir lo siguiente: double pagoHora = 123.0;

21