Maison  >  Article  >  Java  >  Introduction détaillée à l'exemple de code de l'expression Lambda, une nouvelle fonctionnalité d'Android utilisant Java 8

Introduction détaillée à l'exemple de code de l'expression Lambda, une nouvelle fonctionnalité d'Android utilisant Java 8

黄舟
黄舟original
2017-03-11 11:54:451934parcourir

Avant-propos

Expression Lambda, une nouvelle fonctionnalité de java8. En utilisant l'expression Lambda, vous pouvez remplacer l'implémentation de l'interface par une seule fonction, dire adieu aux classes internes anonymes et le code semble plus concis et facile à comprendre.
Java8 propose également d'autres nouvelles fonctionnalités, mais elles peuvent ne pas être disponibles sur Android.
Studio 2.x et versions ultérieures prennent en charge le compilateur jack. En l'utilisant, vous pouvez utiliser l'expression Lambda de java8, mais rien ne garantit que d'autres fonctionnalités seront disponibles.

Remarque : Le SDK Android intègre du code source du JDK. Certaines classes du JDK natif peuvent avoir des implémentations de nouvelles fonctionnalités ajoutées, mais pas celles d'Android. Un autre exemple est le package java.util.function de java8, qui n'est pas disponible dans les versions inférieures

Vous pouvez également utiliser le plug-in retrolambda pour prendre en charge l'expression Lambda de java8.

Configuration Jack

Ajoutez la configuration suivante

android {
    jackOptions {
        enabled true
    }
    compileOptions {//jack、retrolambda编译必需        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

pour permettre au compilateur Jack de prendre en charge l'expression Lambda

Utilisez la dernière version 2.3 studio, environnement jdk 1.8, gradle2.3 et la configuration ci-dessus
Après test, il peut également être exécuté sur le simulateur 4.4
Démo de configuration : http://www.php.cn/

retrolambda Configuration

retrolambda est compatible avec java5, 6 et 7 en utilisant l'expression Lambda.

La configuration est la suivante

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'
        classpath 'me.tatarka:gradle-retrolambda:3.6.0'
    }}
apply plugin: 'me.tatarka.retrolambda'android {
    defaultConfig {
        minSdkVersion 11 //这个没有硬性要求
    }
    compileOptions {//jack、retrolambda编译必需
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }}

Remarque : de nombreux projets open source utilisent encore retrolambda

Comment utiliser l'expression Lambda

Tout d'abord, ce qu'il faut savoir, c'est que cette expression dans son ensemble exprime un "type d'objet".

L'expression Lambda la plus simple

Code :

Runnable runnable = () -> System.out.println("hi, 我是 stone");runnable.run();

() est en fait la liste des paramètres de la méthode. Si aucun paramètre n'est transmis ici, elle correspondra à la méthode sans paramètres. , comme Runnable n'a qu'un seul void run(), il sera mis en correspondance ; le nom de la méthode n'est pas écrit ici, donc le nom de la méthode sera ignoré.

-> Ceci est suivi du corps de la méthode. Il n'y a qu'un seul code d'impression ici, vous pouvez omettre les accolades du corps de la méthode : {}.

Remarque : le code tel que "new Runnable" est également omis ici car le compilateur effectuera une inférence de type automatique. Si vous appelez () directement -> System.out.println(“salut, je suis stone”).run(); alors il ne sera pas compilé car le compilateur ne sait pas dans quelle classe rechercher la méthode correspondante

Expression lambda avec paramètres et valeur de retour

Code :

button.setOnTouchListener((view, event)-> {    
if (event.getAction() == MotionEvent.ACTION_DOWN) {        
if (flag) {            
return true;
        }
    }    return super.onTouchEvent(event);
});

Quand il y a des paramètres, passez simplement le nom du paramètre, et le nom peut être défini à volonté ; définition de type ou Peu importe s'il n'est pas défini ; lorsqu'il n'est pas défini, le compilateur le déduira automatiquement.
Lorsqu'il y a une valeur de retour, vous pouvez utiliser return dans le corps de la méthode ; vous pouvez également omettre return lorsqu'il n'y a qu'un morceau de code, comme suit :

button.setOnTouchListener((v, e) -> super.onTouchEvent(e));

Personnalisez l'interface et utilisez Expression lambda

Définissez d'abord une interface avec une seule méthode abstraite :

    interface IGetData<T> {//lambda只能用于单一方法类型匹配
        T get();//      T getOne(int i); //多个抽象方法,直接编译不过
    }

