Programmation fonctionnelle orientée objet Java

1 Programmation fonctionnelle

En mathématiques, une fonction est un ensemble de plans de calcul avec des quantités d'entrée et de sortie, c'est-à-dire « ce qui est utilisé pour faire quelque chose ». Relativement parlant, l'orientation objet met trop l'accent sur "les choses doivent être faites sous la forme d'objets", tandis que la pensée fonctionnelle tente d'ignorer la syntaxe complexe de l'orientation objet - en mettant l'accent sur ce qu'il faut faire plutôt que sur la forme sous laquelle le faire.

1.1 Que faire, pas comment le faire

  • Par exemple:

new Thread(new Runnable(){ 
    @Override 
    public void run(){ 
        //TODO choses 
    } 
}).start();

Concernant l’usage ​Runnable​des classes internes anonymes, plusieurs points peuvent être analysés :

  • La classe​Thread​ nécessite ​Runnable​une interface comme paramètre et la méthode d'exécution abstraite est le noyau utilisé pour spécifier le contenu de la tâche du thread ;
  • Afin de spécifier le corps de la méthode run, nous devons créer une classe d'implémentation de ​Runnable​l'interface ;
  • Afin d'éviter d'avoir à définir une classe ​Runnable​d'implémentation , nous devons utiliser des classes internes anonymes ;
  • Dans la classe interne anonyme, nous devons remplacer et réécrire la méthode d'exécution abstraite, de sorte que le nom de la méthode, les paramètres de la méthode et la valeur de retour de la méthode doivent être réécrits et il ne doit y avoir aucune erreur ;
  • En fait , seul le corps de la méthode run() est probablement la clé la plus importante du programme.
  • Ce que nous voulons vraiment faire, c'est transmettre le code du corps de la méthode run à la classe Thread et l'exécuter.

pense:

Voulons-nous vraiment créer un objet de classe interne anonyme ? Non!

Il suffit de créer un objet pour ce faire.

1.2 Quelle est l'essence de la programmation fonctionnelle ?

Passer un morceau de code - c'est notre véritable objectif. La création d'objets n'est qu'une méthode qui doit être adoptée en raison de la syntaxe orientée objet. Alors, existe-t-il un moyen plus simple ?

Si nous ramenons notre attention du « comment faire » à l'essence du « quoi faire », nous constaterons que tant que l'objectif peut être mieux atteint, le processus et la forme ne sont pas réellement importants.

Un problème avec les classes internes anonymes est que même si l'implémentation de la classe interne anonyme est très simple, comme une interface qui ne contient qu'une méthode abstraite, la syntaxe de la classe interne anonyme semble toujours redondante.

Solution : Vous pouvez utiliser l'expression lambda prise en charge par JDK8. Cette expression n'est implémentée que pour une interface avec une méthode abstraite, et implémente la fonction d'interface sous la forme d'une expression concise en tant que paramètre de méthode.

new Thread(() -> System.out.println("Exécution de tâches multithread!")).start();

L'effet d'exécution de ce code est exactement le même que celui du moment, et il peut passer sous le niveau de compilation 1.8 ou supérieur. Cela se voit à la sémantique du code : nous démarrons un thread et le contenu de la tâche du thread est spécifié sous une forme plus concise.

Il n'y a plus les contraintes de « devoir créer des objets d'interface », et il n'y a plus le fardeau du « remplacement et de la réécriture de méthodes abstraites », c'est aussi simple que cela !

1.3Expression lambda

Format de syntaxe de base de l'expression lambda

Les flèches sont utilisées dans les instructions pour distinguer les listes de paramètres et les corps de méthode.

2Interface fonctionnelle

2.1 Est-il possible d'utiliser des lambdas au lieu de toutes les classes internes anonymes ?

Les expressions Lambda peuvent être utilisées à la place des classes internes anonymes lorsqu'il n'y a qu'une seule méthode abstraite dans l'interface. En effet, les expressions lambda sont implémentées sur la base d'interfaces fonctionnelles.

