Domanda

Qual è la differenza tra queste due dichiarazioni classe interna? commento anche su vantaggi / svantaggi?

A caso:. Classe all'interno di una classe

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

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

e caso B:. Classe nell'interfaccia

public interface Levels{

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

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

correzione apportata:. Per il posizionamento di metodo GetValue

Per maggiori informazioni: Sono in grado di creare un'istanza di classe di prodotti che in entrambi i casi A e B in un'altra classe che non implementa l'interfaccia AFFATTO.

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

Dal momento che l'interfaccia non è istanziato, tutti gli elementi all'interno di un'interfaccia sono accessibili tramite la notazione del punto senza interfaccia LIVELLI un'istanza semplicemente perché non è possibile creare un'istanza di un'interfaccia -. Efficacemente facendo una classe definita all'interno di un'interfaccia permeabile al riferimento statico

Quindi, dicendo che classe I prodotti che nel caso in cui B non è statico non ha senso. Dal momento che sia i casi A e B vengono create istanze allo stesso modo, io non sto cercando la semantica su ciò che è statico o interno o nidificato. Smettere di darmi delle risposte sulla semantica. Voglio che il compilatore, runtime e differenze di comportamento / vantaggi, o se nessuno poi dire così. Non più risposte sulla semantica per favore !!!!! Un esperto di JVM o .NET VM specifica interiora piacere a questa domanda la risposta, piuttosto che di testo semanticissiests libro.

È stato utile?

Soluzione

statiche classi interne sono per lo più simili a classi di primo livello, ad eccezione della classe interna ha accesso a tutti i statiche variabili e metodi della classe contenitrice. Il nome classe contenitrice è effettivamente aggiunto al pacchetto namespace della classe interna. Dichiarando una classe come una classe interna statica, si comunica che la classe è in qualche modo legato indissolubilmente al contesto della classe contenitrice.

classi interne non statici sono meno comuni. La differenza principale è che le istanze di una classe interna non statica contenere un implicito riferimento a un'istanza della classe contenitrice, e come risultato hanno accesso a variabili e metodi di questa istanza classe contenitrice istanza. Questo porta ad alcuni modi di dire di istanza strano guardare, ad esempio:

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(); 

Non statico classi interne sono molto più intimamente legati ai loro classi muraria di classi interne statiche. Hanno utilizzi validi (ad esempio iteratori sono spesso implementate come classi interne non statici all'interno della classe della struttura di dati che iterare).

E 'un errore comune per dichiarare una classe interna non statica quando si ha realmente bisogno solo il comportamento classe interna statica.

Altri suggerimenti

Una classe interna static è una classe annidata e la non statico è chiamata una classe interna. Per di più, guarda qui .

Tuttavia, mi piace citare un brano tratto dallo stesso collegamento.

  

Una classe innestata statica interagisce con   i membri del suo esterno istanza   di classe (e le altre classi), proprio come   qualsiasi altra classe di livello superiore. In effetti,   una classe innestata statica è comportamentale   una classe di primo livello che è stato annidato   in un'altra classe di livello superiore per   confezione convenienza.

Non hai utilizza la parola static nel secondo caso. E pensi che sarebbe implicitamente essere static perché la sua interfaccia. Hai ragione nel ritenere che.

È possibile creare un'istanza della classe interna nell'interfaccia, proprio come una classe innestata statica, perché la sua davvero un static nidificato di classe.

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

Quindi, la dichiarazione di cui sopra sarà valido in entrambi i vostri casi . Il tuo primo caso è di classe innestata statica, e nel secondo caso non ha specificato static, ma anche in quel caso sarebbe una classe innestata statica perché la sua nell'interfaccia. Quindi, nessuna differenza altri poi il fatto che uno è annidata in una classe, e l'altra in un'interfaccia .

normalmente una classe interna in una classe, non nell'interfaccia , sarebbe istanziare come qui di seguito.

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

Inoltre, una classe interna "non statica" avrà un riferimento implicito alla sua classe esterna. Questo non è il caso di classe annidata "statica".

Se si dichiara una classe annidata in un'interfaccia è sempre pubblici e static . Quindi:

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

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

è esattamente lo stesso di

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

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

E anche

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

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

Ho controllato questo con javap verbose e tutti produco

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;


}

Gli esempi si danno delle classi nidificate / interna sono (IMO) cattivi esempi. Oltre al secondo esempio non è valido in quanto Java un'interfaccia può dichiarare solo (implicitamente) metodi astratti. Ecco un esempio migliore:

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(...);
}

Incorporando la classe di risposta, ci stanno indicando che si tratta di una parte fondamentale del lavoratore API senza altri usi.

La classe Map.Entry è un esempio ben noto di questo linguaggio.

IMHO, vantaggio è che si ha un minor numero di classi che ingombrano la vostra cartella del progetto se sono banali; svantaggio è che quando la classe interna ottenere crescono lungo il cambiamento requisito, il maintenacne diventare il vostro incubo.

Ho pensato che il primo avrebbe dichiarato a livelli di classe e di una classe interna statica denominata Elementi. Gli articoli hanno potuto essere referenziati da Levels.Items e sarebbe statica.

Mentre il secondo dichiara una semplice classe interna, a cui si accede utilizzando Levels.Items, come nel seguente:

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

EDIT: questo è totalmente sbagliato, leggere i commenti e le altre risposte

.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top