Visualizzazione dei risultati da 1 a 8 su 8

Discussione: espressioni lambda

  1. #1
    Utente di HTML.it
    Registrato dal
    Oct 2014
    Messaggi
    315

    espressioni lambda

    Ho un dubbio su un esercizio sulle espressioni lambda.
    L'esercizio in questione riprende un precedente esercizio sui thread che permetteva di astrarre il concetto di osservatorio astronomico, in particolare venivano creati 10 thread (rappresentavano 10 persone) e ogni thread passava dallo stato "IN_ATTESA" a quello "OSSERVAZIONE" (che durava 3 secondi) fino a quello "FINITO".
    L'esercizio sulle espressioni lambda per prima cosa chiede se è possibile fare, tramite espressioni lambda, l'override del metodo run() in modo però da modificarlo solo per un thread specifico.
    Io ho pensato che si potesse fare, anche perchè parliamo di fare l'override del metodo run() che è il metodo di Runnable e cioè di una interfaccia funzionale e così ho modificato il seguente codice:
    codice:
    for(int i=0; i<50; i++) {
                int numeroCasuale = (int)(Math.random()*10);
                if (persone[numeroCasuale] != null) {
                    try {
                        Telescopio oggetto = new Telescopio(persone[numeroCasuale].getName());
                        oggetto.run();
                    }
                    catch (Exception exc) {
                        exc.printStackTrace();
                    }
                    persone[numeroCasuale] = null;
                }
    }
    in questo modo:
    codice:
    for(int i=0; i<50; i++) {
                int numeroCasuale = (int)(Math.random()*10);
                if (persone[numeroCasuale] != null) {
                    try {
                        Telescopio oggetto = new Telescopio(persone[numeroCasuale].getName());
                        if(numeroCasuale == 2) {
                            Runnable r = () -> {
                                try {
                                         System.out.println(oggetto.getNome() + Stati.OSSERVAZIONE.getStato());
                                         Thread.sleep(10000);
                                         System.out.println(oggetto.getNome() + Stati.FINITO.getStato());
                                         Thread.sleep(1000);
                                }
                                catch (InterruptedException exc) {
                                         exc.printStackTrace();
                                }
                            };
                        }
                        else {
                            oggetto.run();
                        }
                    catch (Exception exc) {
                        exc.printStackTrace();
                    }
                    persone[numeroCasuale] = null;
                }
    }
    Errori in compilazione non ne ho (tranne un warning che avvisa che r non è utilizzato) però in realtà non funziona come vorrei perchè arrivato al thread con indice 2 in automatico è come se lo saltasse e quindi quel thred non viene proprio preso in considerazione.

    Ho dato un'occhiata alla soluzione e dice che innanzitutto, con mio grande stupore, non è possibile effettuare un override del metodo run tramite un'espressione lambda ma al massimo lo si può fare tramite una classe anonima.

    Ho provato a questo punto a utilizzare la classe anonima, sempre nel main, durante la creazione dell'array di thread modificando il seguente codice:
    codice:
            Thread[] persone;
            persone = new Thread[10];
            
            persone[0] = new Thread("Carlo ");
            persone[1] = new Thread("Michele ");
            persone[2] = new Thread("Aldo ") 
            persone[3] = new Thread("Gianni ");
            persone[4] = new Thread("Federico ");
            persone[5] = new Thread("Alberto ");
            persone[6] = new Thread("Roberto ");
            persone[7] = new Thread("Vittorio ");
            persone[8] = new Thread("Antonio ");
            persone[9] = new Thread("Paolo ");
    in questo modo:
    codice:
    Thread[] persone;
            persone = new Thread[10];
            
            persone[0] = new Thread("Carlo ");
            persone[1] = new Thread("Michele ");
            persone[2] = new Thread("Aldo ") {
                
                Telescopio oggetto = new Telescopio("Aldo ");
                
                @Override
                public synchronized void run() {
                    try {
                        System.out.println(oggetto.getNome() + Stati.OSSERVAZIONE.getStato());
                        Thread.sleep(10000);
                        System.out.println(oggetto.getNome() + Stati.FINITO.getStato());
                        Thread.sleep(1000);
                    }
                    catch (InterruptedException exc) {
                        exc.printStackTrace();
                    }
                }
                
            };
            
            persone[3] = new Thread("Gianni ");
            persone[4] = new Thread("Federico ");
            persone[5] = new Thread("Alberto ");
            persone[6] = new Thread("Roberto ");
            persone[7] = new Thread("Vittorio ");
            persone[8] = new Thread("Antonio ");
            persone[9] = new Thread("Paolo ");
    Anche in questo caso non ho errori di sintassi ma non funziona come vorrei infatti il thread che subisce l'override del metodo run va subito nello stato "FINITO" senza passare da "OSSERVAZIONE".


    Quindi quello che vorrei cercare di capire è innanzitutto perchè non potrei fare un override di run tramite espressione lambda e poi come far funzionare correttamente il programma modificato tramite classe anonima.

    Potete darmi qualche dritta?

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254
    Quote Originariamente inviata da newutente Visualizza il messaggio
    (tranne un warning che avvisa che r non è utilizzato)
    Appunto .... chi invoca run() su quel 'r' ? Nessuno. Quindi a cosa serve?

    Quote Originariamente inviata da newutente Visualizza il messaggio
    dice che innanzitutto, con mio grande stupore, non è possibile effettuare un override del metodo run tramite un'espressione lambda ma al massimo lo si può fare tramite una classe anonima.
    È perfettamente possibile implementare un Runnable tramite una lambda expression. Dopotutto Runnable è una functional interface!


    Buon Natale e Buone Feste a tutti!
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    Oct 2014
    Messaggi
    315
    Quote Originariamente inviata da andbin Visualizza il messaggio
    Appunto .... chi invoca run() su quel 'r' ? Nessuno. Quindi a cosa serve?
    accidenti che dimenticanza, è stato sufficiente aggiungere (alla mia soluzione) "r.run();" dopo l'espressione lambda per far funzionare il tutto.

    Quote Originariamente inviata da andbin Visualizza il messaggio
    È perfettamente possibile implementare un Runnable tramite una lambda expression. Dopotutto Runnable è una functional interface!
    La domanda che pone è chiara: "E' possibile usare un'espressione lambda per sovrascrivere il metodo run() della classe Telescopio, per uno dei partecipanti?".
    In realtà anzichè "Telescopio" il manuale l'ha chiamata "Partecipante" e all'interno il codice è un po' diverso però contiene ugualmente, come la mia classe Telescopio (per quello nella domanda ho scritto Telescopio), il metodo run(). L'unica differenza è che io ho implementato Runnable mentre il manuale in quella classe ha esteso Thread ed è forse lì il "problema".
    Non può utilizzare l'espressione lambda su un metodo che non è "preso" da un'interfaccia funzionale. Avrebbe potuto farlo se, come nella mia soluzione, anzichè estendere Thread avesse implementato Runnable.
    Giusto?

    Quote Originariamente inviata da andbin Visualizza il messaggio
    Buon Natale e Buone Feste a tutti!
    Buone Feste anche a te!!!
    Ultima modifica di newutente; 29-12-2014 a 15:23

  4. #4
    Utente di HTML.it
    Registrato dal
    Oct 2014
    Messaggi
    315
    Giusto per conferma, l'espressione lambda io posso utilizzarla SOLO se ho anche un'interfaccia funzionale da poter usare, giusto? Questo perchè appunto l'espressione lambda permette di rimpiazzare un'interfaccia funzionale.

  5. #5
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254
    Quote Originariamente inviata da newutente Visualizza il messaggio
    l'espressione lambda io posso utilizzarla SOLO se ho anche un'interfaccia funzionale da poter usare, giusto?
    Sì, è così, perlomeno al momento in Java 8. L'inferenza funziona solo se una lambda expression (o method reference) viene assegnata direttamente (a una variabile o a un parametro) ad una interfaccia "funzionale".

    Runnable r = () -> { .....codice che non ritorna nulla...... };

    Così è corretto.

    Ma:

    Object o = () -> { .....codice che non ritorna nulla...... };

    NON compila. Il compilatore non ha appigli per dedurre ciò che gli serve per applicare la lambda expression.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

  6. #6
    Utente di HTML.it
    Registrato dal
    Oct 2014
    Messaggi
    315
    ok, grazie per la spiegazione.

  7. #7
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254
    Completo la spiegazione facendo una piccola precisazione.

    Come ho detto prima questo NON compila:
    Object o = () -> { .....codice che non ritorna nulla...... };

    Il javac di JDK8 dice "error: incompatible types: Object is not a functional interface". Perché come già detto, le lambda expression funzionano solo a fronte di una functional interface da associare alla expressione.

    Questo di seguito però tecnicamente compila!

    Object o = (Runnable) () -> { .....codice che non ritorna nulla...... };

    Il cast rende evidente al compilatore quale è il tipo voluto per la lambda expression, quindi l'inferenza funziona. E siccome Runnable è-un Object anche l'assegnamento a 'o' chiaramente è corretto.
    È ovvio che così ha relativamente poco senso, perché avendo il riferimento come Object, il run() non è "visibile". Potrebbe avere senso se si mette il riferimento ... che so ... in una lista di <Object> e poi successivamente lo si riprende e si fa un down-cast. Ma sono cose rare e poco belle in generale (salvo scenari ben specifici).
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

  8. #8
    Utente di HTML.it
    Registrato dal
    Oct 2014
    Messaggi
    315
    grazie per la precisazione.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.