Title: Introduccin a Java I
1Introducción a Java (I)
2Índice
- Tipos de datos y operadores
- Entradas y Salidas básicas
- Sentencias de control
- Clases
3Tipos de datos y operadores
4Variables
- Una variable no es algo muy diferente de lo que
hemos aprendido en matemáticas. Pensemos en las
siguientes operaciones - El largo de la parcela es 60 metros
- El ancho de la parcela es 70 metros
- El área es el producto del ancho por el largo
4200 - Por qué son necesarias las variables?
- Porque necesitamos etiquetas o identificadores
para cosas tales como ancho, largo, etc. - Porque necesitamos almacenar datos asociados a
dichos identificadores (60, 70, 4200) - Un ejemplo en Java
- public static void main(String args)
- System.out.println( "Ha entrado en la
aplicación") - float largo
- float ancho
- float area
- largo 60
- ancho 70
- area ancho largo // Cómo visualizar
el área de la parcela -
5Variables las reglas básicas
- Regla básica toda variable debe ser declarada
antes de ser utilizada - En el formato de la declaración hay que tener en
cuenta - Lo básico, especificar
- El tipo de dato
- El nombre o identificador de la variable
- Lo opcional es
- Dar valor a la variable por primera vez
(inicializar) - Declarar otras variables en la misma línea (ojo
del mismo tipo) - Formato
- Tipo nombre valor , nombre valor ...
- Ejemplos
- int alto, ancho 0, edad
- char x s, b
- El programador tiene completa libertad a la hora
de dar nombre a una variable. Por ejemplo, no
hay obligación de llamar a las variables enteras
con nombres como número, entero, etc. - Lo mejor a la hora de dar un nombre es dejarse
llevar por el sentido común claridad, es decir,
tratar de ser significativo sin alargarse en
exceso. Por ejemplo, el nombre edad es más
significativo que usar simplemente e. La
costumbre de dar nombres no significativos es uno
de los vicios que conduce a crear código
solipsista sólo lo comprende el programador
que lo creó (siempre que no haya pasado mucho
tiempo, en cuyo caso lo normal es que no lo
comprenda ni la persona que lo hizo)
6Los tipos de datos enteros y coma flotante
- Del mismo modo que existen diferentes tipos de
vehículos existen diferentes tipos de variables - El tamaño en bits, a diferencia de C/C, es
fijo, es decir, no varía en función de la
máquina. Esto facilita la portabilidad - Enteros
- byte 8 bits (-128 a 127)
- short 16 bits (-32.768 a 32.767)
- int 32 bits (-2.147.483.648 a 2.147.483.647)
- long 64 bits (/- 9x1018)
- En coma flotante, también llamados reales. Se
utilizan cuando se precisan posiciones decimales - float 32 bits (3.4e-038 a 3.4e038)
- double 64 bits (1.7e-308 a 1.7e308)
7Elegir un tipo de datos
- En principio parece que lo más fácil sería
trabajar con un único tipo de dato. Parece
lógico tener diferentes tipos de datos? - La respuesta más sencilla es responder con una
pregunta parece sensato tener el mismo tipo de
vehículo para transportar 5 personas, transportar
3 toneladas de carga o para llevar a 55 personas? - Tenemos diferentes tipos de datos con la
finalidad de optimizar. Del mismo modo que no es
sensato usar el motor de un autobus para un
turismo, no es sensato emplear 64 bits si
queremos contar del 1 al 10 - Por tanto, parece que el primer criterio para
elegir el tipo es la optimización no malgastar
memoria. Pero hay un criterio más importante, el
sentido común, que nos indica que resulta
prudente actuar con holgura. De hecho, en nuestra
vida cotidiana no llevamos nuestros coches
siempre llenos y perfectamente optimizados. Sino
que con frecuencia, transportan menos personas
que su límite máximo
8Un ejemplo con double
- Un ejemplo para calcular el área de un círculo
(PIr2) - public class j01_radio
- public static void main(String args) throws
IOException -
- double PI 3.1416
- double radio 3.2, area
-
- area radio radio PI // Calculo el área
- System.out.println( "El área es " area)
-
-
- Ejercicio hacer un programa que calcule volumen
de un contenedor a partir de su largo, ancho y
altura (pueden admitir dos decimales).
9Booleanos
- Es un tipo de dato propio de una lógica binaria
sólo tiene como valores true o false. - int edad 0
- boolean mayor_de_edad false
- edad 18
- mayor_de_edad true
- Es el tipo utilizado para evaluar los
condicionales - int edad 0
- boolean mayor_de_edad false
- if (edad gt 18) // Si es verdad que la edad es gt
ó que 18 - mayor_de_edad true // entonces es mayor de
edad - if (mayor_de_edad true) // Si es verdad que es
mayor de edad ... - System.out.println( Puede obtener el carnet B1
) - El último condicional se puede escribir de manara
más cómoda (y más usual) - if (mayor_de_edad) // Si es verdad que es mayor
de edad ... - System.out.println( Puede obtener el carnet B1
)
10Caracteres (char)
- En Java los caracteres se almacenan en variables
de 16 bits. Se utiliza un formato estándar e
internacional denominado Unicode que admite
65.537 caracteres, de esta forma podemos utilizar
desde el latín hasta el arábigo. Unicode es el
formato más utilizado en Internet. - En el siguiente ejemplo cambiamos el valor de una
variable char - char cuadricula A
- System.out.println( La cuadrícula del mapa es
cuadricula ) - cuadricula b
- System.out.println( La cuadrícula del mapa es
cuadricula ) - El siguiente ejemplo nos muestra como funciona
internamente el ordenador asocia a cada carácter
un número. Puesto que con 16 bits podemos
representar números enteros de 0 a 65.536,
entonces podemos representar 65.537 caracteres.
En nuestro ejemplo asociamos a un char el número
126, que se representa en formato de carácter
como - char a 126
- System.out.println( El carácter es a )
- Observar que una cadenas de caracteres (String)
se delimita por comillas dobles y los caracteres
aislados (char) se delimitan por comillas
simples.
11String
- String no es un tipo simple (como float, char,
etc.), sino una clase que nos ayuda a manejar de
forma sencilla cadenas de caracteres. - Ejemplos de instancias
- String j Hola mundo
- String k new String( Hola mundo )
- Podemos concatenar cadenas
- String k "Hola, String m "Adios"
- String h "Saludos " k " y " m
- System.out.println( h )
- Podemos saber su ancho
- String k Antonio
- System.out.println( k.length() )
- Mediante compareTo() podemos ordenar diferentes
cadenas (ver más adelante) - Conversión de númerico a cadena mediante el
método static valueOf() - int anio 1999
- String p String.valueOf( anio)
- System.out.println( p )
- La conversión inversa se hace con métodos static
que están en las clases Double, Float, etc - radio Double.parseDouble( cadena ) //
Convierto el String en double - Se puede acceder a un carácter de la cadena
12Ámbito de vida
- El ámbito de una variable u objeto es el espacio
del programa en el que esa variable existe. Por
ello, se habla de ámbito de vida - De forma general (hay excepciones que veremos más
adelante), la vida de una variable comienza con
su declaración y termina en el bloque en el que
fue declarada (los bloques de código se delimitan
por llaves ). Por ejemplo, cuál es el ámbito
de la variable radio y del vector args? - public static void main(String args)
-
- double PI 3.1416
- double radio 3
- System.out.println( El área es
(PIradioradio) ) -
- Más adelante profundizaremos en los diferentes
tipos de ámbito
13Conversión de tipos
- Hemos visto que los datos tienen un tipo. Pero en
ocasiones nos conviene convertir un dato de su
tipo original a otro - Tipos de conversión
- Automática o implícita. El tipo destino es más
grande (mayor número de bits) que el tipo origen
(ensanchamiento o promoción) - int Origen 65
- float Destino 4.35f
- Destino Origen // Cuál es el valor de
Destino? - También hay conversión automática ante tipos
compatibles. Por ejemplo, la asignación de un int
a un char que vimos anteriormente - Explicita. La conversión se produce cuando el
tipo destino es más pequeño que el origen
(estrechamiento). Para ello debemos realizar un
moldeado (cast) - double Origen 65.13
- int Destino 4
- Destino (int) Origen // Cuál es el valor de
Destino? - La conversión por medio de métodos es en realidad
una aplicación de los tipos de conversión
anteriores. Para ver ejemplos (transparencia
dedicada a la clase String) - String p String.valueOf( anio)
- double radio Double.parseDouble( cadena )
14Comprender la conversión de tipos
- Supongamos que tenemos en una variable (int) el
precio de un producto. Queremos incrementarlo en
un 20 - int precio 10000
- precio precio 1.2
- Este código parece correcto, sin embargo el
compilador nos informa de un error Error num.
355 puede perderse precisión double, hacía
falta int. Cuál es la razón? Para entenderlo,
conviene comprender como trabaja el ordenador - El ordenador trata de realizar el producto
(precio1.2) entre un int y un double (1.2), para
lo cual el ordenador convierte de forma
automática el int en un double. Hasta aquí todo
va bien, el resultado de multiplicar dos números
double es un double
precio precio 1.2
(int)
(double)
(conversión automática a double)
(double)
- El problema viene a continuación no hay
conversión automática de un double (el resultado
del producto) a un int (la variable a la
izquierda del operador ) - Para que se produzca esta conversión es necesario
realizar un moldeado (cast) - precio (int) (precio 1.2) // Esto si es
correcto
15Matrices (I)
- Una matriz es un conjunto ordenado de variables u
objetos, con las siguientes características - Tienen el mismo tipo
- Tienen el mismo nombre (aunque hay casos poco
usuales de matrices anónimas) - Si tienen el mismo nombre, cómo se diferencia un
elemento de otro? La respuesta es por el índice - Formatos
- Con new Tipo nombre new tipotamaño
- Sin new Tipo nombre x, y, ...
- Un ejemplo
- int m new int3
- m0 5
- m1 9
- m2 2
- System.out.println( m1 )
-
Matriz
Valor
5
9
2
Posición
0
1
2
16Matrices (II)
- Un ejemplo en el que incremento en un 50 el
tercer elemento de la matriz - public static void main(String args)
- int depositos
- int num_depositos 4
- depositos new intnum_depositos // Igual
que int depositos new int4 - depositos0 depositos1 300
- depositos2 depositos3 700
- System.out.println( "Litros del segundo
deposito" depositos1) - depositos2 (int) (depositos2 1.5)
// Incremento de un 50 - System.out.println( "Litros del tercer
deposito" depositos2) -
- Por qué necesito hacer casting?
-
17Matrices (III)
- Es importante destacar una diferencia a la hora
de crear una matriz - Si trabajamos con tipos simples (int, char,
float, double, etc.) tenemos que usar el operador
new una vez, al crear la matriz - int botes new botes4
- Botes0 325
- Si trabajamos con tipos compuestos (todos los
demás, es decir, clases de Java como String, o
cualquier otra creada por el programador),
entonces hay que usar dos veces dicho operador
una al crear la matriz y luego tantas veces como
objetos queramos almacenar en ella - public static void main(String args)
- Vehiculo mios new Vehiculo2
- mios0 new vehiculo()
- mios1 new vehiculo()
- mios0.definir_precio_bajo()
- mios1.definir_precio_bajo()
- mios1.mostrar()
-
Vehiculo.java package xxx public class
Vehiculo private int precio void
definir_precio_bajo() precio 12000
void mostrar() System.out.println( "
Precio" precio)
18Matrices (IV)
- Para obtener el ancho de una matriz
Nombre.length. Ejemplo - String nombres new String3
- nombres0 new String(Antonio)
- System.out.println( nombres.length ) // Muestra
el número 3 - En comparación con C/C la copia de matrices
completas resulta muy sencilla - int Origen 200, 400, 600
- int Destino 10, 20, 30
- Destino Origen
- System.out.println( Destino0 )
- System.out.println( Destino1 )
- Al intentar acceder a un elemento que está fuera
del rango de la matriz se genera un
ArrayIndexOutOfBoundsException
200 400
19Matrices multidimensionales
- Utilizamos una pareja de corchetes () para cada
dimensión. En el caso de una matriz bidimensional
un ejemplo sería - int Lista new intfilascolumnas
- Java le permite no tener que especificar todas
las dimensiones al principio (con el primer new).
Al menos tiene que especificar la dimensión más
significativa (más a la izquierda). Además puede
hacer que las dimensiones siguientes (menos
significativas) difieran. El siguiente ejemplo
crea una matriz en la que la primera fila tiene
tres columnas y la segunda fila tiene cinco - int M new int2
- M0 new int3
- M1 new int5
20Operadores aritméticos
- Suma
- Resta -
- Producto
- División /
- Módulo (se puede aplicar a coma flotante y a
int) - Incremento (a es equivalente a aa1)
- Decremento -- (a-- es equivalente a aa-1)
- Suma y asignación (a3 es equivalente a
aa3) - Resta y asignación - (a-3 es equivalente a
aa-3)
21Operadores relacionales
- El resultado de los operadores relacionales es un
valor boolean (true o false) - Igual a (no confundirlo con el operador de
asignación) - Distinto de !
- Mayor que, mayor o igual gt, gt
- Menor que, menor o igual lt, lt
- Ejemplo 1
- int a 5, b 2
- boolean c a gt b
- Ejemplo 2
- float a 3
- if (a 3)
- System.out.println( El valor es a)
22Qué ocurre con String?
- A menudo necesitamos comparar cadenas de
caracteres, para saber si una es
lexicográficamente igual, mayor o menor que otra.
El ejemplo típico es ordenar una lista de nombres - Ya sabemos que String no es un tipo simple, sino
que es una clase. Para ayudarnos en la
comparación tenemos los métodos compareTo y
compareToIgnoreCase. Podemos saber el orden de
las cadenas en función de lo que devuelvan los
métodos - String j "Belén", k "Susana", m
"Belén", n "Antonio" - if (j.compareTo(m) 0)
- System.out.println( j " es igual a "
m) - if (j.compareTo(k) lt 0)
- System.out.println( j " es menor que "
k) - if (j.compareTo(n) gt 0)
- System.out.println( j " es mayor que "
n) - Existe también el método equals( String ), que
devuelve true si las cadenas son iguales. Hay
otra versión equalsIgnoreCase(String)
Belén es igual a Belén Belén es menor que
Susana Belén es mayor que Antonio
23Operadores lógicos
- Operan solamente con valores booleanos
- Conjunción (Y)
- Disyunción inclusiva (O)
- Negación !
- Ejemplo
- int edad 17
- float nota 6f
- boolean mayoria_edad edad gt 18
- if (mayoria_edad nota gt 5)
- System.out.println( "aprobado" )
- if (!mayoria_edad)
- System.out.println( "Le falta(n) "
(18-edad) " año(s)" )
24Entradas y Salidas básicas
25Streams (I)
- Cualquier programa realizado en Java que necesite
llevar a cabo una operación de I/O lo hará a
través de un stream. - Un stream, cuya traducción literal es "flujo", es
una abstracción de todo aquello que permite
introducir o extraer información. Así, un stream
de teclado es un flujo de entrada para el
programa y un stream de pantalla es un flujo de
salida del programa
Input Teclado
Output Pantalla
- La vinculación de este stream al dispositivo
físico (teclado, pantalla, impresora, etc.) la
hace el sistema de entrada y salida de Java.
26Streams (II)
- El paquete System define tres clases
- in (entrada estándar)
- out (salida estándar)
- err (salida de errores estándar)
- La escritura hacia pantalla se hace con
System.out - System.out.println(Hola Mundo) // Añade nueva
línea al final - System.out.print(Adios) // NO añade
nueva línea al final - La lectura desde teclado se hace con System.in
27Stream de entrada por teclado
- Para manejar entradas por teclado tenemos que
crear un BufferedReader a partir de System.in - import java.io.
- public class inicio
- public static void main(String args) throws
IOException - String cadena
- BufferedReader entrada
- entrada new BufferedReader(new
InputStreamReader(System.in)) // Crear objeto de
entrada - System.out.println("Escribe tu nombre")
- cadena entrada.readLine() //leemos cadena de
caracteres mediante readLine() -
-
- Condiciones previas a la creación de un
BufferedReader - Tengo que importar las clases que uso
(BufferedReader y InputStreamReader), que están
en el paquete java.io, por medio de import. - Tengo que poner throws IOException en la
función que usa BufferedReader (ya se explicará
más adelante el manejo de excepciones). - Una vez creado el objeto de entrada para teclado,
mediante BufferedReader, puedo leer la entrada
por teclado mediante una llamada a
objeto.readLine() (la entrada termina al pulsar
Enter). No olvidar que esta función devuelve un
String, es decir, cualquier cosa que el usuario
teclea se almacena como una cadena, sea pedro o
3420. Java es un lenguaje fuertemente tipado y
si queremos que lo tecleado se convierta en un
número habrá que hacer posteriormente una
conversión mediante métodos, como veremos en el
siguiente ejemplo.
28Un ejemplo entrada por teclado y conversión
- public static void main(String args) throws
IOException - double PI 3.1416, radio
- int area_int
- String c
- / Creo el objeto 'entrada', es un lector de
entradas por teclado / - BufferedReader entrada new BufferedReader( new
InputStreamReader(System.in)) - System.out.print( "Escriba el radio " )
- c entrada.readLine() // Leo un String de
la entrada de teclado - radio Double.parseDouble( c ) // Convierto
el String en double radio - System.out.println( "El área es " radio
radio PI) - area_int (int) (radio radio PI) //
Calculo el área entera del círculo. Hago casting - System.out.println( "El área (entera) es "
area_int) -
- Desde un String existen conversiones a otros
tipos Integer.parseInt( cadena ) o
Float.parseFloat( cadena). La conversión inversa
utiliza String.valueOf( numero).
29Sentencias de control
30Introducción
- Las sentencias de control nos ayudan a que el
flujo de ejecución del programa deje de tener un
carácter lineal. - Ejemplos de sentencias de control en la vida
cotidiana - Ejemplo 1
- Si el cheque es correcto y hay fondos
- Entonces pagar
- Si no
- No pagar
- Ejemplo 2
- Mientras la salsa no este densa
- Calentar y remover
- Ejemplo 3
- Siga adelante
- Cuando llegue a la plaza
- Si es hora punta
- Entonces tuerza a la derecha
- Si no
- Siga todo recto
- Vamos a ver los siguientes tipos de sentencias de
control - Selección
31if / else (I)
- La sentencia básica para realizar bifurcaciones o
ramificaciones. Formato - if (condición)
- sentencia 1
- else
- sentencia 2
- La condición es una expresión booleana. Si es
true, se hace la sentencia 1 si es false, se
hace la sentencia 2 (si existiese) - Ejemplo
- int a 3, b 9, c
- if (a lt b a ! 0)
- c b a
- else
- c a b
Precaución La tabulación es fundamental para
realizar código legible
32if / else (II)
- Si hay más de una sentencia debemos delimitar los
bloques por llaves . En el siguiente ejemplo
vamos a determinar las ventajas que tiene un
cliente en función de los puntos de su tarjeta de
compra - if (puntos gt 1000)
- tipo_cliente "VIP"
- descuento 0.05f
-
- else
- tipo_cliente "Normal"
- descuento 0.02f
-
- System.out.println( "Tipo " tipo_cliente
"\tDescuento " descuento100 "") - Los condicionales pueden ser anidados, es decir,
que uno este dentro de otro. En nuestro ejemplo
vamos a añadir otra condición para los clientes
de más de 1000 puntos, si su antigüedad es mayor
de 1825 días, les haremos un descuento del 6 - if (puntos gt 1000)
- tipo_cliente "VIP"
- descuento 0.05f
- if (antiguedad gt 1825)
- descuento 0.06f
33switch
- Formato
- switch ( expresión ) // expresión no tiene
que ser booleano - case constante1
- secuencia de sentencias
- break
- case constante2
- secuencia de sentencias
- break
- ...
- default
- secuencia de sentencias
-
- No olvidar break. Pero a veces es adecuado
omitirlo - switch ( categoria )
- case 1
- case 2
- porcen 0.2 // Tanto para 1 como para 2
- break
34while
- Formato
- while (condición)
- Sentencia
- La sentencia puede ser un bloque delimitado por
llaves (). El bucle se realiza mientras la
condición sea cierta - Ejemplo en el que modificamos un vector de
números, de tal modo que ponemos el cuadrado del
número que antes estuviese - double serie 23, 4, 36, 9
- int i 0
- while ( i lt serie.length )
- System.out.print( "Posición " i "\t
Anterior " seriei ) - seriei seriei seriei
- System.out.println( "\t Cuadrado "
seriei ) - i
-
Bucle
Posición 0 Anterior 23.0 Cuadrado
529.0 Posición 1 Anterior 4.0 Cuadrado
16.0 Posición 2 Anterior 36.0 Cuadrado
1296.0 Posición 3 Anterior 9.0 Cuadrado 81.0
35for (I)
- En la vida cotidiana hay numerosos casos de
iteraciones (repeticiones). Por ejemplo, si
alguien tiene que asignar un número a las cinco
personas que hay en una habitación haría algo
así - for (el número es 1 mientras que el número sea lt
6 incremento el número) - Digo en voz alta el número, señalando a la
persona correspondiente - De forma semejante, el formato de for es
- for ( inicialización condición variación )
- Sentencia
- Con un ejemplo puede aclararse. Supongamos que
queremos mostrar por pantalla los cuatro primeros
números enteros, empezando por el 3 - La inicialización sería empezar con el número 3
- Condición mientras que el número sea menor que 7
(es aquello que debe cumplirse para poder volver
a repetir la sentencia) - Variación incrementar en uno el número
- Sentencia (aquello que se debe iterar o repetir,
en nuestro ejemplo 4 veces) mostrar el número
por pantalla - Ejemplo
- int i
- for ( i 3 i lt 7 i)
- System.out.println( i )
- Nos podemos saltar la inicialización (empieza en
el valor previo) - int i 3
- for ( i lt 7 i)
- System.out.println( i )
36for (II)
- Vamos a ver paso a paso como actua la iteración
- Ejemplo
- int i
- for ( i 1 i lt 3 i)
- System.out.println( i )
- Al observar la ejecución paso a paso es
importante recordar - Siempre se evalúa la condición ANTES de ejecutar
la sentencia - DESPUÉS de la sentencia siempre se realiza la
variación - Se pueden iterar varias variables, para lo cual
necesitamos comas for(i0, k5 i lt 5 i,
kk5)
- INICIO la variable i se inicia a 1
- CONDICIÓN se comprueba la condición ilt3 ? SI
- SENTENCIA se ejecuta la sentencia println
- VARIACIÓN al terminar el bucle, se incrementa i.
Ahora vale 2 - CONDICIÓN se comprueba la condición ilt3 ? SI
- SENTENCIA se ejecuta la sentencia println
- VARIACIÓN al terminar el bucle, se incrementa i.
Ahora vale 3 - CONDICIÓN se comprueba la condición ilt3 ? NO,
fin del bucle - IMPORTANTE al salir del bucle el valor de i es
3. Cuál sería su valor si la condición fuese
ilt3?
37for (III)
- Igual que los casos anteriores utilizan para
acotar conjuntos de sentencias y además son
anidables. - Ejemplo en el que se calcula la media y el máximo
de un vector de números - public static void main(String args)
- float serie -8, -12, -4, -14
- float media, sumatorio 0
- int contador
- float maximo serie0 // Funcionaria si
asignamos el 0? - / Hallamos el máximo y sumamos todos los
números / - for ( contador 0 contador lt serie.length
contador ) - if (seriecontador gt maximo)
- maximo seriecontador
- sumatorio sumatorio seriecontador
-
- / Calculamos media. Mostramos la media y
el maximo / - media sumatorio / contador
- System.out.println( "La media es " media
" y el max es " maximo) -
- Se pueden clasificar las variables en virtud de
su función o uso (hasta ahora las hemos
clasificado en virtud del tipo de dato). Entre
estos tipos de usos hay dos que son muy comunes y
aparecen en nuestro ejemplo
38do-while
- Formato
- do
- Sentencia
- while (condición)
- A diferencia de while, analiza la condición al
final del bucle. Por tanto, la sentencia se
realiza al menos una vez - Ejemplo. Qué hace?
- int i 1
- do
- System.out.println( iii )
- i
- while ( i lt 3 )
- do-while es muy útil en la gestión de menús. El
diseño sería - do
- Muestro las opciones de menú
- Solicito la opción por teclado
- switch (opcion)
- En función de la opción elegida realizo una u
otra acción -
- while (la opción no sea Salir)
39Calculadora
- public static void main(String args) throws
IOException - char opcion
- String cadenaTeclado
- double operando1 0, operando2 0
- / Creo el obj. 'entrada', es un lector de
entradas por teclado / - BufferedReader entrada new BufferedReader(
new InputStreamReader(System.in)) - do
- / Mostrar menu y pedir opcion por
teclado / - System.out.print("\r\n S - Suma\r\n R -
Resta\r\n P - Producto" "\r\n D - División\r\n
Q - Salir\r\n Su opción") - cadenaTeclado entrada.readLine()
// Teclado - opcion cadenaTeclado.charAt( 0 )
// Conv a char - / Si la opción no es salir,
solicito operandos / - if ( opcion ! 'Q' opcion ! 'q')
- System.out.print( "Número 1 " )
- cadenaTeclado entrada.readLine()
// Teclado - operando1 Double.parseDouble(
cadenaTeclado ) // Conv - System.out.print( "Número 2 " )
/ En función de la opción opero o
salgo / switch (opcion) case
's' case 'S'
System.out.print( operando1 operando2 )
break case 'r' case 'R'
System.out.print( operando1 - operando2 )
break case 'p' case
'P' System.out.print( operando1
operando2 ) break case 'd'
case 'D' System.out.print(
operando1 / operando2 ) break
case 'q' case 'Q'
System.out.print( "Adios" ) break
default System.out.print( "Opción
no disponible" ) //////////////////////
///////// Fin de switch while (opcion !
'Q' opcion ! 'q') /////////////////////
/////////// Fin de función
40Salto
- Hay sentencias que controlan el flujo de
ejecución, de tal forma que realizan saltos fuera
del bloque en el que se encuentran - break salta fuera del bucle o switch
- return salta fuera del método
- Un ejemplo con break. Busca un nombre en una
lista y, si lo encuentra, sale del bucle - private static void funcion()
- int i 0
- String nombre "Ana", "Belen", "Juan",
"Pedro" - String nombrBuscado Belen"
- boolean encontrado false
- while (i lt nombre.length)
- if (nombrei.equals(nombreBuscado))
- System.out.println(nombre_buscado "
está en la posición " i) - encontrado true
- break
-
- i
-
- if (!encontrado)
41Clases
42Introducción (I)
- Hasta ahora las clases las hemos usado como
soporte al método main. A partir de aquí vamos a
adentrarnos en el manejo de clases - Una clase puede entenderse como un modelo o
patrón la representación abstracta de un
conjunto - Un conjunto en la vida cotidiana puede ser
definido por sus atributos y/o por acciones
(comportamiento). Por ejemplo - El conjunto de los mamíferos con aletas
- El conjunto de los profesionales en extinción del
fuego - Un bombero en concreto sería una instancia del
conjunto de los bomberos - Cuando definimos el conjunto de los bomberos no
hacemos referencia a ningún bombero en concreto,
de la misma manera, cuando definimos una clase no
hacemos referencia ni creamos un objeto o
instancia de la clase
43Introducción (II)
- Del mismo modo que ocurre con los conjuntos de la
vida cotidiana, las clases se definen por sus
atributos y/o métodos (funciones que definen el
comportamiento de la clase). Por ahora vamos a
empezar con los atributos. - Veamos el siguiente ejemplo en el que la clase
Inicio hace una instancia de la clase Circulo - Creamos la clase Circulo. Es importante entender
que la sentencia Circulo a NO CREA un objeto,
sino que crea una referencia o etiqueta (vacía o
nula). Por ello, si queremos acceder al atributo
radio para asignarle un valor (23), el
compilador nos dará un mensaje de error. SOLO se
crea un objeto si se utiliza new. Lo correcto
sería - Circulo a
- a new Circulo() // O bien Circulo a new
Circulo() - a.radio 23
/ Circulo.java / package
figuras.dominio public class Circulo public
double radio public double PI 3.1416
/ Inicio.java / package
figuras.inicio import figuras.dominio.Circulo p
ublic class Inicio public static void
main(String args) Circulo a //
ERROR a.radio 23
44Introducción (III)
- El error anterior era un error en tiempo de
compilación. La mayor parte de IDEs nos darán un
mensaje del estilo variable no inicializada
antes de compilar, es decir, el entorno de
desarrollo ha detectado que no hay un objeto, que
la etiqueta no hace referencia a un objeto. - Podemos engañar a la mayor parte de los IDEs
con el siguiente código, que se puede compilar
sin errores - Circulo a null
- a.radio 23 // Línea número 7
- Decimos engañar ya que este código hará que el
IDE no nos muestre el error en tiempo de
compilación. Pero el problema es el mismo no hay
objeto para la etiqueta a. - El error surge en tiempo de ejecución
- java.lang.NullPointerException at
figuras.inicio.Inicio.main(Inicio.java7) - Este es el error más frecuente en programación
Java (y en otros lenguajes como C/C) y siempre
indica lo mismo tratamos de acceder a un
atributo o método del objeto, pero ocurre que no
hay objeto
45Introducción (IV)
- Una clase es un patrón o modelo, no crea un
objeto. Se crea un objeto con new - Cada objeto tiene sus atributos o variables
miembro (hay una excepción a esta regla los
atributos static). - En el siguiente ejemplo, el primer círculo tiene
un atributo radio que es diferente al mismo
atributo del segundo círculo. Es más, ocupan
posiciones de memoría diferentes - public static void main(String args)
- Circulo a new Circulo()
- Circulo b new Circulo()
- a.radio 23
- b.radio 35.6
-
46El primer método
- Vamos a introducir un método en nuestra clase
Circulo, que simplemente muestra el área - Una llamada al método implica un SALTO el
ordenador pasa a ejecutar el código del método y
una vez que este termina se devuelve el control a
main - Las flechas muestran los saltos que da el control
de ejecución del programa - El método muestra los atributos de SU OBJETO
public class Circulo public double radio
public double PI 3.1416 public void
mostrarArea() System.out.println(
radioradioPI )
public class Inicio public static void
main(String args) Circulo a new
Circulo() Circulo b new Circulo()
a.radio 23 b.radio 35.6
a.mostrarArea() b.mostrarArea()
47Formato de los métodos
- El formato de los métodos es
- Tipo_acceso tipo_devuelto Nombre_método(
parámetros ) - Cuerpo del método
-
- El tipo de acceso puede ser
- Para clases que están en el mismo paquete (por
defecto public) - public se puede llamar al método desde fuera de
la clase - protected se puede llamar al método desde fuera
de la clase - private no se accede desde fuera de la clase
- Para clases que están en diferentes paquetes (por
defecto protected) - public se puede llamar al método desde fuera de
la clase - protected no se accede desde fuera de la clase
- private no se accede desde fuera de la clase
- El tipo devuelto es el tipo de dato que
devuelve el método
48Devolviendo valores
- En nuestro ejemplo calculamos el área en println,
pero esto no es muy inteligente. Ya que si
necesitamos de nuevo el área, tenemos que volver
a calcularla. Lo lógico es realizar el cálculo EN
UN ÚNICO MÉTODO y que este método devuelva el
resultado. En el siguiente ejemplo vamos a crear
un método público que devuelve el área - public class Circulo
- public double radio
- public double PI 3.1416
- public void mostrarArea()
- System.out.println( getArea() )
-
- public double getArea()
- return radioradioPI
-
-
- La flecha muestra como se transfiere el control
de ejecución. La sentencia return es una orden de
salto. - Error de principiante no hay coherencia entre el
tipo que declaramos que vamos a devolver y el
tipo efectivamente devuelto. En nuestro ejemplo
hay coherencia - Declaramos que vamos a devolver double al
escribir public double obtener_area() ... - Efectivamente devolvemos double, el resultado de
multiplicar variables de tipo double como radio y
PI
49Introducción a los parámetros
- Veamos el siguiente ejemplo de función que
calcula y devuelve el cuadrado de un número - double cuadrado()
- return 55
-
- Esto es evidentemente un absurdo, sólo nos sirve
si el número es 5. Resulta más lógico que el
método calcule con independencia de cual es el
número base. Para ello, el método debe tener
parámetros - public class Param
- public static void main(String args)
- double h cuadrado(3) // Argumentos
- System.out.println( h )
-
- / Devuelve el cuadrado /
- public static double cuadrado( double base )
// Parámetros - return ( base base )
-
El parámetro base recibe el argumento 3
50Parámetros los nombres son lo de menos
- El principiante poco informado puede pensar que
los nombres de los parámetros dependen de los
nombres de los argumentos. Puede creer que si el
argumento se llama X, el parámetro debe
llamarse X - public static void main(String args)
- double largo 3, ancho 2
- double h getArea( largo, ancho)
- System.out.println( h )
-
- public static double getArea(double largo, double
ancho) - return (largo ancho)
-
- Este personaje desconoce que los nombres son
indiferentes, lo que importa es que el parámetro,
se llame como se llame, recibe el contenido del
argumento (más adelante distinguiremos llamadas
por valor de llamadas por referencia). La aprueba
es que el método anterior actúa igual si se
escribiese así - public static double getArea(double PinPanPun,
double segundo) - return (PinPanPun segundo)
-
51Una pequeña excepción a la regla anterior
- Hemos visto que los nombres son lo de menos en el
ejemplo de las variables ancho y largo (no
hay conflicto porque tienen ámbitos de vida
independientes) - Bien, pero la excepción es salvo cuando hay
conflicto de nombres con un atributo de la
clase, aquí hay conflicto con los ámbitos de
vida. Supongamos que usamos de parámetros para
almacenar los valores en atributos de un objeto - public class Camino
- private double largo
- public void setLargo( double largo )
largo largo -
- Esto es un error absurdo almacenamos el valor de
la variable parámetro largo en ella misma (no
en el atributo). Con el agravante de que ese
valor se pierde al terminar el método. - Lo que queremos es almacenar el valor en el
atributo, para lo cual usaremos la palabra
reservada this - public void setLargo( double largo )
this.largo largo - this es una forma de hacer referencia al
objeto, es la forma que tiene el propio objeto de
decir yo. Este nombre se usa para hacer
referencia a atributos o métodos del objeto.
Resumiendo, en nuestro ejemplo - this.largo variable atributo de la clase
- largo variable parámetro
- Volveremos más adelante sobre this y veremos
por qué es incompatible con su uso dentro de
métodos static
52Parámetros encapsulando
- En nuestro ejemplo del círculo podemos acceder a
los atributos de Circulo directamente desde
fuera de la clase - Circulo a new Circulo()
- a.radio 3
- Cambiemos de forma de trabajar. Vamos a hacer que
sólo se pueda acceder a los datos por medio de
los métodos. Esto implica que debemos poner
métodos que devuelvan valores (usan return, get)
y otros que asignen valores (usan parámetros,
set) - public class Circulo
- private double radio
- private double PI 3.1416
- public double getArea()
- return radio radio PI
-
- public void setRadio(double nuevoRadio)
- radio nuevoRadio
-
- public double getRadio()
- return radio
-
- Reglas importantes
- Encapsular desde fuera de la clase sólo se
accede a los métodos públicos. No se accede
directamente a los datos - Modularizar separar procesamiento de datos de su
presentación. Un ejemplo es que los cálculos se
hacen en métodos diferentes a la presentación de
datos (incluso, lo que es aún mejor, en clases
diferentes). También es una forma de hacer
software cohesivo
53Encapsular
- En la ingeniería del software se especifican
reglas que deben seguirse para ayudarnos a
realizar software robusto (no proclive a fallos),
fácilmente entendible y de fácil mantenimiento
(modificaciones poco costosas) - El principio de Encapsulamiento (ocultamiento
de información) nos indica (entre otras cosas)
que debemos hacer que los detalles de la clase
estén ocultos para el exterior (también se
denomina implementación encapsulada). Una
aplicación de este principio implica que los
atributos serán privados y sólo se puede acceder
a ellos desde los métodos de la clase - Ventaja desde el código de la clase controlamos
el acceso a los atributos. En caso de fallo o
modificación del código, el programador comprueba
los métodos de la clase y no tiene que revisar
todo el código de los otros archivos - Los métodos públicos son el intermediario entre
los datos y los otros objetos
Los métodos públicos de la clase son el interfaz
de la clase
54Un ejemplo de encapsulamiento
- Supongamos que tenemos una clase que representa
los productos de un comercio, en el que hay un
precio normal y un precio rebajado - public class Producto
- private float precio
- private float precioRebajado
-
- public void setPrecioRebajado( float
porcentajeRebaja ) - precioRebajado precio
(1-porcentajeRebaja) -
-
-
- Por qué decimos que es una implementación
encapsulada? Por dos razones ligadas - Encapsular datos sólo se accede al atributo
privado precioRebajado por medio de un método
público de la clase - Encapsulamos el cálculo la forma de calcular el
dato queda oculta al exterior de la clase.
Supongamos que debemos cambiar la forma de
calcular el precio rebajado (bien por corregir un
error de programación o bien por cambiar la
política de rebajas), entonces sólo tendremos que
cambiar el método setPrecioRebajado().
55Un ejemplo de NO encapsulamiento
- Tomemos el ejemplo anterior y supongamos que la
clase es así - public class Producto
- public float precio
- public float precioRebajado
-
- Estoy permitiendo el acceso externo a los datos
del producto. Por tanto en una clase externa se
podría escribir algo como esto - static public void main()
- Producto a new Producto()
- a.precio 25.5
- a.precioRebajado a.precio 0.80
-
- Producto b new Producto()
- b.precio 19
- b.precioRebajado b.precio 0.80
-
- La irracionalidad suele ser costosa. Si tenemos
que cambiar nuestra política de rebajas tendremos
que cambiar todas las líneas de código donde
calculamos el precio rebajado para cada producto,
en una implementación encapsulada sólo tenemos
que cambiar el método setPrecioRebajado() de la
clase Producto - En una implementación encapsulada tendríamos que
modificar un bloque de código, no N bloques de
código.
56Modularizar
- Un diseño modular se basa en la conocida
estrategia de divide y vencerás. Descomponer de
forma lógica la aplicación - Para conseguir la modularidad debemos hacer que
nuestros componentes de software sean
especialistas - En un ejemplo básico y típico separaremos
- Inicio de aplicación paquete y clase donde está
main() - Clases del dominio de problema por ejemplo,
paquete figuras.dominio con las clases Circulo,
Rectangulo, etc - Clases de presentación paquete para el interfaz
de la aplicación (menú de opciones, presentación
de clases de dominio, etc.) - Clases para persistencia o almacenamiento en base
de datos, archivos, etc.
57Un ejemplo de modularización
- En el siguiente ejemplo separamos las clases del
dominio (en este caso Circulo.java) de la clase
responsable de la presentación
package figuras.dominio public class Circulo
private double radio private double PI
3.1416 public Circulo() public
Circulo( double nuevoRadio ) setRadio(
nuevoRadio ) public double getArea()
return radio radio PI
public void setRadio( double radio )
this.radio radio public double
getRadio() return radio
public String toString() return "Radio
" radio " Area " getArea()
package figuras.presentacion import
figuras.dominio. public class VistaFiguras
public static void mostrar( Circulo cir )
System.out.println( cir.toString() )
public static void mostrar( Rectangulo rec
) System.out.println( rec.toString()
)
Cómo se haría un main() que use estas clases?
58Constructores
- Un constructor es un método al que se llama
cuando se crea un objeto con new - Sólo son llamados inmediatamente después de la
creación del objeto - Tienen el mismo nombre que la clase y no
devuelven valores - Son públicos
- En nuestro ejemplo vamos a crear un constructor
que inicia el radio con 1 - Circulo()
- radio 1
-
- Pero en muchas ocasiones al crear un objeto nos
interesa inicializar atributos (en nuestro caso
el radio). Para ello, los constructores admiten
parámetros - class Circulo
- private double radio
- private double PI 3.1416
- public Circulo( double nuevoRadio )
- setRadio( nuevoRadio )
-
- public void setRadio( double radio )
- this.radio radio
-
59finalize()
- En lenguajes como C la memoria ocupada por los
objetos creados por new es liberada manualmente,
mediante el operador delete . En Java la
orientación es diferente tiene un procedimiento
automático de recogida de basura. Este
procedimiento examina las referencias y el
ámbito, cuando considera que un objeto no va a
ser utilizado lo elimina, es decir, libera la
memoria que ocupa - Inmediatamente antes de que se libere la memoria
se invoca automáticamente al método finalize().
El programador puede implementarlo cuando desee
realizar una acción antes de la eliminación del
objeto - protected void finalize()
- System.out.println( Adios )
-
- Téngase en cuenta que no se puede garantizar el
momento exacto en el que el programa invocará al
método - El procedimiento de recogida de basura no se
ejecuta siempre que se deja de utilizar un
objeto, sino que se ejecuta de manera esporádica - Además cada interprete de Java tiene su
procedimiento de recogida de basura - Por tanto, no se puede confundir con los
destructores de C. Java no tiene el concepto de
destructor
60Sobrecarga de métodos
- Java nos permite tener métodos con el mismo
nombre y que se diferencian por sus argumentos
package figuras.presentacion import
figuras.dominio. public class VistaFiguras
public static void mostrar( Circulo cir )
System.out.println( cir.toString() )
public static void mostrar( Rectangulo rec
) System.out.println( rec.toString()
)
Por qué hace falta hacer import de las clases
del paquete figuras.domino? Porque están en un
paquete diferente que VistaFiguras
Al llamar a un método, Java busca la versión del
método que coincide con los argumentos de la
llamada
61Sobrecarga de constructores
- Los constructores, como cualquier otro método,
pueden ser sobrecargados - class Circulo
- private double radio
- private double PI 3.1416
- / Constructores sobrecargados /
- public Circulo()
- public Circulo( double nuevoRadio )
- setRadio( nuevoRadio )
-
- public Circulo( Circulo circulo )
- setRadio( circulo.getRadio() )
-
- ...
-
- Observe que el último constructor define el r