Classe aninhada estática em Java, por quê?

Eu estava olhando para o código Java para LinkedList e notei que ele fez uso de uma class aninhada estática, Entry .

 public class LinkedList ... { ... private static class Entry { ... } } 

Qual é a razão para usar uma class aninhada estática, em vez de uma class interna normal?

A única razão pela qual eu pude pensar, foi que o Entry não tem access a variables ​​de instância, então, de um ponto de vista OOP, ele tem melhor encapsulamento.

Mas eu pensei que poderia haver outras razões, talvez performance. O que poderia ser?

Nota. Espero ter corrigido meus termos, eu teria chamado de class interna estática, mas acho que isso está errado: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html

A página do Sun que você vincula tem algumas diferenças importantes entre as duas:

Uma class aninhada é um membro de sua class de inclusão. Classes aninhadas não estáticas (classs internas) têm access a outros membros da class envolvente, mesmo que sejam declaradas como privadas. Classes aninhadas estáticas não têm access a outros membros da class incluída.

Nota: Uma class aninhada estática interage com os membros da instância de sua class externa (e outras classs) como qualquer outra class de nível superior. Na verdade, uma class aninhada estática é comportamentalmente uma class de nível superior que foi aninhada em outra class de nível superior para conveniência de empacotamento.

Não há necessidade de LinkedList.Entry para ser class de nível superior, pois é usado apenas por LinkedList (existem algumas outras interfaces que também têm classs aninhadas estáticas chamado Entry , como Map.Entry – mesmo conceito). E como não precisa de access aos membros do LinkedList, faz sentido que seja estático – é uma abordagem muito mais limpa.

Como Jon Skeet aponta , eu acho que é uma idéia melhor se você estiver usando uma class aninhada é começar com estática, e então decidir se ela realmente precisa ser não-estática com base no seu uso.

Na minha opinião, a questão deve ser o contrário quando você vê uma class interna – ela realmente precisa ser uma class interna, com a complexidade extra e a referência implícita (em vez de explícita e mais clara, IMO) a uma instância? da class que contém?

Lembre-se, sou viciado como fã de C # – C # não tem o equivalente de classs internas, embora tenha tipos nesteds. Eu não posso dizer que eu senti falta de classs internas ainda 🙂

Existem problemas de retenção de memory não óbvios a serem considerados aqui. Como uma class interna não estática mantém uma referência implícita à sua class ‘outer’, se uma instância da class interna é fortemente referenciada, a instância externa também é fortemente referenciada. Isso pode levar a um arranhão na cabeça quando a class externa não é coletada como lixo, embora pareça que nada a faça referência.

Bem, por um lado, as classs internas não estáticas têm um campo oculto extra que aponta para a instância da class externa. Então, se a class Entry não fosse estática, além de ter access que não precisa, ela carregaria cerca de quatro pointers em vez de três.

Como regra geral, eu diria, se você definir uma class que está basicamente lá para agir como uma coleção de membros de dados, como uma “struct” em C, considere torná-la estática.

A class aninhada estática é como qualquer outra class externa, já que ela não tem access aos membros da class externa.

Apenas para conveniência de empacotamento, podemos agrupar classs aninhadas estáticas em uma class externa para fins de legibilidade. Além disso, não há outro caso de uso de class aninhada estática.

Exemplo para esse tipo de uso, você pode encontrar no arquivo Android R.java (resources). Res pasta do android contém layouts (contendo desenhos de canvas), pasta drawable (contendo imagens usadas para o projeto), pasta de valores (que contém constantes de string), etc.

Sine todas as pastas fazem parte da pasta Res, ferramenta android gera um arquivo R.java (resources) que internamente contém muitas classs aninhadas estáticas para cada uma das suas pastas internas.

Aqui está a aparência do arquivo R.java gerado em android: Aqui eles estão usando apenas para conveniência de embalagem.

 /* AUTO-GENERATED FILE. DO NOT MODIFY. * * This class was automatically generated by the * aapt tool from the resource data it found. It * should not be modified by hand. */ package com.techpalle.b17_testthird; public final class R { public static final class drawable { public static final int ic_launcher=0x7f020000; } public static final class layout { public static final int activity_main=0x7f030000; } public static final class menu { public static final int main=0x7f070000; } public static final class string { public static final int action_settings=0x7f050001; public static final int app_name=0x7f050000; public static final int hello_world=0x7f050002; } } 

