28
SCJP 6 Clase 8 – Inner Classes Ezequiel Aranda Sun Microsystems Campus Ambassador

Clase8 innerclasses

Embed Size (px)

Citation preview

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 método

>!Clases internas anónimas

>!Clases estáticas anidadas

Generics Vs. Arrays

Animal

<<abs>> checkup()

!"#$% &'(% )*+%

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?

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 razón por la cual es peligroso pasar como parámetro una colección de un subtipo es porque podríamos agregar algo erróneo en la colección (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 código anterior, compila

>!Lo que permite que compile es la existencia de la excepción ArrayStoreException, que previene que se de el problema visto anteriormente en tiempo de ejecución.

Generics Vs. Arrays (IX)

>!Pero no existe un equivalente a esta excepción para colecciones, debido a que las

parametrizaciones se eliminan

en tiempo de ejecución.

>!Es decir, la JVM conoce el tipo de los Arrays

en tiempo de ejecución, pero no el tipo de

una colección.

Codificando una inner class “regular”

>!Llamamos regulares a las clases internas que no son:

>!Estáticas

>!Locales a un método

>!Anónimas

>!Una inner class regular no puede tener declaraciones estáticas de ningún tipo

>!La única forma de acceder a la clase interna es a través 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 código es perfectamente legal. Nótese 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.

Instanciando una clase interna

>!Desde el interior de la clase externa:

MyInner mi = new MyInner();

>!Desde el exterior de la clase externa (incluyendo código de métodos estáticos 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 ejecución 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 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(); }

}

Que puede y que no puede hacer una clase

local a un método

>!Definiendo una clase interna dentro de un método, solo podremos crear objetos de esa clase dentro del método.

>!Puede ser una clase abstracta.

>!No puede tener métodos o atributos estáticos salvo que la clase interna sea estática también.

Que puede y que no puede hacer una

clase local a un método (II)

>!Puede acceder a las variables de la clase externa.

>!No puede acceder a las variables locales al método.

>!Salvo que sean declaradas “final”

>!Los únicos modificadores que podemos aplicar a una clase interna local a un método 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 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.

} } } }

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.

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

class MyWonderfulClass {

void go() {

Bar b = new Bar();

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

}

Clases internas anónimas:

clases definidas en

argumentos

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

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á).

Preguntas