class OuterClass {
class InnerClass {
static int i = 100; // compile error
static void f() { } // compile error
}
}
Embora não seja possível acessar o campo estático com OuterClass.InnerClass.i
, se eu quiser registrar algo que deve ser estático, por exemplo, o número de objetos InnerClass criados, seria útil tornar esse campo estático. Então, por que Java proíbe campos / métodos estáticos em classes internas?
EDITAR: Eu sei como deixar o compilador feliz com a classe aninhada estática (ou classe interna estática), mas o que eu quero saber é por que o java proíbe campos / métodos estáticos dentro de classes internas (ou classe interna comum) de design de linguagem e aspectos de implementação, se alguém souber mais sobre isso.
java
inner-classes
static-members
Jichao
fonte
fonte
Respostas:
A ideia por trás das classes internas é operar no contexto da instância envolvente. De alguma forma, permitir variáveis e métodos estáticos contradiz essa motivação?
fonte
Porque essas classes internas são classes internas de "instância". Ou seja, eles são como um atributo de instância do objeto envolvente.
Visto que são classes de "instância", não faz nenhum sentido permitir
static
recursos, poisstatic
foi criado para funcionar sem uma instância em primeiro lugar.É como se você tentasse criar um atributo estático / instância ao mesmo tempo.
Veja o seguinte exemplo:
class Employee { public String name; }
Se você criar duas instâncias de funcionário:
Employee a = new Employee(); a.name = "Oscar"; Employee b = new Employee(); b.name = "jcyang";
Fica claro porque cada um tem seu valor pelo imóvel
name
, certo?O mesmo acontece com a classe interna; cada instância de classe interna é independente da outra instância de classe interna.
Portanto, se você tentar criar um
counter
atributo de classe, não haverá como compartilhar esse valor entre duas instâncias diferentes.class Employee { public String name; class InnerData { static count; // ??? count of which ? a or b? } }
Quando você cria a instância
a
eb
no exemplo acima, qual seria o valor correto para a variável estáticacount
? Não é possível determiná-lo, porque a existência daInnerData
classe depende totalmente de cada um dos objetos envolventes.É por isso que, quando a classe é declarada como
static
, ela não precisa mais de uma instância viva para viver a si mesma. Agora que não há dependência, você pode declarar livremente um atributo estático.Eu acho que isso parece reiterativo, mas se você pensar sobre as diferenças entre atributos de instância e classe, fará sentido.
fonte
final
, campos estáticos são permitidos na classe interna em java. Como você explica esse cenário?InnerClass
não pode terstatic
membros porque pertence a uma instância (deOuterClass
). Se você declararInnerClass
comostatic
desanexá-lo da instância, seu código será compilado.class OuterClass { static class InnerClass { static int i = 100; // no compile error static void f() { } // no compile error } }
BTW: você ainda será capaz de criar instâncias de
InnerClass
.static
neste contexto, permite que isso aconteça sem uma instância envolvente deOuterClass
.fonte
InnerClass
que não pertencem aOuterClass
, casos de ele fazer. As duas classes em si não têm essa relação. A questão de por que você não pode ter métodos estáticosInnerClass
ainda permanece.Na verdade, você pode declarar campos estáticos se eles forem constantes e forem escritos em tempo de compilação.
class OuterClass { void foo() { class Inner{ static final int a = 5; // fine static final String s = "hello"; // fine static final Object o = new Object(); // compile error, because cannot be written during compilation } } }
fonte
Como as classes internas são dependentes da instância da classe envolvente / Outer, a classe Outer precisa ser inicializada antes da inicialização da classe Inner.
Isso é o que JLS diz sobre a inicialização da classe. O que precisamos é, a classe T será inicializada se
Portanto, se a classe interna tiver um acesso de campo estático, isso causará a inicialização da classe interna, mas não garantirá que a classe envolvente seja inicializada.
Isso violaria algumas regras básicas . você pode pular para a última seção (para
two cases
) para evitar coisas noobUma coisa sobre , quando alguma é, ela se comportará como uma classe normal em todos os sentidos e está associada à classe Externa.
static nested
class
nested class
static
Mas o conceito de
Inner class
/ é será associado à classe externa / envolvente. Observe o associado à instância, não à classe. Agora, associar a instância significa claramente que (a partir do conceito de variável de instância ) ela existirá dentro de uma instância e será diferente entre as instâncias.non-static
nested class
instance
Agora, quando tornamos algo estático, esperamos que seja inicializado quando a classe estiver sendo carregada e deve ser compartilhado entre todas as instâncias. Mas por serem não estáticas, mesmo as próprias classes internas ( você pode definitivamente esquecer a instância da classe interna por enquanto ) não são compartilhadas com todas as instâncias da classe externa / envolvente ( pelo menos conceitualmente ), então como podemos esperar que alguma variável da classe interna será compartilhado entre todas as instâncias da classe interna.
Portanto, se o Java permitir o uso de variáveis estáticas dentro de uma classe aninhada não estática. haverá dois casos .
context of instance
(variável de instância). Então é um NÃO.fonte
Aqui está a motivação que considero mais adequada para este "limite": você pode implementar o comportamento de um campo estático de uma classe interna como um campo de instância do objeto externo; Portanto, você não precisa de campos / métodos estáticos . O comportamento que quero dizer é que todas as instâncias de classe interna de algum objeto compartilham um campo (ou método).
Então, suponha que você queira contar todas as instâncias de classe interna, você faria:
public class Outer{ int nofInner; //this will count the inner class //instances of this (Outer)object //(you know, they "belong" to an object) static int totalNofInner; //this will count all //inner class instances of all Outer objects class Inner { public Inner(){ nofInner++; totalNofInner++; } } }
fonte
final
então?Em palavras simples, classes internas não estáticas são variáveis de instância para classe externa e são criadas apenas quando uma classe externa é criada e um objeto de classe externa é criado em tempo de execução, enquanto variáveis estáticas são criadas no tempo de carregamento da classe. Portanto, a classe interna não estática é algo do tempo de execução, por isso que a estática não faz parte de uma classe interna não estática.
NOTA: trate as classes internas sempre como uma variável para uma classe externa, elas podem ser estáticas ou não estáticas como quaisquer outras variáveis.
fonte
static final
constantes.Porque causaria ambigüidade no significado de "estático".
Retirado de "Core Java SE 9 for the Impacient" por Cay S. Horstmann. Pág. 90 Capítulo 2.6.3
fonte
Do Java 16 em diante, esse não é mais o caso. Citando JEP 395 (sobre a finalização dos registros):
Na verdade, o código a seguir pode ser compilado com Java 16 (tentado com 16.ea.27):
public class NestingClasses { public class NestedClass { static final String CONSTANT = new String( "DOES NOT COMPILE WITH JAVA <16"); static String constant() { return CONSTANT; } } }
fonte
Eu acho que é para consistência. Embora não pareça haver nenhuma limitação técnica para isso, você não seria capaz de acessar membros estáticos da classe interna de fora, ou seja,
OuterClass.InnerClass.i
porque a etapa do meio não é estática.fonte
static final
constantes.