L'interface dite fonctionnelle fait référence à une interface avec une et une seule méthode abstraite. L'expression lambda est l'incarnation de la programmation fonctionnelle en Java. Ce n'est qu'en s'assurant que l'interface a une et une seule méthode abstraite que l'expression lambda peut déduire avec succès l'interface implémentée. .méthode dans.

2.2 Définition

Dans JDK8, l'interface marquée de l'annotation @FunctionalInterface est une interface fonctionnelle, et il n'y a qu'une seule méthode abstraite à l'intérieur de l'interface fonctionnelle.

Jetons un coup d'œil au code source dans l'interface Runnable :

Remarque : L'annotation @FunctionalInterface marque explicitement uniquement l'interface comme une interface fonctionnelle et oblige l'éditeur à effectuer des contrôles plus stricts pour garantir que l'interface est une interface fonctionnelle.

Quelques interfaces fonctionnelles qui existaient avant JDK8 :

  • java.lang.Runnable
  • java.util.Comparateur
  • java.io.FileFilter
  • java.lang.Reflect.InvocationHandler

Interface fonctionnelle ajoutée dans JDK8

Le package java.util.function contient de nombreuses classes pour prendre en charge la programmation fonctionnelle en Java.

 

​​​​​​​

 

2.3 Simplification des expressions Lambda

