Une brève introduction aux classes internes anonymes est donnée dans le chapitre sur l'amélioration de Java - Explication détaillée des classes internes. Cependant, il existe de nombreux autres problèmes détaillés avec les classes internes, c'est pourquoi ce blog en a été dérivé. Dans ce blog, vous pouvez en apprendre davantage sur l'utilisation des classes internes anonymes, les éléments à prendre en compte dans les classes internes anonymes, comment initialiser les classes internes anonymes et pourquoi les paramètres formels utilisés par les classes internes anonymes doivent être définitifs.
1. Utiliser des classes internes anonymes Classes internes
Étant donné que les classes internes anonymes n'ont pas de nom, la façon dont elles sont créées est un peu étrange. Le format de création est le suivant :
new 父类构造器(参数列表)|实现接口() { //匿名内部类的类体部分 }
Ici nous voyons que pour utiliser des classes internes anonymes nous devons hériter d'une classe parent ou implémenter une interface. Bien entendu, nous ne pouvons hériter que d'une seule classe parent ou implémenter une interface. . En même temps, il n'a pas de mot-clé class, car les classes internes anonymes utilisent directement new pour générer une référence à un objet. Bien entendu, cette référence est implicite.
public abstract class Bird { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public abstract int fly(); } public class Test { public void test(Bird bird){ System.out.println(bird.getName() + "能够飞 " + bird.fly() + "米"); } public static void main(String[] args) { Test test = new Test(); test.test(new Bird() { public int fly() { return 10000; } public String getName() { return "大雁"; } }); } } ------------------ Output: 大雁能够飞 10000米
Dans la classe Test, la méthode test() accepte un paramètre de type Bird. En même temps, nous savons qu'il n'y a aucun moyen de créer directement une classe abstraite. Nous devons d'abord avoir une implémentation. classe avant de pouvoir la créer une nouvelle instance de classe. Utilisez donc la classe interne anonyme directement dans la méthode principale pour créer une instance Bird.
Puisqu'une classe interne anonyme ne peut pas être une classe abstraite, elle doit implémenter toutes les méthodes abstraites dans sa classe ou interface parent abstraite.
Ce code de classe interne anonyme peut en fait être divisé sous la forme suivante :
public class WildGoose extends Bird{ public int fly() { return 10000; } public String getName() { return "大雁"; } } WildGoose wildGoose = new WildGoose(); test.test(wildGoose);
Ici, le système créera un objet de la classe anonyme héritée de la classe Bird, et l'objet être transformé Une référence au type Bird.
Il y a un défaut dans l'utilisation de classes internes anonymes, c'est-à-dire qu'elles ne peuvent être utilisées qu'une seule fois lors de la création d'une classe interne anonyme, cela créera immédiatement une instance de la classe et la définition de la classe. la classe disparaîtra immédiatement. Les classes internes anonymes ne pourront donc pas être réutilisées. Pour l'exemple ci-dessus, si nous devons utiliser la classe interne dans la méthode test() plusieurs fois, il est recommandé de redéfinir la classe au lieu d'utiliser une classe interne anonyme.
2. Notes
Dans le processus d'utilisation de classes internes anonymes, nous devons prêter attention aux points suivants :
1. Lors de l'utilisation de classes internes anonymes, nous devons hériter d'une classe ou implémenter une interface, mais vous ne pouvez pas avoir les deux en même temps, vous ne pouvez qu'hériter d'une classe ou implémenter une interface.
2. Les constructeurs ne peuvent pas être définis dans des classes internes anonymes.
3. Il ne peut y avoir de variables membres statiques ni de méthodes statiques dans les classes internes anonymes.
4. Les classes internes anonymes sont des classes internes locales, donc toutes les restrictions sur les classes internes locales s'appliquent également aux classes internes anonymes.
5. Une classe interne anonyme ne peut pas être abstraite. Elle doit implémenter toutes les méthodes abstraites de la classe héritée ou de l'interface implémentée.
3. Pourquoi les paramètres formels utilisés doivent-ils être définitifs
Fichier de référence : http://android.blog.51cto.com/268543/384844
Lorsque nous transmettons des paramètres à des classes internes anonymes, si le paramètre formel doit être utilisé dans la classe interne, alors le paramètre formel doit être final. C'est-à-dire : lorsque le paramètre formel de la méthode doit être utilisé dans la classe interne, le paramètre formel doit être final.
Pourquoi faut-il que ce soit définitif ?
Tout d'abord, nous savons qu'une fois la classe interne compilée avec succès, elle générera un fichier de classe. Ce fichier de classe n'est pas le même fichier de classe que la classe externe. Il ne conserve que les références à la classe externe. . Lorsque les paramètres transmis par la classe externe doivent être appelés par la classe interne, du point de vue du programme Java, ils sont appelés directement :
public class OuterClass { public void display(final String name,String age){ class InnerClass{ void display(){ System.out.println(name); } } } }
D'après le code ci-dessus, il semble que le nom Le paramètre doit être appelé directement par la classe interne ? En fait, ce n'est pas le cas. L'opération réelle après la compilation Java est la suivante :
public class OuterClass$InnerClass { public InnerClass(String name,String age){ this.InnerClass$name = name; this.InnerClass$age = age; } public void display(){ System.out.println(this.InnerClass$name + "----" + this.InnerClass$age ); } }
Ainsi, à partir du code ci-dessus, la classe interne n'appelle pas directement les paramètres passés par la méthode, mais utilise son propre constructeur dans les paramètres est sauvegardé, et ce qui est appelé par sa propre méthode interne est en fait ses propres propriétés plutôt que les paramètres transmis par la méthode externe.
直到这里还没有解释为什么是final?在内部类中的属性和外部方法的参数两者从外表上看是同一个东西,但实际上却不是,所以他们两者是可以任意变化的,也就是说在内部类中我对属性的改变并不会影响到外部的形参,而然这从程序员的角度来看这是不可行的,毕竟站在程序的角度来看这两个根本就是同一个,如果内部类该变了,而外部方法的形参却没有改变这是难以理解和不可接受的,所以为了保持参数的一致性,就规定使用final来避免形参的不改变。
简单理解就是,拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变。
故如果定义了一个匿名内部类,并且希望它使用一个其外部定义的参数,那么编译器会要求该参数引用是final的。
四、匿名内部类初始化
我们一般都是利用构造器来完成某个实例的初始化工作的,但是匿名内部类是没有构造器的!那怎么来初始化匿名内部类呢?使用构造代码块!利用构造代码块能够达到为匿名内部类创建一个构造器的效果。
public class OutClass { public InnerClass getInnerClass(final int age,final String name){ return new InnerClass() { int age_ ; String name_; //构造代码块完成初始化工作 { if(0 < age && age < 200){ age_ = age; name_ = name; } } public String getName() { return name_; } public int getAge() { return age_; } }; } public static void main(String[] args) { OutClass out = new OutClass(); InnerClass inner_1 = out.getInnerClass(201, "chenssy"); System.out.println(inner_1.getName()); InnerClass inner_2 = out.getInnerClass(23, "chenssy"); System.out.println(inner_2.getName()); } }
以上就是 java提高篇(九)-----详解匿名内部类的内容,更多相关内容请关注PHP中文网(m.sbmmt.com)!