São classes internas comumente usado em Java? Eles são “maus”? [fechadas]

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

  •  06-07-2019
  •  | 
  •  

Pergunta

Você classes internas comumente usado em Java? São estes o mesmo que classes aninhadas? Ou estes foram substituídos em Java por algo melhor? Eu tenho um livro em versão 5 e tem um exemplo usando uma classe interna, mas eu pensei que eu li somewere que classes internas eram "maus".

Eu não tenho idéia e estava esperando por pensamentos sobre ele.

Obrigado.

Foi útil?

Solução

Classes internas são freqüentemente usados, e algo muito similar - classes anônimas - são praticamente indispensável, pois eles são a coisa mais próxima Java tem de encerramentos. Então, se você não consegue se lembrar onde você ouviu que classes internas são ruins, tentar esquecê-lo!

Outras dicas

Eles não são "mau" como tal.

Eles podem ser objecto de abuso (classes internas de classes internas, por exemplo). Assim que meus vãos classe interna mais do que algumas linhas, eu prefiro para extraí-lo em sua própria classe. Ela ajuda a legibilidade, e testando em alguns casos.

Há uma pegadinha que não é imediatamente óbvio, e vale a pena lembrar. Qualquer não static classe interna terá uma referência implícita a classe exterior circundante (um 'isto' referência implícita). Isto normalmente não é um problema, mas se você vir a serialização a classe interna (por exemplo, usando XStream ), você verá que isso pode causar-lhe sofrimento inesperado.

Eu não acho que eles são maus ou ruim. Talvez eles não são amplamente utilizados, mas eles têm muitos usos, chamadas de retorno é um deles. Uma vantagem especial é que eles podem se estender de uma classe diferente da classe externa, para que pudesse ter herança múltipla.

Eu diria que um dos problemas com classes internas é que sua sintaxe é um pouco "feio". Isso é algo que desencoraja algumas pessoas. Aqui no trabalho há muitos deles.

Um bom exemplo de uma classe interna é a implementação iterador para um determinado tipo de coleção. Sua classe A que implementa uma interface pública, mas não tem nenhum negócio existente, exceto em associação com outra classe. Ele permite modelar coisas que em C ++ você seria forçado a ver com o operador amigo.

classes internas não-estáticos pode esconder um problema de desempenho. Eles têm acesso a campos de membros da classe delimitador, mas não diretamente, mas através de getters que são criados automaticamente. Este será mais lento, em seguida, apenas copiando os membros da classe delimitador para a classe interna.

Alguns outros problemas com classes internas não-estáticos são descritos aqui

Eles são úteis e podem ser muito utilizado. Enquanto você deve ser cauteloso sobre a abusar da funcionalidade, eles não são muito mais susceptíveis de ser abusado do que qualquer outro recurso de linguagem.

A principal coisa a lembrar é que você está indo para o comércio flexibilidade para a simplicidade e a coesão, fazendo as duas classes mais fortemente acoplados. Você pode querer as classes a serem fortemente ligada, mas você está dando-se a capacidade de forma transparente trocar outras classes no lugar do que é atualmente seu classe incorporada por não definir sua classe a partir de um fora de interface da classe que contém.

Considere o exemplo seguinte:

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

}

Neste exemplo, há a comparação de cada tipo de classe aninhada não estático com class.Now aninhada estática se você executar método da classe Outer exibição para cada classe aninhada você verá uma saída de cada classe aninhada printAboutMe método (), que tem algum código reflexão para imprimir todas as variáveis ??de membro de classes aninhadas.

Você vai ver por classes não aninhados há uma variável de membro adicional que não seja variável string declarado no código, que só está presente em tempo de execução.

Por exemplo, se nós executarmos seguinte código para InnerClass. : -

public class NestedClassesDemo {

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

}

saída é assim: -

InnerClass.printAboutMe.........
private String sampleField
protected OuterClass this$0

Nota existe membro do mistério variável dessa $ 0 do tipo envolvendo class (classe Outer).

Agora você está claro que classes internas manter referência ao cenário externo imagem class.So onde você passar de referência da classe interna para outra classe mundo exterior e em seguida, referência nunca é liberado para, por sua vez OuterClass também é referenciado, daí vazar.

o que faz usando interior aulas ruim se não for usado prpperly.

Não caso com classes.Please estática interior executar toda a exposição methods.Also se algum problema no código por favor ponto fora.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top