Question

Quelle est la différence entre ces deux déclarations classe interne? Commenter les avantages / inconvénients?

Cas A:. Classe dans une classe

public class Levels {   
  static public class Items {
    public String value;
    public String path;

    public String getValue() {
      return value;}
  }
}

et le cas B:. Classe dans l'interface

public interface Levels{

  public class Items {
    public String value;
    public String path;

    public String getValue() {
      return value;}
  }
}

Correction FOURNIE. Au placement de la méthode GetValue

Plus d'infos: Je suis en mesure d'instancier les objets de classe dans les deux cas A et B dans une autre classe qui ne met pas en oeuvre l'interface ALL AT.

public class Z{//NOTE: NO INTERFACE IMPLEMENTED here!!!!
 Levels.Items items = new Levels.Items();
}

Depuis une interface n'est pas instancié, tous les éléments à l'intérieur d'une interface sont accessibles par la notation par points sans interface NIVEAUX instancié simplement parce que vous ne pouvez pas instancier une interface -. Rendant effectivement une classe définie à l'intérieur d'une interface perméable à la référence statique

Alors dire que les objets de classe B dans le cas où n'est pas statique n'a pas de sens. Étant donné que les deux cas, A et B sont instanciés de la même façon, je ne cherche pas la sémantique sur ce qui est statique ou intérieure ou emboîtés. Arrête de me donner des réponses sur la sémantique. Je veux que le compilateur, les différences / avantages de l'exécution et du comportement, ou si aucun dire alors si. Plus de réponses sur la sémantique vous plaît !!!!! Un expert sur la spécification JVM entrailles ou VM .NET vous sur cette question de réponse plutôt que semanticissiests livre de texte.

Était-ce utile?

La solution

classes internes statiques sont essentiellement similaires aux classes de haut niveau, à l'exception de la classe interne a accès à tous les statiques variables et méthodes de la classe englobante. Le nom de classe englobante est effectivement ajouté à l'espace de noms de package de la classe interne. En déclarant une classe comme une classe interne statique, vous communiquez que la classe est en quelque sorte inséparablement liée au contexte de la classe englobante.

classes internes non statiques sont moins fréquents. La principale différence est que les instances d'une classe interne non statique contenir une référence implicite à une instance de la classe externe, et en conséquence avoir accès à des variables d'instance et les méthodes de cette instance de classe englobante. Cela conduit à des idiomes instanciation recherche étrange, par exemple:

Levels levels = new Levels(); // first need an instance of the enclosing class

// The items object contains an implicit reference to the levels object
Levels.Items items  = levels.new Items(); 

classes internes non statiques sont beaucoup plus intimement liés à leurs classes enveloppantes que les classes internes statiques. Ils ont des utilisations valides (par exemple itérateurs sont souvent mis en œuvre sous forme de classes internes non statiques dans la classe de la structure de données qu'ils itérer plus).

Il est une erreur commune de déclarer une classe interne non statique lorsque vous ne avez vraiment besoin le comportement de classe interne statique.

Autres conseils

Un static classe interne est une classe imbriquée, et la non-statique est appelée une classe interne. Pour en savoir plus, regarder ici .

Cependant, je tiens à citer un extrait du même lien.

  

Une classe imbriquée statique interagit avec   les membres d'instance de son externe   classe (et d'autres classes) comme   toute autre classe de haut niveau. En effet,   une classe imbriquée statique est behaviorally   une classe de niveau supérieur qui a été imbriqué   dans une autre classe de haut niveau pour   commodité d'emballage.

Vous n'avez pas utilisé le mot static dans le second cas. Et vous pensez que ce serait static implicitement parce que son interface. Vous avez raison de supposer que.

Vous pouvez instancier la classe interne dans votre interface, tout comme une classe imbriquée statique, parce que son vraiment une static classe imbriquée.

Levels.Items hello = new Levels.Items();

Ainsi, l'énoncé ci-dessus sera valable dans vos deux cas . Votre premier cas est de classe imbriquée statique, et dans le second cas vous ne spécifiez pas static, mais même alors ce serait une classe imbriquée statique car son dans l'interface. Par conséquent, aucune différence autre que le fait que l'on est niché dans une classe, et l'autre dans une interface .

Normalement, une classe interne dans une classe, pas dans l'interface , serait instancié comme ci-dessous.

Levels levels = new Levels();
Levels.Items items = levels.new Items();

