Java
Introducción a Java
Java
● No es OO puro
● No todo es un objeto
● Tipado estático
● Tipos built-in (int, long, etc.)
● Instrucciones de control
● Sintaxis similar a C [Link]
● No tiene herencia múltiple
● Manejo de errores a través de excepciones
Plataformas
● Java ME (Micro Edition)
● Java SE (Standard Edition)
● Java EE (Enterprise Edition)
Aplicaciones a desarrollar
Age Of Empires II
Mobile en Java ME
● Applets (2005)
● Aplicaciones desktop
○ interface gráfica
○ de consola
● Aplicaciones web
The 25 greatest Java apps ever written (2020)
Plataforma Java
● Se necesita
○ JRE: Para ejecutar código Java (cliente)
○ JDK: Para crear código Java (desarrollador)
● Las clases se escriben en un archivo .java con el mismo
nombre de la clase
● El código se compila (javac) y se genera código intermedio:
archivo binario .class
● El código intermedio es pasado a código de máquina en el
equipo final por la JVM: Java Virtual Machine
● Para generar un programa ejecutable una clase tiene que
implementar el método main.
Hello, world!
Archivo de texto [Link] Correspondencia entre archivo y clase
Toda clase pertenece a un “package”
package [Link];
public class MyClass {
public static void main(String[] args) {
[Link]("Hello, world!"); Argumentos por línea
} de comandos
}
Clase que no se puede instanciar con tres campos: in, err, out
Clases abstractas
public abstract class Class1 {
public abstract Integer method1();
public class Class2 extends Class1 {
Error:java: Class2 is not abstract and does not
override abstract method method1() in Class1
Hello, world!
Versión gráfica con JavaFX
package [Link];
import [Link];
import [Link];
import [Link];
Para usar clases de otros packages
se deben importar esas clases (o el
import [Link];
package completo)
import [Link];
import [Link];
import [Link];
public class App extends Application {
public static void main(String[] args) {
launch(args);
}
Hello, world!
@Override
public void start(Stage primaryStage) {
Button btn = new Button("Say 'Hello World'");
[Link](new MyAction());
StackPane root = new StackPane(btn);
[Link](new Scene(root, 300, 250));
[Link](); Hello World!
}
private class MyAction implements EventHandler<ActionEvent> {
@Override
public void handle(ActionEvent event) {
[Link]("Hello World!");
}
}
Hello, world!
@Override
public void start(Stage primaryStage) {
Button btn = new Button("Say 'Hello World'");
[Link](new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
[Link]("Hello World!"); Clase Anónima
}
});
StackPane root = new StackPane(btn);
[Link](new Scene(root, 300, 250));
[Link]();
}
}
Hello, world!
@Override
public void start(Stage primaryStage) {
Button btn = new Button("Say 'Hello World'");
[Link](aE -> [Link]("Hello World!"));
StackPane root = new StackPane(btn);
[Link](new Scene(root, 300, 250)); Expresión
[Link](); Lambda
} (Funcional)
}
Métodos y propiedades
public class Date {
private Integer year, month, day; // inicializadas en null
private static String format;
private static final int MIN_YEAR = 1900;
public Date(int year, int month, int day) {
[Link] = year;
[Link] = month;
[Link] = day;
}
public Date() {
this(1970, 1, 1);
}
Polimorfismo
public static void setFormat(String format) {
if ( isValid(format))
[Link] = format; // debo diferenciar ambos “format”
}
private static boolean isValid(String fmt) {
return fmt != null && ...
}
private static boolean isValid(int year, int month, int day) {
return ...
}
public Date getClone() {
return new Date(year, month, day);
}
Validando en el constructor
public class Date {
int year=1970, month=1, day=1; // valores por defecto
public Date(int year, int month, int day) {
if ( !isValid(year, month, day)) {
throw new IllegalArgumentException("...");
}
[Link] = year; [Link] = month; [Link] = day;
}
public Date() {
}
...
}
Métodos: alcance
public class Foo {
private Integer privateMethod() { ... }
protected Integer protectedMethod() { ... }
Integer packageMethod() { ... }
public Integer publicMethod() { ... }
}
Alcance de los modificadores
Extraído de Java in a Nutshell
Ejemplo
public class Foo2 extends Foo {
@Override
public Integer publicMethod() { ... } // OK
@Override
protected Integer protectedMethod() {
Integer n = privateMethod(); // ERROR
}
}
Métodos: modificadores
public abstract class Foo {
public static int staticMethod() { ... };
public final int finalMethod() { ... };
public abstract int abstractMethod();
public synchronized int syncMethod() { ... };
public native int nativeMethod();
} Error: Foo2 debe implementar
abstractMethod
public class Foo2 extends Foo {
Error: Sólo una clase abstracta
public abstract int otherAbstractMethod();
puede tener un método
abstracto
}
==, equals
public class Date {
private int year, month, day;
...
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Date))
return false;
Date date = (Date) o;
// Si son int usar ==, si son Integer usar equals
return year == [Link] && month == [Link] && day == [Link];
}
}
Pattern Matching instanceof
public class Date {
private int year, month, day;
...
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Date date))
return false;
return year == [Link] && month == [Link] && day == [Link];
}
}
==, equals
Date d1 = new Date(2020, 11, 11);
Date d2 = new Date(2020, 11, 11);
[Link](d1==d2); // false
[Link]([Link](d2)); // true
Herencia
public class DateTime extends Date {
private int hour, minute, second;
public DateTime(int year, int month, int day, int hour, int min, int secs){
super(year, month, day);
...
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != [Link]())
return false;
if ()
return false;
...
}
}
toString()
public class Date {
private static String format;
...
@Override
public String toString() {
if (format == null)
return [Link]("%02d/%02d/%d", day, month, year);
return [Link](format, day, month, year);
}
}
public static void main(String[] args) {
Date d = new Date(); La fecha es
[Link]("La fecha es " + d); 01/01/1970
}
Boxing, Unboxing
Los tipos de datos primitivos no son objetos, no se deben instanciar para operar con ellos.
Entre las clases wrapper no hay “casteos”.
Se recomienda utilizar los tipos primitivos por sobre las wrapper. 1
Primitive types (built-in) Boxed primitives (wrapper)
byte [Link]
short [Link]
int [Link]
long [Link]
float [Link]
double [Link]
boolean [Link]
char [Link]
Boxing: conversión de un tipo primitivo a una referencia
Automático a partir
de JDK 1.5
Unboxing: conversión de una referencia a su tipo primitivo
Boxing, Unboxing: ejemplos
Integer n = 100; // Equivalente a n = new Integer(100);
int n2 = n; // Equivalente a n2 = [Link]();
Integer n3 = new Integer(n);
Integer sum = n3 + n; // sum = new Integer([Link]() + [Link]());
n3 = null; // OK
n2 = null; // Error: Incompatible types
double x = n2; // OK: acepta promociones
n2 = x; // Error: no acepta demociones
Double x2 = n; // Error: Incompatible types
double real = 10; // OK
Boxing, Unboxing: ejemplos
En el siguiente ejemplo, ¿qué método se invoca?
private static void method(double x) { ... }
private static void method(Integer n) { ... }
...
method(10);
Para casos puntuales donde se presenten estos conflictos se puede optar por utilizar
wrappers en los tipos de dato de los parámetros de los métodos.
Loops
while(boolean_expression)
proposition
do
proposition
while(boolean_expression);
for(initialization; boolean_expression; update)
proposition
Arrays
int v1[] = new int[10]; // Built-in y C-style array
declaration
Integer[] v2 = new Integer[10]; // Wrapper y Java-style array declaration
v1[2] = 10;
[Link](v1[3]); // 0
[Link](v2[3]); // null
[Link](v1[10]); // Exception in thread "main"
// [Link]: 10
[Link](v2[1] + 5); // Exception in thread "main"
// [Link]
[Link]([Link]); // 10
[Link]([Link]()); // [I@2626b418
[Link]([Link](v1)); // [0, 0, 10, 0, 0, 0, 0, 0, 0, 0]
Object[] v = {"Este array", 0, 1.5, "no tiene", 'x', "sentido" };
Clase Arrays
Contiene métodos de clase para operar con vectores
static int binarySearch(Object[] a, Object key)
static int binarySearch(long[] a, long key) // byte, char, int, short, float, …
static void sort(int[] a)
static boolean equals(long[] a, long[] a2)
static void fill(long[] a, int fromIndex, int toIndex, long val)
static void fill(float[] a, float val)
static String toString(boolean[] a)
...
Ver [Link]
Loops
int[] v1 = new int[10];
...
Integer sum = 0;
Ineficiente
for(int i=0; i < [Link]; i++) {
sum += v1[i];
}
int[] v1 = new int[10];
...
int sum = 0;
for(int i=0; i < [Link]; i++) {
sum += v1[i];
}
Loops: for-each
int sum = 0;
for(int value : v1) {
sum += value;
}
Double avg = 0; double avg = 0;
for(int i : v1) { for(int i : v1) {
avg += i; avg += i;
} }
avg /= [Link]; avg /= [Link];
Error: incompatible types: int cannot be
converted to [Link]
Operadores
Categoría Operador Asociatividad
Postfix () [] . Izquierda a derecha
Unary ++ - - ! ~ Derecha a izquierda
Multiplicative * / Izquierda a derecha
Additive + - Izquierda a derecha
Shift >> << Izquierda a derecha
Relational > >= < <= Izquierda a derecha
Equality == != Izquierda a derecha
Operadores
Categoría Operador Asociatividad
Bitwise AND & Izquierda a derecha
Bitwise XOR ^ Izquierda a derecha
Bitwise OR | Izquierda a derecha
Logical AND && Izquierda a derecha
Logical OR || Izquierda a derecha
Conditional ?: Derecha a izquierda
Assignment = += -= *= /= %= >>= <<= &= ^= |= Derecha a izquierda
Strings
Secuencia inmutable de caracteres
String s1 = "Hello";
String s2 = "world";
String s3 = [Link](", ").concat(s2);
String s1 = "Hello";
String s2 = "world";
String s3 = s1 + ", " + s2;
● Primero se crea un string con los caracteres de s1 seguido de “, “
● Luego se crea un nuevo string con el contenido del string creado seguido de los
caracteres de s2
● s1 y s2 no cambian (no pueden cambiar)
Strings
Leer una línea desde la entrada estándar y pasarla a mayúscula.
int ch;
String s;
while ((ch = [Link]()) != -1 && ch != '\n') {
s += ch; Error: variable s might not have been initialized
}
[Link](); s no se modifica
Strings
Leer una línea desde la entrada estándar y pasarla a mayúscula.
int ch;
String s= "";
while ((ch = [Link]()) != -1 && ch != '\n') {
s += ch; MUY Ineficiente
}
s = [Link]();
Es más eficiente usar la clase StringBuilder.
StringBuilder
Leer una línea desde la entrada estándar y pasarla a mayúscula.
int ch;
StringBuilder s = new StringBuilder();
while ((ch = [Link]()) != -1 && ch != '\n') {
[Link](ch);
}
String upperS = [Link]().toUpperCase();
Strings: algunos constructores
String()
String(byte[] bytes)
String(byte[] bytes, Charset charset)
String(byte[] bytes, int offset, int length)
String(byte[] ascii, int hibyte, int offset, int count)
String(char[] value)
String(char[] value, int offset, int count)
String(StringBuffer buffer)
String(StringBuilder builder)
Para el detalle de constructores y métodos ver
[Link]
Strings: algunos métodos
char charAt(int index)
int compareTo(String anotherString)
int compareToIgnoreCase(String str)
boolean contains(CharSequence s)
boolean endsWith(String suffix)
boolean equalsIgnoreCase(String anotherString)
static String format(String format, Object... args)
byte[] getBytes()
int indexOf(int ch)
boolean isEmpty()
boolean matches(String regex)
String replace(char oldChar, char newChar)
String replaceAll(String regex, String replacement)
String[] split(String regex)
String trim()
String toUpperCase()
String toUpperCase(Locale locale)
static String valueOf(double d)
Text Blocks
// Using "one-dimensional" string literals
String html1 = "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>\n";
// Using a "two-dimensional" block of text
String html2 = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
Argumentos por línea de comandos
public static void main(String[] args) {
for(int i=0; i < [Link]; i++) {
...
}
}
public static void main(String[] args) {
for(String s : args) {
...
}
}
Excepciones
Todas las excepciones extienden directa o indirectamente de la clase Exception
● [Link]
○ [Link]
■ [Link]
● [Link]
● ...
■ [Link]
● [Link]
● [Link]
● [Link]
● [Link]
● ...
● [Link]
● [Link]
● ...
Excepciones
Si un método puede lanzar una excepción que no extienda a RuntimeException, debe
indicarlo en su signature.
void method() throws DataAccessException { El que invoque a method()
if (...) { debe capturar la excepción o
throw new DataAccessException("...");
estar dispuesto a propagarla
}
void method2() throws DataAccessException {
method();
}
void method3() {
try {
method();
} catch (DataAccessException e) {
//
}
}
Excepciones: catch
try {
// Código que puede lanzar una excepcion
} catch (Exception1 e) {
...
} catch (Exception2 e) { // Exception1 no debe ser ancestro de Exception2
...
}
try {
// Código que puede lanzar una excepcion
} catch (Exception1 | Exception2 e) { // Exception1 no debe ser
ancestro
... // de Exception2 y viceversa
}
Excepciones
Ejemplo: método para copiar dos archivos usando [Link]
static void copy(String src, String target) throws RuntimeException {
try {
Path in = [Link](src);
Path out = [Link](target);
[Link](in, out);
} catch (IOException e) {
throw new RuntimeException("Error al copiar");
} catch (InvalidPathException e) {
throw new RuntimeException("Alguno de los archivos no existe");
}
}
Excepciones: finally
En el bloque opcional “finally” se incluye código que se ejecuta tanto si se produce como si
no se producen errores o excepciones.
InputStream input = null;
try {
input = FileUtils...
...
} catch (IOException ex) {
// guardamos el error en un archivo de logs y lanzamos un
RuntimeException
throw new ...
} finally { El bloque finally se ejecuta siempre,
cuando finaliza el bloque try - catch
if (input != null) {
[Link]();
}
} No se está considerando la posible excepción al cerrar el archivo
Excepciones: finally
En el siguiente ejemplo nunca se ejecuta el bloque finally.
public class HelloGoodbye {
public static void main(String[] args) {
try {
[Link]("Hello world");
[Link](0); [Link]() aborta
} finally { la ejecución
[Link]("Goodbye world");
}
}
}
Ejemplo extraído de Java Puzzlers