Lorsque les classes internes ont été ajoutés à Java dans la version 1.1 de la langue qu'ils ont été initialement définie comme une transformation à 1,0 code compatible. Si vous regardez un exemple de cette transformation, je pense que ça va le rendre beaucoup plus claire de la façon dont un à l'intérieur de la classe fonctionne réellement.
Considérez le code de Ian Roberts réponse:
public class Foo {
int val;
public Foo(int v) { val = v; }
class Bar {
public void printVal() {
System.out.println(val);
}
}
public Bar createBar() {
return new Bar();
}
}
Lorsqu'il est transformé à 1.0 compatible code, que l'intérieur de la classe Bar
deviendrait quelque chose comme ceci:
class Foo$Bar {
private Foo this$0;
Foo$Bar(Foo outerThis) {
this.this$0 = outerThis;
}
public void printVal() {
System.out.println(this$0.val);
}
}
L'intérieur de la classe le nom est préfixé avec l'extérieur nom de la classe de manière à le rendre unique. Caché privé this$0
membre est ajouté que détient une copie de l'extérieur, this
. Et un caché constructeur est créé à l'initialisation de ce membre.
Et si vous regardez l' createBar
méthode, il serait transformé en quelque chose comme ceci:
public Foo$Bar createBar() {
return new Foo$Bar(this);
}
Donc, nous allons voir ce qui se passe lorsque vous exécutez le code suivant.
Foo f = new Foo(5);
Foo.Bar b = f.createBar();
b.printVal();
Nous avons d'abord instancier une instance de Foo
et initialiser l' val
membre à 5 (c'est à dire f.val = 5
).
Ensuite, nous appelons f.createBar()
, qui instancie une instance d' Foo$Bar
et initialise l' this$0
membre de la valeur de this
passée de createBar
(c - b.this$0 = f
).
Enfin, nous appelons b.printVal()
qui essaie d'imprimer b.this$0.val
qui f.val
, qui est de 5.
Maintenant, qui était un habitué de l'instanciation d'un intérieur de classe. Regardons ce qui se passe lors de l'instanciation Bar
provenant de l'extérieur de Foo
.
Foo f = new Foo(5);
Foo.Bar b = f.new Bar();
b.printVal();
L'application de notre 1.0 transformation de nouveau, que la deuxième ligne est devenue quelque chose comme ceci:
Foo$Bar b = new Foo$Bar(f);
C'est presque identique à l' f.createBar()
appel. De nouveau nous sommes de créer une instance de Foo$Bar
et initialisation de l' this$0
membre de f. Encore une fois, b.this$0 = f
.
Et à nouveau lorsque vous appelez b.printVal()
, vous imprimez b.thi$0.val
qui f.val
, qui est de 5.
L'essentiel à retenir est que l'intérieur de la classe a caché membre détenant une copie de l' this
à partir de l'extérieur de la classe. Lorsque vous instanciez un intérieur de classe de l'intérieur que l'extérieur de la classe, il implicitement initialisé avec la valeur courante de this
. Lorsque vous instanciez l'intérieur de la classe à partir de l'extérieur de l'extérieur de la classe, vous spécifiez explicitement l'instance de l'extérieur de la classe à utiliser, via le préfixe sur l' new
mot-clé.