Inner class in interface vs in class

Viewed 38719

What is the difference between these two innerclass declarations? Also comment on advantages/disadvantages?

case A: class within a class.

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

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

and case B: class within interface.

public interface Levels{

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

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

Made correction: to placement of getvalue method.

further info: I am able to instantiate Items class in both cases A and B in another class that does not implement interface AT ALL.

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

Since an interface is not instantiated, all the elements inside an interface are accessible by dot notation without LEVELS interface instantiated simply because you cannot instantiate an interface - effectively making a class defined inside an interface permeable to static reference.

So saying that Items class in case B is not static does not make sense. Since both cases A and B are instantiated the same way, I am not looking for semantics on what is static or inner or nested. Stop giving me answers on semantics. I want the compiler, runtime and behavioural differences/advantages, or if none then say so. No more answers on semantics please!!!!! An expert on JVM or .NET VM specification innards please this answer question rather than text book semanticissiests.

6 Answers

If you declare a nested class in an interface it is always public and static. So:

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

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

Is exactly the same as

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

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

And even

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

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

I've checked this with javap -verbose and they all produce

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;


}
Related