Non c'è niente di difficile nella conversione delle classi di metodo singolo in puntatori di funzioni, ma manca una cosa: le espressioni lambda non sono solo funzioni, sono chiusure . La differenza è che le chiusure possono catturare variabili esterne. Consideriamo ora esempio in pseudo Java:
public Adder makeAdder(double startNumber) {
return #{ int number -> number + startNumber}
}
...
int startNumber = 5;
Adder add5 = makeAdder(startNumber);
add5.invoke(4); // ==> 9
In questo esempio funzione lambda, prodotta dalla chiamata a makeAdder(), si riferisce alla variabile che è stata definita al di fuori di questo lambda. Questo è il motivo per cui si chiamano "chiusure" - sono "chiuse" sulle loro variabili libere (in questo caso - su startNumber). Per gestire tali situazioni, le chiusure devono contenere sia il puntatore a una funzione che il puntatore al suo ambiente . Quindi, ottieni una struttura dati con un metodo e almeno una variabile. Ma non è una definizione di un oggetto in OOP? Quindi qual è la ragione per creare un nuovo tipo di oggetti se puoi renderlo un'istanza di classe anonima?
Tuttavia alcune ottimizzazioni su tali classi anonime possono essere fatte. Il documento di lavoro che hai indicato menziona alcuni di essi, ad esempio, inferendo e utilizzando efficacemente le variabili finali (sebbene ciò avvenga principalmente per consentire lambdas su JVM in principal, non per ottimizzare il codice). Anche la classe anonima prodotta può essere eseguita in modo definitivo e la maggior parte delle JVM ha già buone ottimizzazioni per le classi e le classi finali.
Altri miglioramenti possono riguardare anche i riferimenti all'ambiente - ci sono tonnellate di opzioni lì.
Quando si dice "puntatore di funzione", si intende puntatore semplice all'inizio del codice funzione? – ffriend
@ffriend - Sì, lo so.So che ci sono alcuni problemi con questo approccio, ad esempio è possibile sincronizzare su un oggetto. Ma la JVM può fare anche altre ottimizzazioni non banali, ad esempio l'allineamento dei metodi virtuali. –