De plus, une classe interne « non-statiques » aura une référence implicite à sa classe externe. Ce n'est pas le cas avec classe imbriquée « statique ».

Si vous déclarez une classe imbriquée dans une interface, il est toujours publique et statique . Donc:

public interface Levels{
    class Items {
        public String value;
        public String path;

        public String getValue() {return value;}
    }
}

est exactement le même que

public interface Levels{
    public static class Items {
        public String value;
        public String path;

        public String getValue() {return value;}
    }
}

Et même

public interface Levels{
    static class Items {
        public String value;
        public String path;

        public String getValue() {return value;}
    }
}

J'ai vérifié cela avec javap verbose et ils produisent tous

Compiled from "Levels.java"
public class Levels$Items extends java.lang.Object
  SourceFile: "Levels.java"
  InnerClass: 
   public #14= #3 of #23; //Items=class Levels$Items of class Levels
  minor version: 0
  major version: 50
  Constant pool:
const #1 = Method   #4.#21; //  java/lang/Object."<init>":()V
const #2 = Field    #3.#22; //  Levels$Items.value:Ljava/lang/String;
const #3 = class    #24;    //  Levels$Items
const #4 = class    #25;    //  java/lang/Object
const #5 = Asciz    value;
const #6 = Asciz    Ljava/lang/String;;
const #7 = Asciz    path;
const #8 = Asciz    <init>;
const #9 = Asciz    ()V;
const #10 = Asciz   Code;
const #11 = Asciz   LineNumberTable;
const #12 = Asciz   LocalVariableTable;
const #13 = Asciz   this;
const #14 = Asciz   Items;
const #15 = Asciz   InnerClasses;
const #16 = Asciz   LLevels$Items;;
const #17 = Asciz   getValue;
const #18 = Asciz   ()Ljava/lang/String;;
const #19 = Asciz   SourceFile;
const #20 = Asciz   Levels.java;
const #21 = NameAndType #8:#9;//  "<init>":()V
const #22 = NameAndType #5:#6;//  value:Ljava/lang/String;
const #23 = class   #26;    //  Levels
const #24 = Asciz   Levels$Items;
const #25 = Asciz   java/lang/Object;
const #26 = Asciz   Levels;

{
public java.lang.String value;

public java.lang.String path;

public Levels$Items();
  Code:
   Stack=1, Locals=1, Args_size=1
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return
  LineNumberTable: 
   line 2: 0

  LocalVariableTable: 
   Start  Length  Slot  Name   Signature
   0      5      0    this       LLevels$Items;


public java.lang.String getValue();
  Code:
   Stack=1, Locals=1, Args_size=1
   0:   aload_0
   1:   getfield    #2; //Field value:Ljava/lang/String;
   4:   areturn
  LineNumberTable: 
   line 7: 0

  LocalVariableTable: 
   Start  Length  Slot  Name   Signature
   0      5      0    this       LLevels$Items;


}

Les exemples que vous donnez des classes imbriquées / intérieur sont (OMI) mauvais exemples. Outre le 2ème exemple n'est pas Java valide car une interface ne peut déclarer (implicitement) les méthodes abstraites. Voici un meilleur exemple:

public interface Worker {

    public class Response {
        private final Status status;
        private final String message;
        public Response(Status status, String message) {
            this.status = status; this.message = message;
        }
        public Status getStatus() { return status; }
        public String getMessage() { return message; }
    }

    ...

    public Response doSomeOperation(...);
}

En intégrant la classe de réponse, nous indiquons qu'il est une partie fondamentale de l'API Travailleur sans autres utilisations.

La classe Map.Entry est un exemple bien connu de cet idiome.

à mon humble avis, avantage est que vous avez moins de classes qui encombrent votre dossier de projet si elles sont triviales; désavantage est que lorsque votre classe interne Dépassez-vous le long de la modification de l'exigence, la maintenacne devenir votre cauchemar.

Je pensais que le premier déclarerait un des niveaux de classe et une classe interne statique appelée éléments. Les produits peuvent être référencés par Levels.Items et seraient statiques.

Alors que le second déclarerait une simple classe intérieure, qui peut être consulté en utilisant Levels.Items, comme dans les domaines suivants:

Levels.Items hello = new Levels.Items();

EDIT: ce qui est totalement faux, lisez les commentaires et autres réponses

.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top