Définissez la méthode, et les paramètres sont l'interface définie ci-dessus :

    void print(IGetData<String> data) {        
    String msg = data.get();        
    System.out.println(msg);
    }

Utilisez Expression Lambda comme paramètre et appel print() :

        print(() -> "张三");        print(() -> {
            System.out.println("干活了");            return "李四";
        });

Sortie :

03-08 06:46:00.430 1510-1510/? I/System.out: 张三
03-08 06:46:00.430 1510-1510/? I/System.out: 干活了
03-08 06:46:00.430 1510-1510/? I/System.out: 李四

Utiliser l'expression Lambda pour simplifier le modèle de commandant

Caractéristiques et processus de mise en œuvre simple de le modèle de commandant :

  • Une interface de commande définit une méthode abstraite pour exécuter les commandes de manière uniforme

  • Chaque commandant spécifique implémente l'interface de commande et s'appuie sur un objet récepteur, commande L'agent d'exécution est donné au récepteur pour exécuter la classe d'appelant

  • , qui s'appuie sur un objet d'interface de commande et est exécutée par l'interface de commande. Passer polymorphiquement dans différents commandants spécifiques, et finalement le récepteur adopte différentes méthodes d'exécution

Exemple (implémentation originale)

Par exemple, il existe des commandes d'opération de fichiers :open, fermer, enregistrer, supprimer, le récepteur est un éditeur éditeur
Eh bien, vous devez d'abord définir une interface de commande : IAction

public interface IAction {//原 命令者  抽象出一个 执行命令的方法
    void perform();
}

, puis définir quatre classes de commandes spécifiques OpenAction, CloseAction, SaveAction et DeleteAction.
Code CloseAction :

public class CloseAction implements IAction {
    private Editor mEditor;    
    public CloseAction(Editor editor) {        
    this.mEditor = editor;
    }    
    @Override
    public void perform() {        
    this.mEditor.close();
    }
}

Les trois autres implémentations sont similaires à CloseAction.

La classe éditeur (récepteur) définit chaque implémentation spécifique de la réception de quatre commandes :

public class Editor {     public void save() {
          System.out.println("save");
      }      public void delete() {
          System.out.println("delete");
      }      public void open() {
          System.out.println("open");
      }      public void close() {
          System.out.println("close");
      }
}

Remarque : si différents éditeurs ont des exigences différentes pour ces commandes, s'il existe différentes implémentations, vous pouvez également définir une interface IEditor puis implémenter différents éditeurs. Ce point ne sera pas abordé en détail

Enfin il y a un appelant, qui peut être une classe :

public class Invoker {  
    private IAction action;  

    public Invoker(IAction action) {  
        this.action = action;  
    }  

    public void invoke() {  
        this.action.perform();  
    }  
}

le client initie une commande :

Editor editor = new Editor();
new Invoker(new OpenAction(editor)).invoke();
new Invoker(new CloseAction(editor)).invoke();
new Invoker(new SaveAction(editor)).invoke();
new Invoker(new DeleteAction(editor)).invoke();

L'appelant ici peut être défini non pas comme une classe, mais comme une méthode dans le client :

private void invoke(IAction action) {
    action.perform();
}

Le client initie un appel de commande :

 invoke(new OpenAction(editor)); 
 invoke(new CloseAction(editor)); 
 invoke(new SaveAction(editor)); 
 invoke(new DeleteAction(editor));

Expression Lambda Version simplifiée

conserve l'invocation (action Iaction) dans IAction, l'éditeur et le client.

le client lance un appel de commande :

  Editor editor = new Editor();
  invoke(() -> editor.open());  
  invoke(() -> editor.close());  
  invoke(() -> editor.save());  
  invoke(() -> editor.delete());

De cette façon, après avoir utilisé l'expression Lambda, la définition de la classe de commande spécifique est omise. Et vous pouvez voir d’un seul coup d’œil quelle méthode a finalement été exécutée.

Ne vous inquiétez pas, l'écrire ainsi détruira la séparation originale de la demande et de l'exécution du mode commandant.
Parce queinvoke(() -> editor.open()); 209861d5cd2975725c730f519ed6ad71

invoke(new IAction() {    @Override
    public void perform() {
        editor.open();
    }
});

Si vous conservez la classe appelante Invoker, elle sera appelée comme suit :

new Invoker(() -> editor.open()).invoke();

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn