scjp, clase 8: inner classes

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

Upload: flekoso

Post on 26-May-2015

4.749 views

Category:

Technology


2 download

DESCRIPTION

Slides de la octava clase del curso de Java SCJP dictado en la Universidad Nacional de Centro de La Provincia de Buenos Aires.Contenido:1. Ejemplo de generics vs. arrays2. Inner classes

TRANSCRIPT

Page 1: SCJP, Clase 8: Inner Classes

SCJP 6 Clase 8 – Inner Classes

Ezequiel Aranda

Sun Microsystems Campus Ambassador

Page 2: SCJP, Clase 8: Inner Classes

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/

Page 3: SCJP, Clase 8: Inner Classes

AGENDA

> Generics Vs. Arrays

> Clases internas > Clases internas “regulares”

> Clases internas locales a un método

> Clases internas anónimas

> Clases estáticas anidadas

Page 4: SCJP, Clase 8: Inner Classes

Generics Vs. Arrays

Animal

<<abs>> checkup()

Bird  Cat  Dog 

Page 5: SCJP, Clase 8: Inner Classes

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?

Page 6: SCJP, Clase 8: Inner Classes

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.

Page 7: SCJP, Clase 8: Inner Classes

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

}

Page 8: SCJP, Clase 8: Inner Classes

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

Page 9: SCJP, Clase 8: Inner Classes

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.

Page 10: SCJP, Clase 8: Inner Classes

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.

Page 11: SCJP, Clase 8: Inner Classes

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.

Page 12: SCJP, Clase 8: Inner Classes

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.

Page 13: SCJP, Clase 8: Inner Classes

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.

Page 14: SCJP, Clase 8: Inner Classes

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.

Page 15: SCJP, Clase 8: Inner Classes

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

Page 16: SCJP, Clase 8: Inner Classes

this

> “this” es una referencia al objeto que esta en ejecución actualmente. public void myMethod() {

MyClass mc = new MyClass();

mc.doStuff(this);

}

Page 17: SCJP, Clase 8: Inner Classes

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

} } }

Page 18: SCJP, Clase 8: Inner Classes

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

}

Page 19: SCJP, Clase 8: Inner Classes

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.

Page 20: SCJP, Clase 8: Inner Classes

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.

Page 21: SCJP, Clase 8: Inner Classes

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.

} } } }

Page 22: SCJP, Clase 8: Inner Classes

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.

Page 23: SCJP, Clase 8: Inner Classes

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?

Page 24: SCJP, Clase 8: Inner Classes

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

Page 25: SCJP, Clase 8: Inner Classes

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

Page 26: SCJP, Clase 8: Inner Classes

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

Page 27: SCJP, Clase 8: Inner Classes

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

Page 28: SCJP, Clase 8: Inner Classes

Preguntas