Sei sulla pagina 1di 28

SCJP 6

Clase 8 Inner Classes

Ezequiel Aranda
Sun Microsystems Campus
Ambassador

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/

AGENDA
>Generics Vs. Arrays
>Clases internas
>Clases internas regulares
>Clases internas locales a un mtodo
>Clases internas annimas
>Clases estticas anidadas

Generics Vs. Arrays


Animal
<<abs>> checkup()

Bird

Cat

Dog

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?
>Cmo solucionarlo?

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

>Esto funciona con ambos, Arrays y Generics.

Generics Vs. Arrays (IV)


>Funciona siempre:
public void addAnimal(Animal[] animals) {
animals[0] = new Dog(); Animal[]
}

>Funciona a veces:
public void addAnimal(ArrayList<Animal>
animals) {
animals.add(new Dog());
}

Generics Vs. Arrays (V)


>La razn por la cual es peligroso pasar como
parmetro una coleccin de un subtipo es
porque podramos agregar algo errneo en la
coleccin (o en el Array).

Generics Vs. Arrays (VI)


public void foo() {
Dog[] dogs = {new Dog(), new Dog()};
addAnimal(dogs);
}
public void addAnimal(Animal[] animals) {
animals[0] = new Dog();
}

>Esto funciona perfectamente, y es correcto.

Generics Vs. Arrays (VII)


public void foo() {
Cat[] cats = {new Cat(), new Cat()};
addAnimal(cats);
}
public void addAnimal(Animal[] animals) {
animals[0] = new Dog();
}

>Acabamos de poner un gato en un Array de


perros.

Generics Vs. Arrays (VIII)


>Sin embargo, y a diferencia que realizando
el mismo ejemplo con colecciones
parametrizadas, el cdigo anterior, compila
>Lo que permite que compile es la existencia
de la excepcin ArrayStoreException, que
previene que se de el problema visto
anteriormente en tiempo de ejecucin.

Generics Vs. Arrays (IX)


>Pero no existe un equivalente
a esta excepcin para
colecciones, debido a que las
parametrizaciones se eliminan
en tiempo de ejecucin.
>Es decir, la JVM conoce el tipo de los Arrays
en tiempo de ejecucin, pero no el tipo de
una coleccin.

Codificando una inner class regular


>Llamamos regulares a las clases internas que
no son:
>Estticas
>Locales a un mtodo
>Annimas

>Una inner class regular no puede tener


declaraciones estticas de ningn tipo
>La nica forma de acceder a la clase interna
es a travs de una instancia de la clase
externa.

class MyOuter {
private int x = 7;
class MyInner {
public void seeOuter() {
System.out.println("Outer x is
" + x); }}
}

>Este cdigo es perfectamente legal. Ntese


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 tambin.

Instanciando una clase interna


>Desde el interior de la clase externa:
MyInner mi = new MyInner();

>Desde el exterior de la clase externa


(incluyendo cdigo de mtodos estticos
dentro de la clase externa):
MyOuter.MyInner

>Para instanciar un objeto de la clase interna


debemos usar una referencia a la clase
externa:
obj = new MyOuter().new MyInner();
u outerObjRef.new MyInner();

this
>this es una referencia al objeto que esta en
ejecucin actualmente.
public void myMethod() {
MyClass mc = new MyClass();
mc.doStuff(this);
}

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);
}
}
}

Clases internas locales a un mtodo


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(); }
}

Que puede y que no puede hacer una clase


local a un mtodo
>Definiendo una clase interna dentro de un
mtodo, solo podremos crear objetos de esa
clase dentro del mtodo.
>Puede ser una clase abstracta.
>No puede tener mtodos o atributos estticos
salvo que la clase interna sea esttica
tambin.

Que puede y que no puede hacer una


clase local a un mtodo (II)
>Puede acceder a las variables de la clase
externa.
>No puede acceder a las variables locales al
mtodo.
>Salvo que sean declaradas final

>Los nicos modificadores que podemos


aplicar a una clase interna local a un mtodo
son abstract y final.
>Como siempre, no podemos aplicar los dos al
mismo tiempo.

Que puede y que no puede hacer una


clase local a un mtodo (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.
} } } }

Clases internas annimas


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
annima de Popcorn.

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?

Clases internas annimas:


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
}

class MyWonderfulClass {
Clases internas annimas:
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 declaracin del mtodo
} // fin go()
} // fin class
interface Foo {
void foof();
}
class Bar {
void doStuff(Foo f) { }
}

Clases estticas 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(); }}

Clases estticas anidadas (II)


>Las clases no son exactamente estticas. No existe
tal cosa.
>En este caso el modificador static indica que la
clase interna es un miembro esttico 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 hara una clase
interna (exceptuando a los estticos, claro est).

Preguntas

Potrebbero piacerti anche