Domanda

Le classi interne sono comunemente usate in Java? Sono uguali alle classi nidificate? O questi sono stati sostituiti in Java da qualcosa di meglio? Ho un libro sulla versione 5 e ha un esempio che usa una classe interna, ma ho pensato di leggere da qualche parte che le classi interne erano "cattive."

Non ne ho idea e speravo di pensarci.

Grazie.

È stato utile?

Soluzione

Le classi interne sono usate frequentemente e qualcosa di molto simile - le classi anonime - sono praticamente indispensabili, in quanto sono la cosa più vicina a chiusure Java. Quindi se non ricordi dove hai sentito che le classi interne sono cattive, prova a dimenticartene!

Altri suggerimenti

Non sono " male " come tale.

Possono essere soggetti ad abusi (classi interne di classi interne, per esempio). Non appena la mia classe interiore si estende su più di alcune righe, preferisco estrarla nella sua classe. Aiuta la leggibilità e il test in alcuni casi.

C'è un gotcha che non è immediatamente ovvio e che vale la pena ricordare. Qualsiasi classe interna non statica avrà un riferimento implicito alla classe esterna circostante (un riferimento implicito "questo"). Normalmente questo non è un problema, ma se vieni a serializzare la classe interna (ad esempio, utilizzando XStream ), tu Scoprirò che questo può causare un dolore inaspettato.

Non penso che siano cattivi o cattivi. Forse non sono ampiamente utilizzati, ma hanno molti usi, i callback sono uno di questi. Un vantaggio speciale è che possono estendersi da una classe diversa rispetto alla classe esterna, quindi potresti avere ereditarietà multiple.

Direi che uno dei problemi con le classi interne è che la loro sintassi è in qualche modo "brutta". È qualcosa che scoraggia alcune persone. Qui al lavoro ce ne sono molti.

Un buon esempio di una classe interna è l'implementazione dell'iteratore per un determinato tipo di raccolta. È una classe che implementa un'interfaccia pubblica, ma non ha attività commerciali se non in associazione con un'altra classe. Ti permette di modellare cose che in C ++ saresti costretto a fare con l'operatore amico.

Le classi interne non statiche possono nascondere un problema di prestazioni. Hanno accesso ai campi membro nella classe che lo racchiude, ma non direttamente, ma tramite getter che vengono creati automaticamente. Questo sarà più lento quindi solo copiando i membri della classe che racchiude la classe interna.

Alcuni altri problemi con le classi interne non statiche sono descritti qui

Sono utili e possono essere usati molto comunemente. Anche se dovresti essere cauto sull'abuso della funzionalità, non sono molto più suscettibili di essere abusati di qualsiasi altra funzione linguistica.

La cosa fondamentale da ricordare è che scambierai flessibilità per semplicità e coesione rendendo le due classi più strettamente accoppiate. Puoi volere che le classi siano strettamente legate, ma stai rinunciando alla possibilità di scambiare in modo trasparente altre classi al posto di quella che è attualmente la tua classe incorporata non definendo la tua classe da un'interfaccia al di fuori della classe contenente.

Prendi in considerazione il seguente esempio:

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);
        }
    }
}

}

in questo esempio viene confrontato ogni tipo di classe nidificata non statica con la classe nidificata statica. Ora, se si esegue il metodo di visualizzazione della classe esterna per ciascuna classe nidificata, verrà visualizzato l'output di ogni classe nidificata metodo printAboutMe (), che ha del codice di riflessione per stampare tutte le variabili membro delle classi nidificate.

Vedrai che per le classi non nidificate esiste una variabile membro aggiuntiva diversa dalla stringa di variabile dichiarata nel codice, che è presente solo in fase di esecuzione.

per esempio se eseguiamo il seguente codice per InnerClass. : -

public class NestedClassesDemo {

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

}

l'output è così: -

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

Nota che esiste una variabile membro misteriosa questo $ 0 di tipo che racchiude la classe (classe esterna).

Ora sei chiaro che le classi interne mantengono il riferimento alla classe esterna. Quindi, viene fatto riferimento anche allo scenario di immagine in cui passi il riferimento della classe interna ad altre classi del mondo esterno e quindi non viene mai fatto riferimento al riferimento a cui OuterClass a sua volta fa riferimento, quindi perdita.

Quindi questo rende cattivo l'uso delle classi interne se non usato prpperly.

Non esiste un caso simile con le classi interne statiche. Esegui tutti i metodi di visualizzazione. In caso di problemi con il codice, fai attenzione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top