2. Disclaimer & Acknowledgments
>!Even though Ezequiel Aranda is a full-time employee of Sun
Microsystems, the contents here are created as his own
personal endeavor and thus does not reflect any official
stance of Sun Microsystems.
>!Sun Microsystems is not responsible for any inaccuracies in
the contents.
>!Acknowledgments – The slides of this presentation are made
from “SCJP Unit 8” by Warit Wanwithu and Thanisa
Kruawaisayawan and SCJP Workshop by P. Srikanth.
>!This slides are Licensed under a Creative Commons
Attribution – Noncommercial – Share Alike 3.0
>!http://creativecommons.org/licenses/by-nc-sa/3.0/
3. AGENDA
>! enerics Vs. Arrays
G
>! lases internas
C
>! lases internas “regulares”
C
>! lases internas locales a un método
C
>! lases internas anónimas
C
>! lases estáticas anidadas
C
5. Generics Vs. Arrays (II)
public void checkAnimals(ArrayList<Animal>
animals){
for(Animal a : animals) {
a.checkup();
}
}
doc.checkAnimals(dogs); // dogs: List<Dog>
doc.checkAnimals(cats); // cats: List<Cat>
doc.checkAnimals(birds); // birds: List<Bird>
>! Porqué no funciona?
¿
>! Cómo solucionarlo?
¿
6. Generics Vs. Arrays (III)
Animal[] animals = new Animal[3];
animals[0] = new Cat();
animals[1] = new Dog();
List<Animal> animals = new
ArrayList<Animal>();
animals.add(new Cat()); // OK
animals.add(new Dog()); // OK
>! sto funciona con ambos, Arrays y Generics.
E
7. Generics Vs. Arrays (IV)
>! unciona siempre:
F
public void addAnimal(Animal[] animals) {
animals[0] = new Dog(); Animal[]
}
>! unciona a veces:
F
public void addAnimal(ArrayList<Animal>
animals) {
animals.add(new Dog());
}
8. Generics Vs. Arrays (V)
>! a razón por la cual es peligroso pasar como
L
parámetro una colección de un subtipo es
porque podríamos agregar algo erróneo en la
colección (o en el Array).
9. Generics Vs. Arrays (VI)
public void foo() {
Dog[] dogs = {new Dog(), new Dog()};
addAnimal(dogs);
}
public void addAnimal(Animal[] animals) {
animals[0] = new Dog();
}
>! sto funciona perfectamente, y es correcto.
E
10. Generics Vs. Arrays (VII)
public void foo() {
Cat[] cats = {new Cat(), new Cat()};
addAnimal(cats);
}
public void addAnimal(Animal[] animals) {
animals[0] = new Dog();
}
>! cabamos de poner un gato en un Array de
A
perros.
11. Generics Vs. Arrays (VIII)
>! in embargo, y a diferencia que realizando
S
el mismo ejemplo con colecciones
parametrizadas, el código anterior, compila
>! o que permite que compile es la existencia
L
de la excepción ArrayStoreException, que
previene que se de el problema visto
anteriormente en tiempo de ejecución.
12. Generics Vs. Arrays (IX)
>! ero no existe un equivalente
P
a esta excepción para
colecciones, debido a que las
parametrizaciones se eliminan
en tiempo de ejecución.
>! s decir, la JVM conoce el tipo de los Arrays
E
en tiempo de ejecución, pero no el tipo de
una colección.
13. Codificando una inner class “regular”
>! lamamos regulares a las clases internas que
L
no son:
>! státicas
E
>! ocales a un método
L
>! nónimas
A
>! na inner class regular no puede tener
U
declaraciones estáticas de ningún tipo
>! a única forma de acceder a la clase interna
L
es a través de una instancia de la clase
externa.
14. class MyOuter {
private int x = 7;
class MyInner {
public void seeOuter() {
System.out.println("Outer x is
" + x); }}
}
>! ste código es perfectamente legal. Nótese
E
que la clase interna esta accediendo a un
miembro privado de la clase externa. Esto es
correcto, dado que la clase interna es un
miembro de la clase externa también.
15. Instanciando una clase interna
>! esde el interior de la clase externa:
D
MyInner mi = new MyInner();
>! esde el exterior de la clase externa
D
(incluyendo código de métodos estáticos
dentro de la clase externa):
MyOuter.MyInner
>! ara instanciar un objeto de la clase interna
P
debemos usar una referencia a la clase
externa:
obj = new MyOuter().new MyInner();
u outerObjRef.new MyInner();
16. this
>! this” es una referencia al objeto que esta en
“
ejecución actualmente.
public void myMethod() {
MyClass mc = new MyClass();
mc.doStuff(this);
}
17. Haciendo referencia a la instancia de la clase
interna/ externa desde la clase interna
class MyOuter {
private int x = 7;
class MyInner {
public void seeOuter() {
System.out.println("Outer x is "+ x);
System.out.println("Inner class ref is
” + this);
System.out.println("Outer class ref is
” + MyOuter.this);
}
}
}
18. Clases internas locales a un método
class MyOuter2 {
private String x = "Outer2";
void doStuff() {
class MyInner {
public void seeOuter() {
System.out.println("Outer x is " + x);
}
}
MyInner mi = new MyInner();
mi.seeOuter(); }
}
19. Que puede y que no puede hacer una clase
local a un método
>! efiniendo una clase interna dentro de un
D
método, solo podremos crear objetos de esa
clase dentro del método.
>! uede ser una clase abstracta.
P
>! o puede tener métodos o atributos estáticos
N
salvo que la clase interna sea estática
también.
20. Que puede y que no puede hacer una
clase local a un método (II)
>! uede acceder a las variables de la clase
P
externa.
>! o puede acceder a las variables locales al
N
método.
>! alvo que sean declaradas “final”
S
>! os únicos modificadores que podemos
L
aplicar a una clase interna local a un método
son “abstract” y “final”.
>! omo siempre, no podemos aplicar los dos al
C
mismo tiempo.
21. Que puede y que no puede hacer una
clase local a un método (III)
class MyOuter2 {
private String x = "Outer2";
void doStuff() {
String z = "local variable";
class MyInner {
public void seeOuter() {
System.out.println("Outer x is " + x);
System.out.println("Local variable z
is"+ z);
// Esto no compila. Dado que se accede a z desde la
clase interna, z debe ser declarada final.
} } } }
22. Clases internas anónimas
class Popcorn {
public void pop() {
System.out.println("popcorn");
}
}
class Food {
Popcorn p = new Popcorn() {
public void pop() {
System.out.println("anonymous popcorn");
}
}; // debe colocarse un punto y coma aquí
}
>!La variable p no hace referencia a una instancia de
Popcorn, sino a una instancia de una subclase
anónima de Popcorn.
23. class Popcorn {
public void pop() {
System.out.println("popcorn");
}
}
class Food {
Popcorn p = new Popcorn() {
public void sizzle() {
System.out.println("anonymous sizzling
popcorn");
}
public void pop() {
System.out.println("anonymous popcorn");
}
};
public void popIt() {
p.pop(); // OK
p.sizzle(); //KO ¿Porqué no funciona?
}}
24. Clases internas anónimas:
implementando una interfaz
interface Cookable {
public void cook();
}
class Food {
Cookable c = new Cookable() {
public void cook() {
System.out.println("anonymous cookable
implementer");
}
}; Nota: no existe un mecanismo para implementar mas
} de una interfaz de esta forma
25. class MyWonderfulClass { Clases internas anónimas:
void go() { clases definidas en
Bar b = new Bar(); argumentos
b.doStuff(new Foo() {
public void foof() {
System.out.println("foofy");
} // fin foof
}); //fin inner class y declaración del método
} // fin go()
} // fin class
interface Foo {
void foof();
}
class Bar {
void doStuff(Foo f) { }
}
26. Clases estáticas anidadas
class BigOuter {
static class Nest {
void go(){System.out.println("hi"); } }
}
class Broom {
static class B2 {
void goB2(){System.out.println("hi 2"); }
}
public static void main(String[] args) {
BigOuter.Nest n = new BigOuter.Nest();
n.go();
B2 b2 = new B2();
b2.goB2(); }}
27. Clases estáticas anidadas (II)
>!Las clases no son exactamente “estáticas”. No existe
tal cosa.
>!En este caso el modificador “static” indica que la
clase interna es un miembro estático de la clase
externa.
>!Esto quiere decir que podemos acceder al mismo sin
la necesidad de crear una instancia de la clase
externa.
>!No puede acceder a los miembros de la clase
externa de la misma forma que lo haría una clase
interna (exceptuando a los estáticos, claro está).