Les classes internes sont-elles couramment utilisées en Java? Sont-ils "mauvais" et # 8221; [fermé]

StackOverflow https://stackoverflow.com/questions/1028850

  •  06-07-2019
  •  | 
  •  

Question

Les classes internes sont-elles couramment utilisées en Java? Sont-ils les mêmes que les classes imbriquées? Ou ont-ils été remplacés à Java par quelque chose de mieux? J'ai un livre sur la version 5 et son exemple utilise une classe interne, mais je pensais avoir lu que certaines classes internes étaient "mauvaises".

Je n'en ai aucune idée et espérais y réfléchir.

Merci.

Était-ce utile?

La solution

Les classes internes sont fréquemment utilisées et quelque chose de très similaire - les classes anonymes - est pratiquement indispensable, car ce sont les éléments les plus proches de Java pour les fermetures. Donc, si vous ne vous rappelez pas où vous avez entendu dire que les classes intérieures sont mauvaises, essayez de l’oublier!

Autres conseils

Ils ne sont pas "mauvais". En tant que tel.

Ils peuvent être victimes d'abus (classes internes de classes internes, par exemple). Dès que ma classe interne s'étend sur plus de quelques lignes, je préfère l'extraire dans sa propre classe. Cela facilite la lisibilité et les tests dans certains cas.

Il y en a un qui n'est pas immédiatement évident et qui mérite d'être rappelé. Toute classe interne non statique aura une référence implicite à la classe externe environnante (une référence implicite 'this'). Ce n’est normalement pas un problème, mais si vous venez de sérialiser la classe interne (par exemple, en utilisant XStream ), vous Vous constaterez que cela peut vous causer un chagrin inattendu.

Je ne pense pas qu'ils soient mauvais ou mauvais. Ils ne sont peut-être pas largement utilisés, mais ils ont de nombreux usages, les rappels en étant un. Un avantage particulier est qu’ils peuvent s’étendre à une classe différente de la classe externe, ce qui vous permet d’avoir plusieurs héritages.

Je dirais que l’un des problèmes des classes internes est que leur syntaxe est un peu "laide". C'est quelque chose qui décourage certaines personnes. Ici au travail, ils sont nombreux.

Un bon exemple de classe interne est l'implémentation d'itérateur pour un type de collection donné. C'est une classe qui implémente une interface publique, mais n'a pas d'activité existante sauf en association avec une autre classe. Cela vous permet de modéliser des choses que vous seriez obligé de faire avec l'opérateur ami en C ++.

Les classes internes non statiques peuvent masquer un problème de performances. Ils ont accès aux champs membres de la classe englobante, mais pas directement, mais via des accesseurs créés automatiquement. Ce sera plus lent que de simplement copier les membres de la classe englobante dans la classe interne.

D'autres problèmes avec les classes internes non statiques sont décrits ici

Ils sont utiles et peuvent être très couramment utilisés. Même si vous devez faire preuve de prudence lorsque vous en abusez, les fonctionnalités ne sont pas beaucoup plus susceptibles d’être utilisées que toute autre fonctionnalité linguistique.

L'essentiel à retenir est que vous allez échanger la flexibilité contre la simplicité et la cohésion en rendant les deux classes plus étroitement couplées. Vous souhaitez peut-être que les classes soient étroitement liées, mais vous renoncez à la possibilité de permuter de manière transparente d'autres classes à la place de votre classe intégrée en ne définissant pas votre classe à partir d'une interface en dehors de la classe contenante.

Considérez l'exemple suivant:

public class OuterClass {

private AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass() {
    @Override
    protected void printAboutme() {
        System.out.println("AnonymousInnerClass.printAboutMe.........");
        Class clazz = this.getClass();

        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {

            String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected");
            message = message + " " + field.getType().getSimpleName();
            message = message + " " + field.getName();

            System.out.println(message);
        }
    }
};

public void displayAnonymousInnerClass() {
    anonymousInnerClass.printAboutme();
}

public void displayStaticInnerClass() {
    NestedStaticClass staticInnerClass = new NestedStaticClass();
    staticInnerClass.printAboutMe();
}

public void displayInnerClass() {
    InnerClass innerClass = new InnerClass();
    innerClass.printAboutMe();
}

public void displayMethodInnerClass(){

    class MethodInnerClass {

        private String sampleField = "Method Inner Class";
        public void printAboutMe() {
            System.out.println("MethodInnerClass.printAboutMe.........");
            Class clazz = this.getClass();

            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {

                String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected");
                message = message + " " + field.getType().getSimpleName();
                message = message + " " + field.getName();

                System.out.println(message);
            }
        }
    }

    MethodInnerClass methodInnerClass = new MethodInnerClass();
    methodInnerClass.printAboutMe();
}

class InnerClass {
    private String sampleField = "Inner Class";
    public void printAboutMe() {
        System.out.println("InnerClass.printAboutMe.........");
        Class clazz = this.getClass();

        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {

            String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected");
            message = message + " " + field.getType().getSimpleName();
            message = message + " " + field.getName();

            System.out.println(message);
        }
    }
}


abstract class AnonymousInnerClass {
    protected String sampleField = "Anonymous Inner Class";
    protected abstract void printAboutme();
}

static class NestedStaticClass {
    private String sampleField = "NestedStaticClass";
    public void printAboutMe() {
        System.out.println("NestedStaticClass.printAboutMe.........");
        Class clazz = this.getClass();

        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {

            String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected");
            message = message + " " + field.getType().getSimpleName();
            message = message + " " + field.getName();

            System.out.println(message);
        }
    }
}

}

dans cet exemple, chaque type de classe imbriquée non statique est comparé à une classe imbriquée statique.Maintenant, si vous exécutez la méthode d'affichage de la classe externe pour chaque classe imbriquée, vous verrez la sortie de chaque méthode de la classe imbriquée printAboutMe (), qui a un code de réflexion pour imprimer toutes les variables membres des classes imbriquées.

Vous verrez pour les classes non imbriquées qu'il existe une variable membre supplémentaire autre que la chaîne de variable déclarée dans le code, qui n'est présente qu'au moment de l'exécution.

par exemple si nous exécutons le code suivant pour InnerClass. : -

public class NestedClassesDemo {

public static void main(String[] args) {
    OuterClass outerClass = new OuterClass();
    outerClass.displayInnerClass();
}

}

la sortie est comme ceci: -

InnerClass.printAboutMe.........
private String sampleField
protected OuterClass this<*>

Notez qu'il existe une variable membre mystère this $ 0 de type classe englobante (classe externe).

Il est maintenant clair que les classes internes conservent la référence à la classe externe. Ainsi, le scénario de l'image dans lequel vous transmettez la référence de la classe interne à une autre classe mondiale externe, puis la référence n'est jamais libérée, est fait référence à OuterClass, d'où la fuite.

Cela rend donc l'utilisation de classes internes mauvaise si elle n'est pas utilisée de manière prépondérante.

Il n’existe pas de tel cas avec les classes internes statiques. Veuillez exécuter toutes les méthodes d’affichage. De même, si vous rencontrez un problème dans le code, veuillez le signaler.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top