La méthode d'écriture omise de l'expression lambda (simplification supplémentaire basée sur l'expression lambda)

1. Si le code du corps de la méthode de l'expression lambda ne contient qu'une seule ligne de code, vous pouvez omettre les accolades et le point-virgule !

2. Si le code du corps de la méthode de l'expression lambda n'a qu'une seule ligne de code et si cette ligne de code est une instruction return, le return doit être omis et le point-virgule doit être omis.

3. Le type de paramètre peut être omis.

4. S'il n'y a qu'un seul paramètre, le () en dehors du paramètre peut également être omis.

En plus des règles de simplification ci-dessus, les expressions lambda peuvent être encore simplifiées à l'aide de « références de méthode ».

public class TestOutter { 
  public static void main(String[] args) { 
    //Méthode d'écriture de fonction anonyme 
    new Thread(new Runnable() {      
      @Override 
      public void run() { 
        System.out.println("Le thread 1 est démarré !" ) ; 
        
      } 
    }).start(); 
    
    //méthode d'écriture lambda 
    new Thread(() -> {System.out.println("Thread 2 démarré!");}.start(); 
  } 
}

3 référence de méthode

Remarque : Lorsque le corps de l'expression lambda n'a qu'une seule instruction, le programme peut non seulement omettre les accolades contenant le corps, mais également référencer des méthodes et des constructeurs (c'est-à-dire des méthodes de construction) via la syntaxe anglaise à double deux-points "::" format.

Fonction : Il peut simplifier davantage l'écriture des expressions lambda. Son essence est de référencer directement les méthodes existantes dans la partie principale de l'expression lambda. La principale différence est la référence aux méthodes ordinaires et aux méthodes du constructeur.

3.1 Le nom de la classe fait référence à une méthode statique

Définition : Le nom de la classe fait référence à la méthode statique, qui est la référence à la méthode statique via le nom de la classe. La classe peut être une classe spéciale fournie avec Java ou une classe ordinaire personnalisée.

Des exemples de citations sont les suivants :

//Définir l'interface fonctionnelle 
@FunctionalInterface 
interface Calcable{ 
  int calc(int num); 
} 

//Définir une classe et définir une méthode statique dans la 
classe class Math{ 
  public static int abs(int num){ 
    return num > 0 ? num : -num; 
  } 
} 

exemple de classe publique { 
  private static void printAbs(int num, Calcable calcable){ 
    System.out.println(calcable.calc(num)); 
  } 
  
  public static void main(String[] args) { 
    
    //1 , utilisez la classe interne anonyme 
    printAbs(-8, new Calcable() {      
      @Override 
      public int calc(int num) { 
        return Math.abs(num); 
      } 
    }); 
    
    //2. Utiliser l'expression lambda
    printAbs(-8, (num) -> {return Math.abs(num);}); 
    
    //3. Simplifier l'expression lambda 
    printAbs(-9, num -> Math.abs(num)); 
    
    //4. Utiliser références de méthodes pour simplifier les expressions lambda 
    printAbs(-7, Math::abs); 
  } 
}

3.2 Méthode de référence du nom d'objet

Définition : La méthode de référence de nom d'objet fait référence à la référence à sa méthode via le nom de l'objet instancié.

Des exemples de citations sont les suivants :

//Définir l'interface fonctionnelle 
@FunctionalInterface 
interface Utils{ 
  String calc(String str); 
} 

//Définir une classe et définir une méthode commune dans la classe 
class UpperUtil{ 
  public String toUpper(String str){ 
    return str.toUpperCase(); 
  } 
} 

public class Exemple2 { 
  private static void printUpper(String ori, Utils u){ 
    System.out.println(u.calc(ori)); 
  } 
  
  public static void main(String[] args) { 
    UpperUtil upper = new UpperUtil() ; 
    
    //1. Utiliser la classe interne anonyme 
    printUpper("abc", new Utils() {      
      @Override 
      public String calc(String ori) { 
        return upper.toUpper(ori); 
      }
    });
    
    //2. Utilisez l'expression lambda 
    printUpper("bcd", (ori) -> {return upper.toUpper(ori);}); // 
    
    3. Simplifiez l'expression lambda 
    printUpper("cde", ori -> upper. toUpper( ori)); 
    
    //4. Utilisez des références de méthode pour simplifier les expressions lambda 
    printUpper("def", upper::toUpper); 
  } 
}

3.3 Méthode de référence du constructeur

Définition : fait référence à une référence au constructeur fourni avec la classe.

Des exemples de citations sont les suivants :

//Définir l'interface fonctionnelle 
@FunctionalInterface 
interface PersonBuilder{ 
  Person buildPerson(String name); 
} 

//Définir une classe, définir un constructeur et des méthodes communes dans la 
classe class Person{ 
  private String name; 
  
  public Person(String name){ 
    this. name = nom; 
  } 
  
  public String getName(){ 
    return name; 
  } 
} 

public class Exemple3 { 
  private static void printName(String name, PersonBuilder buildPerson){ 
    System.out.println(buildPerson.buildPerson(name).getName()); 
  } 
  
  public static void main(String[] args) { 
    
    //1. Utilisez l'expression lambda 
    printName("李思", (String name) -> {return new Person(name);});
    
    //2. Utilisez la méthode de référence du constructeur 
    printName("Zhang San", Person::new); 
  } 
}

3.4 Les noms de classe font référence à des méthodes courantes

Définition : fait référence à une référence à une méthode commune d'une classe commune via son nom de classe.

Des exemples de citations sont les suivants :

//Définir une interface fonctionnelle 
@FunctionalInterface 
interface Printable{ 
  void print(StringUtils su, String str); 
} 

//Définir une classe et une méthode 
class StringUtils{   
  public void printUppercase(String str){ 
    System.out.println(str.toUpperCase( ) ); } 
  } 
public 

class Exemple4 { 
  private static void printUpper(StringUtils su, String str, Printable printable){ 
    printable.print(su, str); 
  } 
  
  public static void main(String[] args) { 
    //1. Utiliser Anonyme classe interne 
    printUpper(new StringUtils(), "abc", new Printable() {       
      @Override  
      public void print(StringUtils su, String str) {
        su.printUppercase(str);        
      } 
    });
    
    //2. Utilisez l'expression lambda 
    printUpper(new StringUtils(), "bcd", (Object, t) -> Object.printUppercase(t)); // 3. 
    
    Utilisez la référence de méthode 
    printUpper(new StringUtils(), "def" , StringUtils::printUppercase); 
  } 
}

Je suppose que tu aimes

Origine blog.csdn.net/QQ156881887/article/details/129191775
conseillé
Classement