Inner class in interface vs in class

送分小仙女□ 提交于 2019-11-27 05:22:06

问题


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.


回答1:


Static inner classes are mostly similar to top-level classes, except the inner class has access to all the static variables and methods of the enclosing class. The enclosing class name is effectively appended to the package namespace of the inner class. By declaring a class as a static inner class, you are communicating that the class is somehow inseparably tied to the context of the enclosing class.

Non-static inner classes are less common. The main difference is that instances of a non-static inner class contain an implicit reference to an instance of the enclosing class, and as a result have access to instance variables and methods of that enclosing class instance. This leads to some odd looking instantiation idioms, for example:

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-static inner classes are much more intimately tied to their enclosing classes than static inner classes. They have valid uses (for example iterators are often implemented as non-static inner classes within the class of the data structure they iterate over).

It's a common mistake to declare a non-static inner class when you only really need the static inner class behaviour.




回答2:


An static inner class is a nested class, and the non-static is called an inner class. For more, look here.

However, I like to quote an excerpt from the same link.

A static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class. In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.

You didn't use the word static in the second case. And you think it would implicitly be static because its an interface. You are right in assuming that.

You can instantiate the inner class in your interface, just like a static nested class, because its really a static nested class.

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

So, the above statement will be valid in both of your cases. Your first case is of static nested class, and in the second case you didn't specify static, but even then it would be an static nested class because its in the interface. Hence, no difference other then the fact that one is nested in a class, and the other in an interface.

Normally an inner class in a class, not in interface, would be instantiated like below.

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

Moreover, a "non-static" inner class will have a implicit reference to its outer class. This is not the case with "static" nested class.




回答3:


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;


}



回答4:


The examples you give of nested / inner classes are (IMO) bad examples. Besides the 2nd example is not valid Java since an interface can only declare (implicitly) abstract methods. Here's a better example:

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

By embedding the Response class, we are indicating that it is a fundamental part of Worker API with no other uses.

The Map.Entry class is a well-known example of this idiom.




回答5:


IMHO, advantage is that you got fewer classes cluttering your project folder if they're trivial; the disadvantage is that when your inner class get growing along the requirement change, the maintenacne become your nightmare.




回答6:


I thought that the first one would declare a class Levels and a static inner class called Items. Items could be referenced by Levels.Items and would be static.

While the second would declare a simple inner class, which can be accessed by using Levels.Items, like in the following:

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

EDIT: this is totally wrong, read the comments and other replies.



来源:https://stackoverflow.com/questions/1845731/inner-class-in-interface-vs-in-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!