A class interna estática é usada no padrão do construtor. A class interna estática pode instanciar sua class externa que possui apenas um construtor privado. Portanto, você pode usar a class interna estática para instanciar a class externa que possui apenas um construtor privado. Você não pode fazer o mesmo com a class interna, pois precisa ter o object da class externa criada antes de acessar a class interna.

 class OuterClass { private OuterClass(int x) { System.out.println("x: " + x); } static class InnerClass { public static void test() { OuterClass outer = new OuterClass(1); } } } public class Test { public static void main(String[] args) { OuterClass.InnerClass.test(); // OuterClass outer = new OuterClass(1); // It is not possible to create outer instance from outside. } } 

Isto irá produzir x: 1

Exemplo simples:

 package test; public class UpperClass { public static class StaticInnerClass {} public class InnerClass {} public static void main(String[] args) { // works StaticInnerClass stat = new StaticInnerClass(); // doesn't compile InnerClass inner = new InnerClass(); } } 

Se não for estático, a class não poderá ser instanciada exceto em uma instância da class superior (portanto, não no exemplo em que main é uma function estática)

De http://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html :

Use uma class aninhada não estática (ou class interna) se você precisar de access aos campos e methods não públicos de uma instância delimitadora. Use uma class aninhada estática se você não precisar desse access.

Uma das razões para estática versus normal tem a ver com o carregamento de class. Você não pode instanciar uma class interna no construtor de seu pai.

PS: Eu sempre entendi ‘nested’ e ‘interior’ para ser intercambiável. Pode haver nuances sutis nos termos, mas a maioria dos desenvolvedores de Java também entenderia.

Classes internas não estáticas podem resultar em vazamentos de memory, enquanto a class interna estática protegerá contra elas. Se a class externa contiver dados consideráveis, isso poderá diminuir o desempenho do aplicativo.

Usando uma class aninhada estática em vez de uma não-estática pode salvar espaços em alguns casos. Por exemplo: implementando um Comparator dentro de uma class, diga Student.

 public class Student { public static final Comparator BY_NAME = new ByName(); private final String name; ... private static class ByName implements Comparator { public int compare() {...} } } 

Em seguida, a static garante que a class Student tenha apenas um Comparador, em vez de instanciar uma nova sempre que uma nova instância de aluno for criada.

Eu não sei sobre diferença de desempenho, mas como você diz, a class aninhada estática não faz parte de uma instância da class que a contém. Parece mais simples criar uma class aninhada estática, a menos que você realmente precise que ela seja uma class interna.

É um pouco como eu sempre faço minhas variables ​​finais em Java – se elas não são finais, eu sei que há algo engraçado acontecendo com elas. Se você usar uma class interna em vez de uma class aninhada estática, deve haver um bom motivo.

Adestramento da class interna

  1. um tempo de uso
  2. suporta e melhora o encapsulamento
  3. legibilidade
  4. access de campo privado

Sem existir da class interna da class externa não existirá.

 class car{ class wheel{ } } 

Existem quatro tipos de class interna.

  1. class interna normal
  2. Método Local Classe Interna
  3. Classe interna anônima
  4. class interna estática

ponto —

  1. da class interna estática, só podemos acessar o membro estático da class externa.
  2. Dentro da class interna nós não podemos declarar o membro estático.
  3. inorder para invocar a class interna normal na área estática da class externa.

    Outer 0=new Outer(); Outer.Inner i= O.new Inner();

  4. inorder para invocar a class interna normal na área de instância da class externa.

    Inner i=new Inner();

  5. inorder para invocar a class interna normal fora da class externa.

    Outer 0=new Outer(); Outer.Inner i= O.new Inner();

  6. inside Inner class Esse ponteiro para a class interna.

    this.member-current inner class outerclassname.this--outer class

  7. para modificador aplicável de class interna é – público, padrão,

    final,abstract,strictfp,+private,protected,static

  8. outer $ inner é o nome do nome da class interna.

  9. class interna dentro do método de instância, então podemos acessar o campo estático e de instância da class externa.

Classe 10.inner dentro do método estático, em seguida, podemos acessar apenas o campo estático de

class externa.

 class outer{ int x=10; static int y-20; public void m1() { int i=30; final j=40; class inner{ public void m2() { // have accees x,y and j } } } }