Differences

This shows you the differences between two versions of the page.

Link to this comparison view

poo-ca-cd:laboratoare:clase-interne-si-strings [2025/11/05 03:19]
florian_luis.micu [🪆 Clase interne]
poo-ca-cd:laboratoare:clase-interne-si-strings [2025/11/06 14:02] (current)
florian_luis.micu [Laboratorul 5: Clase Interne și Strings]
Line 3: Line 3:
   * Autori: [[stefancocioran@gmail.com | Ștefan Cocioran ]], [[miculuis1@gmail.com | Florian-Luis Micu ]], [[sorinabuf@gmail.com | Sorina-Anamaria Buf ]]   * Autori: [[stefancocioran@gmail.com | Ștefan Cocioran ]], [[miculuis1@gmail.com | Florian-Luis Micu ]], [[sorinabuf@gmail.com | Sorina-Anamaria Buf ]]
   * Data publicării:​ 03.11.2025   * Data publicării:​ 03.11.2025
-  * Data ultimei modificări: ​05.11.2025+  * Data ultimei modificări: ​06.11.2025
     * ștergerea notiței legată de contest (ambele observații au fost rezolvate).     * ștergerea notiței legată de contest (ambele observații au fost rezolvate).
-    * refrazări pentru ​a favoriza ​lectură clară șrapidă.+    * refrazări pentru ​favorizarea unei lecturi clare și rapide. 
 +    * indicarea că clasă internă poate fi record, enum, interfață sau clasă abstractă. 
 +    * modificări pentru secțiunea clase anonime 
 +      * adăugarea unui exemplu mai detaliat pentru clase anonime în GUI. 
 +      * precizarea că o clasă internă are acces la membrii privațai clasei externe. 
 +      * adăugarea unor secțiuni legate de accesul la metode și variabile în mai multe contexte.
  
 ===== Obiective ===== ===== Obiective =====
