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

SCJP, Clase 8: Inner Classes

May 26, 2015

Download

Technology

flekoso

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. arrays
2. Inner classes
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
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