Classe statique imbriquée en Java, pourquoi?
je regardais le code Java pour LinkedList
et j'ai remarqué qu'il utilisait une classe statique imbriquée, Entry
.
public class LinkedList<E> ... {
...
private static class Entry<E> { ... }
}
Quelle est la raison d'utiliser une classe statique imbriquée, plutôt qu'une classe intérieure normale?
la seule raison à laquelle je pouvais penser, était que L'entrée n'a pas accès aux variables d'instance, donc d'un point de vue OOP il a une meilleure encapsulation.
mais j'ai pensé qu'il pourrait y avoir d'autres raisons, peut-être la performance. Ce qui pourrait-il être?
Note. J'espère que j'ai eu mes termes exacts, Je l'aurais appelé une classe intérieure statique, mais je pense que c'est faux: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html
13 réponses
la page de soleil que vous liez a quelques différences clés entre les deux:
une classe emboîtée est un membre de la classe qui l'entoure. Les classes imbriquées Non statiques (classes intérieures) ont accès à d'autres membres de la classe qui les entoure, même si elles sont déclarées privées. Statique classes imbriquées n'ont pas accès à d'autres membres de la classe englobante.
...Note: une classe statique imbriquée interagit avec la instance membres de sa classe externe (et d'autres classes) comme n'importe quelle autre classe de premier niveau. en effet, une classe statique imbriquée est une classe comportementale de haut niveau qui a été imbriquée dans une autre classe de haut niveau pour la commodité de l'emballage.
il n'est pas nécessaire que LinkedList.Entry
soit une classe supérieure car il s'agit de seulement utilisé par LinkedList
(il existe d'autres interfaces qui ont également des classes statiques imbriquées nommé Entry
, tel que Map.Entry
- même concept). Et comme il n'a pas besoin d'accéder aux membres de LinkedList, il est logique qu'il soit statique - c'est une approche beaucoup plus propre.
comme Jon Skeet souligne , je pense que c'est une meilleure idée si vous utilisez une classe imbriquée est de commencer par elle étant statique, et ensuite décider si elle a vraiment besoin d'être non-statique basé sur votre utilisation.
à mon avis, la question devrait être le contraire chaque fois que vous voyez une classe intérieure - est-il vraiment besoin d'être une classe intérieure, avec la complexité supplémentaire et la référence implicite (plutôt que explicite et plus claire, IMO) à une instance de la classe contenant?
rappelez - vous, je suis biaisé comme un C# fan-c# n'a pas l'équivalent des classes intérieures, bien qu'il ait des types imbriqués. Je ne peux pas dire que j'ai manqué les cours intérieurs. :)
il y a des problèmes non évidents de mémorisation à prendre en compte ici. Comme une classe intérieure non statique maintient une référence implicite à sa classe "extérieure", si une instance de la classe intérieure est fortement référencée, alors l'instance extérieure est fortement référencée Aussi. Cela peut conduire à quelques égratignures de tête quand la classe extérieure n'est pas des ordures collectées, même si il semble que rien ne s'y réfère.
Eh bien, pour une chose, les classes intérieures non statiques ont un champ caché supplémentaire qui pointe vers l'instance de la classe extérieure. Donc si la classe D'entrée n'était pas statique, alors en plus d'avoir un accès dont elle n'a pas besoin, elle porterait autour de quatre pointeurs au lieu de trois.
en règle générale, je dirais, si vous définissez une classe qui est essentiellement là pour agir comme une collecte de données membres, comme un" struct " en C, envisager de le rendre statique.
la classe statique imbriquée est comme n'importe quelle autre classe extérieure, car elle n'a pas accès aux membres de la classe extérieure.
juste pour la commodité de l'emballage, nous pouvons grouper les classes statiques imbriquées en une classe extérieure pour des raisons de lisibilité. En dehors de cela il n'y a pas d'autre cas d'utilisation de classe statique emboîtée.
exemple pour ce type d'utilisation, vous pouvez trouver dans Android R.java (resources) file. Le dossier Res d'android contient des mises en page (contenant l'écran les dessins), drawable dossier (contenant des images utilisées pour le projet), les valeurs de dossier (qui contient les constantes de chaîne), etc..
Sine tous les dossiers font partie du dossier Res, l'outil android génère un R.java (resources) fichier qui contient en interne beaucoup de classes statiques imbriquées pour chacun de leurs dossiers intérieurs.
Voici l'apparence et la sensation de R.java fichier généré sur android: Ici, ils sont utilisés uniquement pour la commodité de l'emballage.
/* 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;
}
}
est utilisée dans le dessin du constructeur. La classe intérieure statique peut instancier sa classe extérieure qui n'a que le constructeur privé. Ainsi, vous pouvez utiliser la classe intérieure statique pour instancier la classe extérieure qui n'a que le constructeur privé. vous ne pouvez pas faire la même chose avec la classe intérieure que vous devez avoir objet de la classe extérieure créé avant d'accéder à la classe intérieure.
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.
}
}
cette sortie x: 1
exemple Simple:
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();
}
}
si non statique la classe ne peut pas être instanciée sauf dans une instance de la classe supérieure (donc pas dans l'exemple où main est une fonction statique)
de http://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html :
utilisez une classe imbriquée non statique (ou classe intérieure) si vous avez besoin d'accès aux champs et méthodes non-publics d'une instance enclosante. Utilisation statique classe imbriquée si vous n'avez pas besoin de cet accès.
L'une des raisons pour lesquelles il y a statique par rapport à la normale a à voir avec le chargement en classe. Vous ne pouvez pas instancier une classe interne dans le constructeur de son parent.
PS: j'ai toujours compris que "imbriqué" et "intérieur" étaient interchangeables. Il peut y avoir des nuances subtiles dans les Termes, mais la plupart des développeurs Java comprendraient l'une ou l'autre.
Non-statiques, les classes internes peuvent entraîner des fuites de mémoire tout en statique à l'intérieur de la classe permettra de protéger contre eux. Si la classe extérieure contient des données considérables, elle peut réduire les performances de l'application.
L'utilisation d'une classe statique imbriquée plutôt que non statique peut sauver des espaces dans certains cas. Par exemple: mettre en œuvre un Comparator
à l'intérieur d'une classe, disons étudiant.
public class Student {
public static final Comparator<Student> BY_NAME = new ByName();
private final String name;
...
private static class ByName implements Comparator<Student> {
public int compare() {...}
}
}
puis le static
garantit que la classe Étudiante n'a qu'un seul comparateur, plutôt que d'en instancier un nouveau chaque fois qu'une nouvelle instance étudiante est créée.
Je ne connais pas la différence de performances, mais comme vous dites, la classe statique emboîtée ne fait pas partie d'une instance de la classe enclosante. Semble juste plus simple de créer une classe statique imbriquée sauf si vous avez vraiment besoin d'être une classe intérieure.
C'est un peu comme Pourquoi je fais toujours mes variables finales en Java - si elles ne sont pas finales, je sais qu'il y a quelque chose de drôle qui se passe avec elles. Si vous utilisez une classe intérieure au lieu d'une classe statique imbriquée, il devrait y avoir une bonne raison.
Avantage intérieure--
- utilisation unique
- supporte et améliore l'encapsulation
- lisibilité
- domaine privé de l'accès
sans classe intérieure extérieure n'existera pas.
class car{
class wheel{
}
}
il existe quatre types de classe intérieure.
- classe intérieure normale
- méthode Classe intérieure locale
- Anonyme intérieur de la classe
- classe intérieure statique
point - - -
- de la classe intérieure statique ,nous ne pouvons accéder qu'à un membre statique de la classe extérieure.
- dans la classe intérieure, nous ne pouvons pas déclarer membre statique .
-
afinde à invoquer la normale intérieure de la classe statique dans la zone de extérieur de la classe.
Outer 0=new Outer(); Outer.Inner i= O.new Inner();
-
afinde à invoquer la normale intérieure de la classe dans l'exemple de la zone de l'extérieur de la classe.
Inner i=new Inner();
-
afinde à invoquer la normale intérieure à l'extérieur de l'extérieur de la classe.
Outer 0=new Outer(); Outer.Inner i= O.new Inner();
-
à l'intérieur de la classe intérieure ce pointeur vers la classe intérieure.
this.member-current inner class outerclassname.this--outer class
-
pour la classe intérieure le modificateur applicable est -- public, par défaut,
final,abstract,strictfp,+private,protected,static
-
$interne externe est le nom du nom de la classe interne.
-
méthode de la classe intérieure en instance alors nous pouvons accéder au champ statique et d'instance de la classe extérieure.
10.intérieur de la classe à l'intérieur de la méthode statique, nous ne pouvons accéder qu'au champ statique de
classe extérieure.
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
}
}
}
}