Line 43: Line 48:
   * clase interne metodelor (//​method-local inner classes//) sau blocurilor   * clase interne metodelor (//​method-local inner classes//) sau blocurilor
  
-<note important>​ 
-O clasă internă se comportă ca un **membru al clasei** în care a fost declarată. 
-</​note>​ 
  
 ====Clase interne "​normale"​ ==== ====Clase interne "​normale"​ ====
Line 97: Line 99:
 Car.class Car$OttoEngine.class Engine.class Test.class Test.java Car.class Car$OttoEngine.class Engine.class Test.class Test.java
 </​code>​ </​code>​
- 
-Urmăriți exemplul de folosire a claselor interne de mai sus. Adresați-vă asistentului pentru eventuale neclarități. 
  
 Din interiorul unei clase interne, putem accesa **referința la instanța clasei externe** folosind numele acesteia urmat de keyword-ul ''​this'':​ Din interiorul unei clase interne, putem accesa **referința la instanța clasei externe** folosind numele acesteia urmat de keyword-ul ''​this'':​
Line 134: Line 134:
  
 <note tip> <note tip>
-Țineți cont de faptul că o **clasă internă** se comportă ca un **membru al clasei**, concret **nu** puteți folosi un membru al clasei dacă nu inițializați mai întâi clasa.+  * Țineți cont de faptul că o **clasă internă** se comportă ca un **membru al clasei**, concret **nu** puteți folosi un membru al clasei dacă nu inițializați mai întâi clasa
 +  * Chiar dacă ''​model''​ este un **câmp privat**, clasa internă **îl poate accesa**, deoarece și clasa internă este un membru al clasei. 
 +  * O clasă internă nu trebuie neapărat să fie o clasă obișnuită;​ puteți declara ca membri interni și **records**,​ **enums**, **interfețe sau clase abstracte**.
 </​note>​ </​note>​
  
Line 228: Line 230:
   * Clasa este **anonimă**,​ adică nu are nume, dar implementează tipul ''​Engine'',​ deci poate defini metodele interfeței.   * Clasa este **anonimă**,​ adică nu are nume, dar implementează tipul ''​Engine'',​ deci poate defini metodele interfeței.
   * Corpul clasei apare **imediat după instanțiere**,​ între ''​{ ... }''​.   * Corpul clasei apare **imediat după instanțiere**,​ între ''​{ ... }''​.
 +</​note>​
 +
 +<note tip>
 +Clasa moștenită poate să fie o **interfață**,​ o **clasă abstractă** sau o **clasă normală**.
 </​note>​ </​note>​
  
Line 237: Line 243:
 | **Durata de viață** ​                                                     | Obiectele anonime sunt create și folosite pe loc, deci potrivite pentru scopuri scurte. ​                          | | **Durata de viață** ​                                                     | Obiectele anonime sunt create și folosite pe loc, deci potrivite pentru scopuri scurte. ​                          |
  
-===Accesul la variabile ​locale===+===Accesul la variabile ​și metode===
  
-O clasă internă anonimă declarată într-o metodă **poate folosi variabilele locale** și parametrii acelei metode doar dacă aceștia sunt:+Față de clasele interne normale, clasele anonime au câteva restricții în ceea ce privește accesul la variabile și metode în funcție de locația acestora. 
 + 
 +==Accesul la câmpurile clasei externe== 
 + 
 +Câmpurile clasei externe pot fi accesate din interiorul clasei anonime **fără** să fie nevoie să se impună anumite restricții. 
 + 
 +<code java> 
 +public class Outer { 
 +    private String secret = "​Private info";​ 
 + 
 +    interface Greeter { 
 +        void greet(); 
 +    } 
 + 
 +    public void createAnonymous() { 
 +        Greeter g = new Greeter() { 
 +            @Override 
 +            public void greet() { 
 +                // acces direct la câmpul privat al clasei externe 
 +                System.out.println("​Secretul este: " + secret); 
 +            } 
 +        }; 
 + 
 +        g.greet(); // -> "​Secretul este: Private info"​ 
 +    } 
 + 
 +    public static void main(String[] args) { 
 +        Outer outer = new Outer(); 
 +        outer.createAnonymous();​ 
 +    } 
 +
 +</​code>​ 
 + 
 +==Accesul la câmpuri moștenite de clasa anonimă== 
 + 
 +Dacă clasa anonimă extinde o **clasă normală** sau **abstractă**,​ ea primește toate câmpurile (''​public''/''​protected''/''​package-private''​ sau ''​private''​ prin getteri) ale clasei părinte: 
 + 
 +<code java> 
 +abstract class Animal { 
 +    protected int age = 5;  // câmp moștenit 
 +     
 +    public abstract void showDetails();​ 
 +
 + 
 +public class Test { 
 +    public static void main(String[] args) { 
 +        Animal a = new Animal() { 
 +            @Override 
 +            public void showDetails() { 
 +                System.out.println("​Animal has age: " + age); // folosește câmpul moștenit 
 +            } 
 +        }; 
 + 
 +        a.showDetails();​ // Output: "​Animal has age 5" 
 +    } 
 +
 +</​code>​ 
 + 
 +Dacă clasa anonimă implementează o **interfață**,​ interfața nu are câmpuri ale instanței, doar **constante** (declarate ''​public static final''​) care pot fi accesate direct din clasa anonimă. 
 + 
 +<code java> 
 +interface Greeter { 
 +    String NAME = "​Ana";​ // constantă 
 +     
 +    void greet(); 
 +
 + 
 +public class Main { 
 +    public static void main(String[] args) { 
 +        Greeter g = new Greeter() { 
 +            @Override 
 +            public void greet() { 
 +                // Accesăm direct constanta din interfața implementată 
 +                System.out.println("​Salut,​ " + NAME); 
 +            } 
 +        }; 
 +         
 +        g.greet(); // Output: Salut, Ana 
 +    } 
 +
 +</​code>​ 
 + 
 +==Accesul la metode== 
 + 
 +  - **Metode moștenite din clasa părinte** 
 +    * Clasele anonime **pot folosi și suprascrie metodele clasei părinte**. 
 +    * Se pot apela aceste metode **direct** din corpul clasei anonime. 
 +    * **Metodele abstracte trebuie implementate obligatoriu** în clasa anonimă <code java> 
 +class Animal { 
 +    protected int age = 5; 
 +     
 +    public void speak() { 
 +        System.out.println("​Animal speaks"​);​ 
 +    } 
 +     
 +    public abstract void showDetails();​ 
 +
 + 
 +public class Test { 
 +    public static void main(String[] args) { 
 +        Animal a = new Animal() { 
 +            // Implementăm metoda abstractă 
 +            @Override 
 +            public void showDetails() { 
 +                speak(); // folosește metoda moștenită 
 +                System.out.println("​Animal has age: " + age); 
 +            } 
 +        }; 
 + 
 +        a.showDetails();​ 
 +        a.speak(); // o putem apela și direct pentru că referința este de tip Animal 
 +    } 
 +
 +</​code>​ 
 +  - **Metode noi definite în clasa anonimă** 
 +    * Se pot adăuga metode proprii, dar **nu se pot accesa prin referința superclasei/​interfeței**. 
 +    * Sunt vizibile **doar** în interiorul clasei anonime, deci pot fi considerate metode private sau helper. <code java> 
 +class Animal { 
 +    protected int age = 5; 
 +     
 +    public void speak() { 
 +        System.out.println("​Animal speaks"​);​ 
 +    } 
 +
 + 
 +public class Test { 
 +    public static void main(String[] args) { 
 +        Animal a = new Animal() { 
 +            // Declarăm o metodă proprie 
 +            public void showDetails() { 
 +                System.out.println("​Age:​ " + age); 
 +            } 
 +        }; 
 + 
 +        a.showDetails();​ // nu va funcționa pentru că referința este de tip Animal 
 +    } 
 +
 +</​code>​ 
 +  - **Metode statice** 
 +    * **Nu putem defini metode statice** într-o clasă anonimă, deoarece acestea nu au nume, deci nu am avea cum să le apelăm. 
 + 
 +<note important>​ 
 +  * Atunci când suprascriem o metodă, **metoda apelată la run-time este determinată de instanța efectivă**,​ nu de tipul referinței. În exemplele cu clase anonime, referința pare de tip ''​Animal'',​ dar JVM creează pentru fiecare clasa anonimă un **nume intern unic**, astfel încât suprascrierea să funcționeze corect. 
 +  * Metodele definite exclusiv în clasele anonime **nu pot fi apelate din afara acestora**, deoarece compilatorul verifică tipul referinței pentru a determina ce metode există. Deși JVM alocă fiecărei clase anonime un **ID intern** la run-time, acesta nu este cunoscut la compilare, deci nu putem declara o referință care să aibă tipul clasei anonime. 
 +</​note>​ 
 + 
 +==Accesul la variabile locale metodei== 
 + 
 +O clasă internă anonimă declarată într-o metodă **poate folosi variabilele locale** și **parametrii** acelei metode doar dacă aceștia sunt:
   * declarați ''​final'',​ sau   * declarați ''​final'',​ sau
   * sunt **effectively final**, adică nu își schimbă valoarea după inițializare.   * sunt **effectively final**, adică nu își schimbă valoarea după inițializare.
  
-Variabilele locale sunt stocate pe **stivă**, deci dispar după terminarea metodei. Pentru a fi accesibile în clasa internă, Java creează **o copie** a acestor variabile și o stochează ca **atribut intern** al clasei anonime.+<code java> 
 +class Car { 
 +    interface Engine { int getFuelCapacity();​ }
  
 +    public Engine getEngine(int fuelCapacityParam) {
 +        int baseCapacity = fuelCapacityParam;​ // effectively final
 +        ​
 +        return new Engine() {
 +            public int getFuelCapacity() {
 +                return baseCapacity + 5; // poate fi folosit
 +            }
 +        };
 +    }
 +
 +    public static void main(String[] args) {
 +        Car car = new Car();
 +        System.out.println(car.getEngine(10).getFuelCapacity());​ // 15
 +    }
 +}
 +</​code>​
 +
 +Variabilele locale sunt stocate pe **stivă**, deci dispar după terminarea metodei. Pentru a fi accesibile în clasa internă, Java creează **o copie** a acestor variabile și o stochează ca **atribut intern** al clasei anonime.
  
 <note important>​ <note important>​
Line 303: Line 477:
   * Vom studia expresiile lambda în detaliu în laboratoarele dedicate c**olecțiilor și stream-urilor**.   * Vom studia expresiile lambda în detaliu în laboratoarele dedicate c**olecțiilor și stream-urilor**.
 </​note>​ </​note>​
- 
- 
-<​hidden>​ 
- 
-**Mutat în laboratorul despre streams** 
- 
-**[Nice to know] Expresii Lambda continuare** 
- 
-O altă situație des intalnită de folosire a lambda-urilor este pentru **transmiterea de funcții ca parametru** iar api-uri precum cel de filtrare al colecțiilor le utilizează intens ([[https://​www.baeldung.com/​java-stream-filter-lambda|exemplu]]). 
- 
- 
-În exemplul de mai jos aveți niște exemple simple de folosire lambda ca paremetru pentru metode. Parametrii primiți în lambda pot fi zero (//()// ca în exemplul cu fuelCapacity) sau mai mulți (param1, param2, ...).  
-<code java> 
-    public static void main(String[] args) { 
-      ​ 
-        ArrayList<​Integer>​ values = new ArrayList<>​(Arrays.asList(1,​ 2, 3, 4, 5)); 
- 
-        values.removeIf((v) -> v % 2 == 0);           // parametru o lambda care intoarce daca numărul primit este par sau nu 
- 
-        values.forEach((v) -> System.out.println(v));​ // parametru o lambda care afiseaza argumentul primit 
-        values.forEach(System.out::​println); ​         // referinta catre metoda println 
-    } 
-} 
-</​code>​ 
- 
-**Operatorul [[https://​www.geeksforgeeks.org/​double-colon-operator-in-java/​|::​]]** este folosit pentru referințierea metodelor. 
-  
-Putem folosi funcții anonime pentru a executa diverse **operații pe liste** (de exemplu ''​removeIf'',​ care filtrează elementele unei colecții pe baza unui predicat, și ''​replaceAll'',​ care aplică o operație pe toate elementele unei colecții). 
- 
-Exemple: 
-<code java> 
-List<​Integer>​ list = new ArrayList<>​(Arrays.asList(1,​ 2, 3, 4, 5, 6, 7, 8, 9, 10)); 
- 
-// incrementează toate numerele din colecție cu 1 
-list.replaceAll((x) -> x + 1); 
- 
-// șterge din colecție numerele impare 
-list.removeIf((x) -> x % 2 == 1); 
-</​code>​ 
- 
-O altă utilitate a funcțiilor anonime reprezintă în **implementarea comparatorilor** folosiți la sortare sau la crearea de colecții sortate (TreeSet, TreeMap). 
- 
-Exemple: 
-<code java> 
-// o variantă 
-Collections.sort(list,​ (o1, o2) -> o2 - o1); 
- 
-// alta variantă, prin care se folosim de metoda sort() din interfața List 
-list.sort((o1,​ o2) -> o2 - o1); 
- 
-// colecții sortate 
-TreeSet<​Integer>​ sortedSet = new TreeSet<>​((o1,​ o2) -> o1 - o2); 
-TreeMap<​Integer,​ Integer> sortedMap = new TreeMap<>​((o1,​ o2) -> o1 - o2); 
-</​code>​ 
- 
-</​hidden>​ 
- 
 ====Clase interne statice==== ====Clase interne statice====
  
Line 560: Line 677:
  
 <code java> <code java>
-button.addActionListener(new ActionListener() { // clasa anonimă implementează ActionListener +// Codul tău cu clasa anonimă 
-    public void actionPerformed(ActionEvent e) {             +public class MyGUI { 
-        numClicks++;​+ 
 +    public void closeWindow() { 
 +        ​// Clasa anonimă implementează ActionListener 
 +        ​button.addActionListener(new ActionListener() {  
 +            @Override 
 +            ​public void actionPerformed(ActionEvent e) {             
 +                numClicks++
 +            } 
 +        });
     }     }
-});+} 
 + 
 +// Cum ar putea arăta metoda addActionListener intern 
 +class JButton { 
 +    ... 
 +     
 +    public void addActionListener(ActionListener listener) { 
 +        // apelează metoda suprascrisă din clasa anonimă 
 +        listener.actionPerformed(this.event); 
 +    } 
 + 
 +    ... 
 +}
 </​code>​ </​code>​
  
 <note tip> <note tip>
-În acest exemplu, clasa anonimă implementează ''​ActionListener''​ și suprascrie metoda ''​actionPerformed'',​ iar implementarea rămâne ascunsă de restul aplicației.+  * În acest exemplu, clasa anonimă implementează ''​ActionListener''​ și suprascrie metoda ''​actionPerformed'',​ iar implementarea ​**rămâne ascunsă** de restul aplicației
 +  * Exemplul de mai sus folosește o **versiune simplificată** a clasei ''​JButton''​ pentru a ilustra exact de ce este nevoie să **pasăm o clasă ca argument** și cum putem **scurta codul folosind o clasă anonimă** pentru acest caz.
 </​note>​ </​note>​
  
Line 965: Line 1103:
 </​note>​ </​note>​
  
-====[Nice to know] Cǎutarea în conținutul unui String====+====[Nice to know] Căutarea în conținutul unui String====
  
 Clasa String oferă mai multe metode simple pentru a căuta subșiruri fixe într-un șir. Astfel, metodele **startsWith()** și **endsWith()** verifică dacă șirul începe sau se termină cu un anumit subșir: Clasa String oferă mai multe metode simple pentru a căuta subșiruri fixe într-un șir. Astfel, metodele **startsWith()** și **endsWith()** verifică dacă șirul începe sau se termină cu un anumit subșir:
Line 992: Line 1130:
  
 Pentru căutări complexe în șiruri, Java oferă API-ul pentru expresii regulate ([[https://​docs.oracle.com/​javase/​tutorial/​essential/​regex/​|Regular Expressions]]),​ care utilizează sintaxa RegEx pentru definirea și identificarea tiparelor în text. Pentru căutări complexe în șiruri, Java oferă API-ul pentru expresii regulate ([[https://​docs.oracle.com/​javase/​tutorial/​essential/​regex/​|Regular Expressions]]),​ care utilizează sintaxa RegEx pentru definirea și identificarea tiparelor în text.
-<​spoiler ​[Optional] ​Metodele clasei String>+<spoiler Metodele clasei String>
 În Java, clasa String oferă o varietate de metode care permit manipularea și analiza șirurilor de caractere. Mai jos prezentăm câteva metode importante, dar pentru detalii suplimentare consultați [[https://​docs.oracle.com/​en/​java/​javase/​11/​docs/​api/​java.base/​java/​lang/​String.html|documentația oficială Oracle]]. În Java, clasa String oferă o varietate de metode care permit manipularea și analiza șirurilor de caractere. Mai jos prezentăm câteva metode importante, dar pentru detalii suplimentare consultați [[https://​docs.oracle.com/​en/​java/​javase/​11/​docs/​api/​java.base/​java/​lang/​String.html|documentația oficială Oracle]].
  
Line 1280: Line 1418:
  
 ===== Resurse și link-uri utile ===== ===== Resurse și link-uri utile =====
 +
 +  * [[https://​docs.oracle.com/​javase/​tutorial/​java/​javaOO/​nested.html#:​~:​text=A%20nested%20class%20is%20a,​members%20of%20the%20enclosing%20class.|Nested vs Inner classes]]
   * [[https://​docs.oracle.com/​en/​java/​javase/​11/​docs/​api/​java.base/​java/​lang/​String.html|String - documentația oficială Oracle]]   * [[https://​docs.oracle.com/​en/​java/​javase/​11/​docs/​api/​java.base/​java/​lang/​String.html|String - documentația oficială Oracle]]
-  * [[:poo-ca-cd:​arhiva:​laboratoare:​2024:​java-features#​interfete_functionale_functii_si_expresii_lambda|Expresii Lambda ​Arhivǎ]] +  * [[https://​www.baeldung.com/​java-string-pool|Guide to Java String Pool Baeldung]] 
-  * [[:poo-ca-cd:​laboratoare:​old-exercises#​clase-interneOld exercises]]+  * [[https://​coderpad.io/​blog/​development/​the-complete-guide-to-regular-expressions-regex/​|The complete guide to Regular Expressions - CoderPad]]
  
  
poo-ca-cd/laboratoare/clase-interne-si-strings.1762305574.txt.gz · Last modified: 2025/11/05 03:19 by florian_luis.micu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0