内部类和匿名内部类的用法
一、内部类:
(1)内部类的同名方法
内部类可以调用外层类的方法,如果内部类有同名方法必须使用"OuterClass.this.MethodName()"格式调用(其中OuterClass与MethodName换成实际外部类名及其方法;this为关键字,表示对外部类的引用);若内部类无同名方法可以直接调用外围类的方法。
但外围类无法直接调用内部类的private方法,外部类同样无法直接调用其它类的private方法。注意:内部类直接使用外部类的方法与该方法的权限与是否static无关,它取决于内部类是否有同名方法。
package innerclass; public class OuterClass { private void outerMethod() { System.out.println("It's Method of OuterClass"); } public static void main(String[] args) { OuterClass t = new OuterClass(); OuterClass.Innerclass in = t.new Innerclass(); in.innerMethod(); } class Innerclass { public void innerMethod() { OuterClass.this.outerMethod();// 内部类成员方法与外部类成员方法同名时,使用this调用外部类的方法 outerMethod();// 内部类没有同名方法时执行外部类的方法 } private void outerMethod() { System.out.println("It's Method of Innerclass"); } } }
输出结果为:
It's Method of OuterClass It's Method of Innerclass
(2)内部类的实例化
内部类实例化不同于普通类,普通类可以在任意需要的时候实例化,而内部类必须在外层类实例化以后方可实例化,并与外部类建立关系
因此在外部类中的非static方法中,是可以实例化内部类对象
private void outerMethod() { System.out.println("It's Method of OuterClass"); Innerclass in = new Innerclass();//在外部类的outerMethod方法中实例化内部类是可以啊 }
但在static方法中,就要注意啦!!!!不能在static方法中直接new内部类,否则出现错误:
No enclosing instance of type OuterClass is accessible. Must qualify the allocation with an enclosing instance of type OuterClass (e.g. x.new A() where x is an instance of OuterClass).
这是因为静态方法是在类实例化之前就可以使用的,通过类名调用,这时动态内部类都还没实例化呢,怎么用,总不能调用一个不存在的东西吧。
如果想在Static方法中new内部类,可以把内部类声明为Static
public class OuterClass { private void outerMethod() { System.out.println("It's Method of OuterClass"); } public static void main(String[] args) { Innerclass in = new Innerclass(); in.innerMethod(); } static class Innerclass {//把内部类声明为static public void innerMethod() { System.out.println("It's Method of innerMethod"); } } }
当然,一般不使用static的方式,而是推荐这种方法:x.new A() ,其中 x是外部类OuterClass的实例,A是内部类Innerclass
package innerclass; public class OuterClass { private void outerMethod() { System.out.println("It's Method of OuterClass"); } public static void main(String[] args) { OuterClass.Innerclass in = new OuterClass().new Innerclass();//使用x.new A()的方式 in.innerMethod(); } class Innerclass { public void innerMethod() { System.out.println("It's Method of innerMethod"); } } }
x.new A() ,其中 x是外部类OuterClass的实例,A是类部类Innerclass,当然可以拆分如下,这样就显然很明白啦:
public static void main(String[] args) { OuterClass out = new OuterClass();//外部实例 OuterClass.Innerclass in = out.new Innerclass();//外部实例.new 外部类 in.innerMethod(); }
(3)什么情况下使用内部类
典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外层类的对象。所以你可以认为内部类提供了某种进
入其外层类的窗口。
使用内部类最吸引人的原因是:每个内部类都能独立地继承自一个(接口的)实现,所以无论外层类是否已经继承了某个(接口的)实
现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角
度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。
(4)在静态方法中实例化内部类例子:(内部类放在静态方法中)
package javatest2; public class JavaTest2 { public static void main(String[] args) { class Boy implements Person { public void say() {// 匿名内部类自定义的方法say System.out.println("say方法调用"); } @Override public void speak() {// 实现接口的的方法speak System.out.println("speak方法调用"); } } Person per = new Boy(); per.speak();// 可调用 per.say();// 不能调用 } } interface Person { public void speak(); }
per.speak()可调用,而per.say()不能调用,这时因为per是Person对象,要想调用子类的方法,可以强制向下转型为:((Boy) per).say();或者直接改为Boy per = new Boy();。从中可发现,要想调用内部类的自定义的方法,必须通过内部类的对象来调用。那么,匿名内部类连名字都没有,怎么调用内部类自定义的方法?
(二)匿名内部类
匿名内部类也就是没有名字的内部类正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写,但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口,但最多只能继承一个父类,或实现一个接口。
关于匿名内部类还有如下两条规则:
1)匿名内部类不能是抽象类,因为系统在创建匿名内部类的时候,会立即创建内部类的对象。因此不允许将匿名内部类定义成抽象类。
2)匿名内部类不等定义构造器(构造方法),因为匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义实例初始化块,
怎样判断一个匿名类的存在啊?看不见名字,感觉只是父类new出一个对象而已,没有匿名类的名字。
先看段伪代码
abstract class Father(){ .... } public class Test{ Father f1 = new Father(){ .... } //这里就是有个匿名内部类 }
一般来说,new 一个对象时小括号后应该是分号,也就是new出对象该语句就结束了。但是出现匿名内部类就不一样,小括号后跟的是大括号,大括号中是该new 出对象的具体的实现方法。因为我们知道,一个抽象类是不能直接new 的,必须先有实现类了我们才能new出它的实现类。上面的伪代码就是表示new 的是Father的实现类,这个实现类是个匿名内部类。
其实拆分上面的匿名内部类可为:
class SonOne extends Father{ ... //这里的代码和上面匿名内部类,大括号中的代码是一样的 } public class Test{ Father f1 = new SonOne() ; }
先看一个例子,体会一下匿名内部类的用法:
运行结果:eat something
可以看到,我们直接将抽象类Person中的方法在大括号中实现了,这样便可以省略一个类的书写。并且,匿名内部类还能用于接口上
public class JavaTest2 { public static void main(String[] args) { Person per = new Person() { public void say() {// 匿名内部类自定义的方法say System.out.println("say方法调用"); } @Override public void speak() {// 实现接口的的方法speak System.out.println("speak方法调用"); } }; per.speak();// 可调用 per.say();// 出错,不能调用 } } interface Person { public void speak(); }
这里per.speak()是可以正常调用的,但per.say()不能调用,为什么呢?注意Person per = new Person()创建的是Person的对象,而非匿名内部类的对象。其实匿名内部类连名字都没有,你咋实例对象去调用它的方法呢?但继承父类的方法和实现的方法是可以正常调用的,本例子中,匿名内部类实现了接口Person的speak方法,因此可以借助Person的对象去调用。
若你确实想调用匿名内部类的自定义的方法say(),当然也有方法:
(1)类似于speak方法的使用,先在Person接口中声明say()方法,再在匿名内部类中覆写此方法。
(2)其实匿名内部类中隐含一个匿名对象,通过该方法可以直接调用say()和speak()方法;代码修改如下:
public class JavaTest2 { public static void main(String[] args) { new Person() { public void say() {// 匿名内部类自定义的方法say System.out.println("say方法调用"); } @Override public void speak() {// 实现接口的的方法speak System.out.println("speak方法调用"); } }.say();// 直接调用匿名内部类的方法 } } interface Person { public void speak(); }
更多内部类和匿名内部类的用法相关文章请关注PHP中文网!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Les classes internes anonymes peuvent provoquer des fuites de mémoire. Le problème est qu'elles contiennent une référence à la classe externe, empêchant ainsi la classe externe d'être récupérée. Les solutions incluent : 1. Utiliser des références faibles. Lorsque la classe externe n'est plus détenue par une référence forte, le garbage collector recyclera immédiatement l'objet de référence faible ; 2. Utiliser des références logicielles lorsqu'il sera utilisé. a besoin de mémoire pendant le garbage collection. Ce n'est qu'alors que l'objet de référence logiciel est recyclé. En combat réel, comme dans les applications Android, le problème de fuite de mémoire provoqué par des classes internes anonymes peut être résolu en utilisant des références faibles, de sorte que la classe interne anonyme puisse être recyclée lorsque l'écouteur n'est pas nécessaire.

Les classes internes anonymes sont des classes internes spéciales en Java qui n'ont pas de nom explicite et sont créées via la nouvelle expression. Elles sont principalement utilisées pour implémenter des interfaces spécifiques ou étendre des classes abstraites et sont utilisées immédiatement après la création. Les modèles de conception de classe interne anonymes courants incluent : Modèle d’adaptateur : convertit une interface en une autre interface. Modèle de stratégie : définition et algorithmes de remplacement. Modèle d'observateur : enregistrez les observateurs et gérez les événements. C'est très utile dans des applications pratiques, telles que le tri d'un TreeSet par longueur de chaîne, la création de threads anonymes, etc.

Les classes internes anonymes sont utilisées en Java en tant que classes internes spéciales qui facilitent le sous-classement, la simplification du code et la gestion des événements (tels que les clics sur des boutons). Les cas pratiques incluent : Gestion des événements : utilisez des classes internes anonymes pour ajouter des écouteurs d'événements de clic pour les boutons. Transformation des données : triez les collections à l'aide de la méthode Collections.sort et d'une classe interne anonyme comme comparateur.

La durée de vie d'une classe interne anonyme est déterminée par sa portée : Classe interne locale à la méthode : valide uniquement dans la portée de la méthode qui l'a créée. Classe interne du constructeur : liée à l'instance de classe externe et libérée lorsque l'instance de classe externe est libérée. Classes internes statiques : chargées et déchargées en même temps que les classes externes.

Erreur d'utilisation de classe interne anonyme : accès à une variable hors de portée en interceptant une exception non déclarée dans un environnement non thread-safe

Le problème de performances des classes internes anonymes est qu'elles sont recréées à chaque fois qu'elles sont utilisées, ce qui peut être optimisé grâce aux stratégies suivantes : 1. Stocker les classes internes anonymes dans des variables locales 2. Utiliser des classes internes non statiques 3. Utiliser lambda ; expressions. Des tests pratiques montrent que l'optimisation de l'expression lambda a le meilleur effet.

Les expressions Lambda, comme alternative aux classes internes anonymes, offrent un moyen plus concis de définir l'implémentation d'interfaces fonctionnelles : utilisez la syntaxe courte (paramètres)->expression pour définir des fonctions anonymes. Convient aux situations où des interfaces fonctionnelles doivent être implémentées (une seule méthode abstraite). Peut simplifier des tâches telles que le tri de liste et la définition de thread.

Les classes internes anonymes ne conviennent pas lorsque : besoin d'accéder à des membres privés, besoin de plusieurs instances, besoin d'héritage, besoin d'accéder à des types génériques
