Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

OCPJP Inner classes.

Podobne prezentacje


Prezentacja na temat: "OCPJP Inner classes."— Zapis prezentacji:

1 OCPJP Inner classes

2 Wprowadzone w Java ?.? inner classes method-local inner classes
anonymous inner classes static nested classes Q1, Java 1.1

3 Inner classes class BabaJaga { class WszystkieDzieciZjada { } javac BabaJaga.java Jakie pliki utworzą się na dysku? Q2, Klasa wewnętrzna to klasa zadeklarowana między klamrami deklaracji innej klasy

4 BabaJaga.class BabaJaga$WszystkieDzieciZjada.class

5 class ZlowrogiDelfin { class MalyZlowrogiDelfin { static void main(String[] args) { System.out.println( „NIE dla delfinariów!”); } Q3, Nie można nawet takiego programu skompilować. Klasa wewnętrzna nie może posiadać statycznych metod ani pól. W następnym slajdzie wytłumaczyć dlaczego nie może mieć i jaki to ma związek z bindingiem. Czy tak skompilowany program można uruchomić poleceniem: java ZlowrogiDelfin$MalyZlowrogiDelfin?

6 public class Pakero { private int obwodKabla = 50; public String odzywka = „Koks”; class DanePakera { public void ileMaWKablu() { out.println(„Obwod kabla: ” + obwodKabla); } public void jakaMaOdzywke() { out.println(„Odżywka: ” + odzywka); public void calaPrawdaOPakerze() { DanePakera dp = new DanePakera(); dp.ileMaWKablu(); dp.jakaMaOdzywke(); Instancje klasy wewnętrznej można utworzyć tylko poprzez instancję klasy zewnętrznej. Wynika to z tego, że klasy wewnętrzne są powiązane z danymi klasy zewnętrznej i potrzebują wskaźnika na klasę otaczającą. W podanym przykładzie klasa wewnętrzna ma dostęp do prywatnego i publicznego pola klasy zewnętrznej. Nie jest to łamanie enkapsulacji ponieważ klasa wewnętrzna jest również traktowana jak pole klasy zewnętrznej i tak jak zwykłe metody klasy zewnętrznej ma dostęp do jej pól i metod. Najczęściej instancję klasy wewnętrznej tworzy sama klasa zewnętrzna (bezpośrednio lub przy użyciu jakiejś metody typu helper np. makeDanePakera())

7 public void static main(String[] args) { new Pakero().new DanePakera().ileMaWKablu(); Pakero.DanePakera dp = new Pakero() .new DanePakera() .jakaMaOdzywke(); } Tworzenie instancji klasy wewnętrznej poza klasą zewnętrzną.

8 class Smerfetka { class SekretSmerfetki { void sekretPierwszy { out
class Smerfetka { class SekretSmerfetki { void sekretPierwszy { out.println(„Osiłek is soo cool..”); } static void zdradzSekret() { SekretSmerfetki ss = new SekretSmerfetki(); ss.sekretPierwszy(); public void main(String[] args) { Smerfetka.zdradzSekret(); Q4, Czy można utworzyć klasę wewnętrzną z metody statycznej? Nie można. W statycznym kontekście wskaźnik this jest niedostępny.

9 class Tieto { int zysk = 1_000_000; int kierownicy = 20; int pracownicy = 700; boolean kryzys = true; boolean zarzadZadowolonyZZysku = false; boolean kierownikZadowolonyZPracownika = false; boolean koniunkcjaMarsJowisz = false; int procentZysku(int p) { return p * zysk / 100; } class Zarzad { int zysk = 950_000; int pensja() { return procentZysku(80); } class Kierownicy { int pensja() { return procentZysku(15); } class Pracownicy { int pensja() { return zysk - Zarzad.this.pensja() - Kierownicy.this.pensja(); } int pensja1() { return Zarzad.Kierownicy.Pracownicy.this.pensja(); } int pensja2() { return Kierownicy.Pracownicy.this.pensja(); } int mojaPensja() { return pensja() / pracownicy; } int mojaPremia() { if(!kryzys && zarzadZadowolonyZZysku && kierownikZadowolonyZPracownika && koniunkcjaMarsJowisz) return 100 / pracownicy; else return 0; } Q5, Każda klasa wewnętrzna jest powiązana z klasą otaczającą i każdą kolejną klasą otaczającą. Pracownicy.pensja () – z której klasy jest pobierana wartość zysk i jak zrobić, żeby była pobierana z klasy Tieto? (Tieto.this.zysk)

10 int access$0 { return x; } int access$1 { return y; }
class A { private int m; public void g() { A$B ob = new A$B(); ob.f(); m = ob.access$0() * ob.access$1(); } int access$0 { return m; class A { private int m; private class B { private int x; private int y; void f() { x = m; } } public void g() { B ob = new B(); ob.f(); m = ob.x * ob.y; class A$B { A this$0; private int x; void f() { x = this$0.access$0(); } int access$0 { return x; } int access$1 { return y; } access$0, A$B – package level visibilty JVM nie rozumie klas wewnętrznych Java 1.1 implementation w Java 1.2 ograniczono dostęp do zmiennych prywatnych tylko do właściwych klas (wymiana sekretnego klucza). Do tej porty metody access były dostępne w obrębie całego pakietu Inicializacja this$0 odbywa się w konstruktorze (parametr jest niejawnie doklejany)

11 Modyfikatory final abstract public private protected static * strictfp
* - w tym przypadku static zmienia klasę wewnętrzną w klasę zagnieżdżoną

12 Method-Local Inner Classes
class NaszaKlasa { int uzytkownikow; void statystyka { class Statystyka { int kobiet; int mezczyzn; } Statystyka s = new Statystyka(); println(„kobiet: ” + s.kobiet + „/” + uzytkownikow); println(„mezczyzn: ” + s.mezczyzn + „/” + uzytkownikow); Klasy definiowane w metodach mogą być tylko instancjonowane tylko w tych metodach. Taka klasa ma dostęp do wszystkich pól klasy zewnętrznej ale nie ma dostępu do zmiennych lokalnych danej metody (dlaczego – następny slajd).

13 class Warzywniak { String godzinyOtwarcia() { final String nazwa = "Warzywko u Stasia"; class GodzinyOtwarcia { String utworzListe() { class Godzina { Godzina(String d, int go, int gd) { dzien = d; godzOd = go; godzDo = gd; } String dzien; int godzOd; int godzDo; public String toString() { return dzien + „:” + godzOd + " - " + godzDo + "\n"; return "Godziny otwarcia sklepu: " + nazwa + "\n" + new Godzina("Poniedzialek", 10, 18) + new Godzina("Sroda", 9, 17) + new Godzina("Sobota", 10, 15); GodzinyOtwarcia godziny = new GodzinyOtwarcia(); return godziny.utworzListe(); System.out.println(new Warzywniak().godzinyOtwarcia()); Q6, Dlaczego zmienna nazwa musi być final?

14 class Warzywniak { String godzinyOtwarcia() { final String nazwa = "Warzywko u Stasia"; class GodzinyOtwarcia { + private String nazwa; + GodzinyOtwarcia(String nazwa) { this.nazwa = nazwa; } String utworzListe() { class Godzina { Godzina(String d, int go, int gd) { dzien = d; godzOd = go; godzDo = gd; } String dzien; int godzOd; int godzDo; public String toString() { return dzien + „:” + godzOd + " - " + godzDo + "\n"; return "Godziny otwarcia sklepu: " + nazwa + "\n" + new Godzina("Poniedzialek", 10, 18) + new Godzina("Sroda", 9, 17) + new Godzina("Sobota", 10, 15); + GodzinyOtwarcia godziny = new GodzinyOtwarcia(nazwa); return godziny.utworzListe(); Zmienna nazwa musi być final ponieważ jest to zmienna lokalna i jest tworzona na stosie. Ramka stosu znika natychmiast po zakończeniu wykonywania się metody a instancja klasy lokalnej może żyć dłużej i po zakończeniu metody odwoływałaby się do nieistniejącej zmiennej. Jeśli zmienna lokalna metody typu final jest użyta w klasie wewnętrznej tej metody to tworzone jest prywatne pole w klasie danej metody i tworzony jest niejawny parametr w każdym konstruktorze tej klasy, które jest automatycznie inicjalizowane przy jego wywołaniu

15 Modyfikatory final abstract public private protected static * strictfp
* - w tym przypadku static zmienia klasę wewnętrzną w klasę zagnieżdżoną

16 Anonymous Inner Class class Pomidorowa { public void zamieszaj() {} } class Ogorkowa { class Zupy { private Pomidorowa p = new Pomidorowa(); private Ogorkowa o = new Ogorkowa() { }; Klasa anonimowa to klasa lokalna bez nazwy tworzona w miejscu deklaracji. Tworzona klasa rozszerza klasę bazową!. Zwrócić uwagę na średnik na końcu deklaracji. Nie można stworzyć klasy anonimowej nieznanego typu.

17 class Ogorkowa { public void zamieszaj() {} } class Zupy { private Ogorkowa o = new Ogorkowa() { public void odcedz() {} }; void gotuj() { o.zamieszaj(); o.odcedz(); Q7, Czy ten kod jest poprawny? Nie można wywołać metody nie będącej częścią klasy bazowej

18 interface Zupa { void skladniki(); } abstract class Rosol implements Zupa { public abstract void zamieszaj(); class Zupy { private Rosol rosol = new Rosol() { public void zamieszaj() {} public void skladniki() {} }; private Zupa grzybowa = new Zupa() { Q8, Czy taki sposób tworzenia instancji interfejsu Zupa i klasy Rosół jest poprawna? Tak. Anonimową klasę można też utworzyć poprzez bezpośrednią implementację interfejsu. Mówi się, że klasa anonimowa jest implementatorem interfejsu. Ciekawostka: new Zupa() – normalnie nie można tworzyć instancji interfejsów – w tym jednak kontekście oznacza to utworzenie instancji klasy która implementuje interfejs Zupa. Składnia nie dopuszcza utworzenia klasy anonimowej, która implementuje wiele interfejsów. Nie dopuszcza też rozszerzenia jakiejś klasy i implementacji jednego interfejsu (np. p = new Klass implements IKlass {}; }

19 interface Operacja { int wykonaj(int a, int b); } class Dodaj implements Operacja { public int wykonaj(int a, int b) { return a + b; } } class Odejmij implements Operacja { public int wykonaj(int a, int b) { return a – b; } class Kalkulator { private int result = 0; void operacja(Operacja op, int liczba) { result = op.wykonaj(result, liczba); System.out.println("Result: " + result);

20 static public void main(String[] args) { new Kalkulator()
public class Test { static public void main(String[] args) { new Kalkulator() .operacja(new Dodaj(), 7) .operacja(new Dodaj(), 5) .operacja(new Odejmij(), 1) .operacja(new Operacja() { public int wykonaj(int a, int b) return a * b; } }, 10); Klasę anonimową można zadeklarować jako przekazywany argument do metody. Zwracać uwagę na średniki.

21 Static Nested Classes Klasa statyczna zagnieżdżona nie jest klasą wewnętrzną! Jest statyczną klasą typu top-class. Ponieważ klasa jest statyczna, nie ma ŻADNYCH powiązań z klasą zewnętrzną. Tworzenie SNC wymaga użycia nazwy klasy zewnętrznej.

22

23 Do czego to się przydaje?
lepsza organizacja kodu / enkapsulacja tworzenie nowych typów w miejscu ich użycia szybkie prototypowanie pozwalają tworzyć zgrabny / elegancki kod

24 Wady wzrasta liczba klas, którą musi załadować JVM
duża liczba wewnętrznych klas może zaciemnić kod nie wszystkie IDE obsługują tak dobrze klasy wewnętrzne jak top klasy (refactoring / podpowiadanie). raczej tylko dla doświadczonych programistów

25 Domknięcia (closures)


Pobierz ppt "OCPJP Inner classes."

Podobne prezentacje


Reklamy Google