java - 静态内部类的设计意图 - 静态嵌套类static nested class和内部类inner class的不同




Java内部类和静态嵌套类 (16)

Java教程说

术语:嵌套类分为两类:静态和非静态。 被声明为静态的嵌套类简单地称为静态嵌套类。 非静态嵌套类称为内部类。

按照一般的说法,术语“嵌套”和“内部”可以被大多数程序员交换使用,但是我将使用正确的术语“嵌套类”,它涵盖内部和静态。

类可以无限嵌套,例如,类A可以包含类B,其中包含包含类D的类C等。但是,多于一级的类嵌套很少见,因为它通常是不好的设计。

有三个原因可以创建一个嵌套类:

  • 组织:有时,将一个类排序到另一个类的名称空间似乎是最明智的,尤其是当它不会用于其他任何环境时
  • 访问:嵌套类对其包含的类的变量/字段有特殊的访问权(正是哪些变量/字段取决于嵌套类的类型,无论是内部还是静态)。
  • 方便:不得不为每个新类型创建一个新文件都很麻烦,特别是当这个类型只用于一个上下文时

Java中四种嵌套类 。 简而言之,它们是:

  • 静态类 :声明为另一个类的静态成员
  • 内部类 :声明为另一个类的实例成员
  • 本地内部类 :在另一个类的实例方法声明
  • 匿名内部类 :像本地内部类一样,但是写成一个返回一次性对象的表达式

让我详细说明一下。


静态类

静态类是最容易理解的类型,因为它们与包含类的实例无关。

静态类是被声明为另一个类的静态成员的类。 就像其他静态成员一样,这样的类实际上只是一个挂钩,它使用包含类作为它的名称空间, 例如 ,声明为类Rhino的静态成员的类Goat在包中比萨由名称pizza.Rhino.Goat

package pizza;

public class Rhino {

    ...

    public static class Goat {
        ...
    }
}

坦率地说,静态类是一个相当不值钱的功能,因为类已经被包分解成名称空间。 创建一个静态类的唯一真正可以想象的理由是,这样的类可以访问其包含的类的私有静态成员,但是我发现这是静态类特性存在的一个非常蹩脚的理由。


内部类

内部类是声明为另一个类的非静态成员的类:

package pizza;

public class Rhino {

    public class Goat {
        ...
    }

    private void jerry() {
        Goat g = new Goat();
    }
}

与静态类一样,内部类被称为包含类名称pizza.Rhino.Goat的限定 ,但在包含类中,可以通过它的简单名称来知道它。 但是,内部类的每个实例都与其包含的类的特定实例绑定在一起:上面的,在杰里中创建的山羊 ,隐含地与犀牛中的Rhino实例相关联。 否则,当我们实例化山羊时,我们使关联的Rhino实例显式化:

Rhino rhino = new Rhino();
Rhino.Goat goat = rhino.new Goat();

(请注意,您将新内核类型称为Goat ,并使用新奇妙的语法:Java推断来自犀牛部分的包含类型,并且, 新的rhino.Goat()对我来说也会更有意义。)

那么这对我们有什么好处呢? 那么,内部类实例可以访问包含类实例的实例成员。 这些封闭的实例成员通过它们的简单名称在内部类中引用,而不是通过 this (在内部类中引用内部类实例,而不是关联的包含类实例):

public class Rhino {

    private String barry;

    public class Goat {
        public void colin() {
            System.out.println(barry);
        }
    }
}

在内部类中,可以将这个包含类称为Rhino.this ,并且可以使用来引用其成员, 例如Rhino.this.barry


本地内部类

本地内部类是在方法体中声明的类。 这样的类只在其包含的方法中是已知的,所以它只能被实例化,并且在其包含的方法中访问其成员。 增益是一个本地内部类实例绑定并可以访问其包含方法的最终局部变量。 当实例使用其包含方法的最后一个局部变量时,即使变量超出了范围(这实际上是Java原始的,限制版本的闭包),变量仍会保留实例创建时的值。

因为本地内部类既不是类或包的成员,也不会声明具有访问级别。 (但是,要清楚自己的成员具有像普通课程那样的访问级别。)

如果在实例方法中声明了一个本地内部类,那么在创建实例时,内部类的实例与包含方法this所持有的实例相关联,因此可以像在实例中一样访问包含类的实例成员内心阶层。 一个本地的内部类通过它的名字实例化, 例如本地内部类Cat被实例化为新的Cat() ,而不是像你期望的那样新建this.Cat()。


匿名内部类

匿名内部类是编写本地内部类的语法便捷方式。 大多数情况下,每次运行包含的方法时,最多只会实例化一次本地内部类。 那么,如果我们能够将本地内部类定义和它的单一实例化合并成一个方便的语法形式,那将是很好的,如果我们不需要为该类考虑一个名字(更不利用您的代码包含的名称越多越好)。 一个匿名的内部类允许这些东西:

new *ParentClassName*(*constructorArgs*) {*members*}

这是一个表达式,返回一个扩展ParentClassName的未命名类的新实例。 你不能提供你自己的构造函数; 而是隐式提供的,它只是简单地调用超级构造函数,所以提供的参数必须适合超级构造函数。 (如果父项包含多个构造函数,那么调用“最简单”的构造函数,这是由一组相当复杂的规则确定的“最简单”规则,不值得深入研究 - 只需注意NetBeans或Eclipse告诉您的内容。)

或者,您可以指定一个接口来实现:

new *InterfaceName*() {*members*}

这样的声明创建了一个扩展Object并实现InterfaceName的未命名类的新实例。 再次,你不能提供你自己的构造函数; 在这种情况下,Java隐含地提供了一个无参数,无所作为的构造函数(所以在这种情况下永远不会有构造函数参数)。

即使你不能给一个匿名的内部类构造函数,你仍然可以使用初始化块(放置在任何方法之外的块)执行任何设置。

要明确一个匿名的内部类是一种不太灵活的创建一个本地内部类的方法。 如果你想要一个实现多个接口的本地内部类,或者实现接口的同时扩展一些除Object之外的类或者指定它自己的构造函数,那么你就不能创建一个常规的命名本地内部类。

Java中的内部类和静态嵌套类之间的主要区别是什么? 设计/实施在选择其中一种方面起作用吗?


Targeting learner, who are novice to Java and/or Nested Classes

Nested classes can be either:
1. Static Nested classes.
2. Non Static Nested classes. (also known as Inner classes ) =>Please remember this


1.Inner classes
例:

class OuterClass  {
/*  some code here...*/
     class InnerClass  {  }
/*  some code here...*/
}


Inner classes are subsets of nested classes:

  • inner class is a specific type of nested class
  • inner classes are subsets of nested classes
  • You can say that an inner class is also a nested class, but you can NOT say that a nested class is also an inner class .

Specialty of Inner class:

  • instance of an inner class has access to all of the members of the outer class, even those that are marked “private”


2.Static Nested Classes:
例:

class EnclosingClass {
  static class Nested {
    void someMethod() { System.out.println("hello SO"); }
  }
}

Case 1:Instantiating a static nested class from a non-enclosing class

class NonEnclosingClass {

  public static void main(String[] args) {
    /*instantiate the Nested class that is a static
      member of the EnclosingClass class:
    */

    EnclosingClass.Nested n = new EnclosingClass.Nested(); 
    n.someMethod();  //prints out "hello"
  }
}

Case 2:Instantiating a static nested class from an enclosing class

class EnclosingClass {

  static class Nested {
    void anotherMethod() { System.out.println("hi again"); } 
  }

  public static void main(String[] args) {
    //access enclosed class:

    Nested n = new Nested(); 
    n.anotherMethod();  //prints out "hi again"
  }

}

Specialty of Static classes:

  • Static inner class would only have access to the static members of the outer class, and have no access to non-static members.

结论:
Question: What is the main difference between a inner class and a static nested class in Java?
Answer: just go through specifics of each class mentioned above.


First of all There is no such class called Static class.The Static modifier use with inner class (called as Nested Class) says that it is a static member of Outer Class which means we can access it as with other static members and without having any instance of Outer class. (Which is benefit of static originally.)

Difference between using Nested class and regular Inner class is:

OuterClass.InnerClass inner = new OuterClass().new InnerClass();

First We can to instantiate Outerclass then we Can access Inner.

But if Class is Nested then syntax is:

OuterClass.InnerClass inner = new OuterClass.InnerClass();

Which uses the static Syntax as normal implementation of static keyword.


I have illustrated various possible correct and error scenario which can occur in java code.

    class Outter1 {

        String OutStr;

        Outter1(String str) {
            OutStr = str;
        }

        public void NonStaticMethod(String st)  {

            String temp1 = "ashish";
            final String  tempFinal1 = "ashish"; 

            //  below static attribute not permitted
            // static String tempStatic1 = "static";    

            //  below static with final attribute not permitted         
            // static final String  tempStatic1 = "ashish";  

            // synchronized keyword is not permitted below          
            class localInnerNonStatic1 {            

                synchronized    public void innerMethod(String str11) {
                    str11 = temp1 +" sharma";
                    System.out.println("innerMethod ===> "+str11);
                }

                /* 
        //  static method with final not permitted
          public static void innerStaticMethod(String str11) { 

                    str11 = temp1 +" india";
                    System.out.println("innerMethod ===> "+str11);
                }*/
            }

            // static class not permitted below
            //  static class localInnerStatic1 {   }                            

        }

        public static  void StaticMethod(String st)     {

            String temp1 = "ashish";
            final String  tempFinal1 = "ashish"; 

            // static attribute not permitted below
            //static String tempStatic1 = "static";     

            //  static with final attribute not permitted below
            // static final String  tempStatic1 = "ashish";                         

            class localInnerNonStatic1 {
                public void innerMethod(String str11) {
                    str11 = temp1 +" sharma";
                    System.out.println("innerMethod ===> "+str11);
                }

                /*
    // static method with final not permitted
    public static void innerStaticMethod(String str11) {  
                    str11 = temp1 +" india";
                    System.out.println("innerMethod ===> "+str11);
                }*/
            }

            // static class not permitted below
            //  static class localInnerStatic1 {   }    

        }

        // synchronized keyword is not permitted
        static  class inner1 {          

            static String  temp1 = "ashish";
            String  tempNonStatic = "ashish";
            // class localInner1 {

            public void innerMethod(String str11) {
                str11 = temp1 +" sharma";
                str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }

            public static void innerStaticMethod(String str11) {
                //  error in below step
                str11 = temp1 +" india";    
                //str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }
            //}
        }

        //synchronized keyword is not permitted below
        class innerNonStatic1 {             

//This is important we have to keep final with static modifier in non
// static innerclass below
            static final String  temp1 = "ashish";  
            String  tempNonStatic = "ashish";
            // class localInner1 {

            synchronized    public void innerMethod(String str11) {
                tempNonStatic = tempNonStatic +" ...";
                str11 = temp1 +" sharma";
                str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }

            /*
            //  error in below step
            public static void innerStaticMethod(String str11) {   
                            //  error in below step
                            // str11 = tempNonStatic +" india";                     
                            str11 = temp1 +" india";
                            System.out.println("innerMethod ===> "+str11);
                        }*/
                    //}
                }
    }

The difference is that a nested class declaration that is also static can be instantiated outside of the enclosing class.

When you have a nested class declaration that is not static, also known as an inner class , Java won't let you instantiate it except via the enclosing class. The object created out of the inner class is linked to the object created from the outer class, so the inner class can reference the fields of the outer.

But if it's static, then the link does not exist, the outer fields cannot be accessed (except via an ordinary reference like any other object) and you can therefore instantiate the nested class by itself.


The following is an example of static nested class and inner class :

OuterClass.java

public class OuterClass {
     private String someVariable = "Non Static";

     private static String anotherStaticVariable = "Static";  

     OuterClass(){

     }

     //Nested classes are static
     static class StaticNestedClass{
        private static String privateStaticNestedClassVariable = "Private Static Nested Class Variable"; 

        //can access private variables declared in the outer class
        public static void getPrivateVariableofOuterClass(){
            System.out.println(anotherStaticVariable);
        }
     }

     //non static
     class InnerClass{

         //can access private variables of outer class
         public String getPrivateNonStaticVariableOfOuterClass(){
             return someVariable;
         }
     }

     public static void accessStaticClass(){
         //can access any variable declared inside the Static Nested Class 
         //even if it private
         String var = OuterClass.StaticNestedClass.privateStaticNestedClassVariable; 
         System.out.println(var);
     }

}

OuterClassTest:

public class OuterClassTest {
    public static void main(String[] args) {

        //access the Static Nested Class
        OuterClass.StaticNestedClass.getPrivateVariableofOuterClass();

        //test the private variable declared inside the static nested class
        OuterClass.accessStaticClass();
        /*
         * Inner Class Test
         * */

        //Declaration

        //first instantiate the outer class
        OuterClass outerClass = new OuterClass();

        //then instantiate the inner class
        OuterClass.InnerClass innerClassExample =  outerClass. new InnerClass();

        //test the non static private variable
        System.out.println(innerClassExample.getPrivateNonStaticVariableOfOuterClass()); 

    }

}

When we declare static member class inside a class, it is known as top level nested class or a static nested class. It can be demonstrated as below :

class Test{
    private static int x = 1;
        static class A{
        private static int y = 2;
        public static int getZ(){
            return B.z+x;
        }
    }
    static class B{
        private static int z = 3;
        public static int getY(){
            return A.y;
        }
    }
}

class TestDemo{
     public static void main(String[] args){
        Test t = new Test();
        System.out.println(Test.A.getZ());
        System.out.println(Test.B.getY());
    }
}

When we declare non-static member class inside a class it is known as inner class. Inner class can be demonstrated as below :

    class Test{
        private int i = 10;
        class A{
            private int i =20;
            void display(){
            int i = 30;
            System.out.println(i);
            System.out.println(this.i);
            System.out.println(Test.this.i);
        }
    }
}

Java教程

嵌套类分为两类:静态和非静态。 被声明为静态的嵌套类简单地称为静态嵌套类。 非静态嵌套类称为内部类。

静态嵌套类可以使用封闭类名来访问:

OuterClass.StaticNestedClass

例如,要为静态嵌套类创建对象,请使用以下语法:

OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

作为内部类实例的对象存在于外部类的实例中。 考虑以下类:

class OuterClass {
    ...
    class InnerClass {
        ...
    }
}

InnerClass的一个实例只能存在于OuterClass的一个实例中,并且可以直接访问其封闭实例的方法和字段。

要实例化一个内部类,你必须首先实例化外部类。 然后,使用以下语法在外部对象内创建内部对象:

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

请参阅: Java教程 - 嵌套类

为了完整性,请注意, 存在封闭实例内部类也有这样的事情:

class A {
  int t() { return 1; }
  static A a =  new A() { int t() { return 2; } };
}

这里, new A() { ... }一个静态上下文中定义内部类,并且没有包含实例。


在创建实例的情况下,非静态内部类的实例是通过引用它定义的外部类的对象来创建的。 这意味着它有爆裂的例子。 但是静态内部类的实例是通过Outer类的引用创建的,而不是外部对象的引用。 这意味着它没有插入实例。

例如:

class A
{
  class B
  {
    // static int x; not allowed here…..    
  }
  static class C
  {
    static int x; // allowed here
  }
}

class Test
{
  public static void main(String… str)
  {
    A o=new A();
    A.B obj1 =o.new B();//need of inclosing instance

    A.C obj2 =new A.C();

    // not need of reference of object of outer class….
  }
}

对于在某些情况下可能有用的嵌套静态类有一个巧妙之处。

虽然静态属性在类通过构造函数实例化之前得到实例化,但嵌套静态类中的静态属性似乎并没有在类的构造函数被调用之前实例化,或者至少直到属性被第一次引用之后才被实例化,即使他们被标记为“最终”。

考虑这个例子:

public class C0 {

    static C0 instance = null;

    // Uncomment the following line and a null pointer exception will be
    // generated before anything gets printed.
    //public static final String outerItem = instance.makeString(98.6);

    public C0() {
        instance = this;
    }

    public String makeString(int i) {
        return ((new Integer(i)).toString());
    }

    public String makeString(double d) {
        return ((new Double(d)).toString());
    }

    public static final class nested {
        public static final String innerItem = instance.makeString(42);
    }

    static public void main(String[] argv) {
        System.out.println("start");
        // Comment out this line and a null pointer exception will be
        // generated after "start" prints and before the following
        // try/catch block even gets entered.
        new C0();
        try {
            System.out.println("retrieve item: " + nested.innerItem);
        }
        catch (Exception e) {
            System.out.println("failed to retrieve item: " + e.toString());
        }
        System.out.println("finish");
    }
}

即使'nested'和'innerItem'都被声明为'static final'。 nested.innerItem的设置不会在类实例化之后(或者至少在嵌套静态项第一次被引用之后)才能发生,正如您通过注释和取消注释我引用的行可以看到的那样,以上。 这同样不适用于'outerItem'。

至少这是我在Java 6.0中看到的。


嵌套类:类内的类

类型:

  1. 静态嵌套类
  2. 非静态嵌套类[Inner class]

区别:

非静态嵌套类[Inner class]

内部类的非静态嵌套类对象存在于外部类的对象内。 所以外部类的数据成员可以被内部类访问。 所以要创建内部类的对象,我们必须首先创建外部类的对象。

outerclass outerobject=new outerobject();
outerclass.innerclass innerobjcet=outerobject.new innerclass(); 

静态嵌套类

内部类的静态嵌套类对象不需要外部类对象,因为单词“静态”表示不需要创建对象。

class outerclass A {
    static class nestedclass B {
        static int x = 10;
    }
}

如果你想访问x,那么写下面的内部方法

  outerclass.nestedclass.x;  i.e. System.out.prinltn( outerclass.nestedclass.x);

我不认为真正的区别在上述答案中变得清晰。

首先让条款正确:

  • 嵌套类是在源代码级别包含在另一个类中的类。
  • 如果使用静态修饰符声明它是静态的
  • 一个非静态的嵌套类被称为内部类。 (我留在非静态嵌套类。)

马丁的回答是正确的。 但是,实际的问题是:声明一个嵌套类是否静态的目的是什么?

如果您只想将类保留在一起,或者如果嵌套类仅在封闭类中使用,则可以使用静态嵌套类。 静态嵌套类与其他类没有语义上的区别。

非静态嵌套类是不同的野兽。 类似于匿名内部类,这样的嵌套类实际上是闭包。 这意味着他们捕捉周围的范围和他们的封闭实例并使其可访问。 也许一个例子会澄清这一点。 查看容器的这个存根:

public class Container {
    public class Item{
        Object data;
        public Container getContainer(){
            return Container.this;
        }
        public Item(Object data) {
            super();
            this.data = data;
        }

    }

    public static Item create(Object data){
        // does not compile since no instance of Container is available
        return new Item(data);
    }
    public Item createSubItem(Object data){
        // compiles, since 'this' Container is available
        return new Item(data);
    }
}

在这种情况下,您希望从子项目到父容器的引用。 使用一个非静态的嵌套类,这个工作没有一些工作。 您可以使用语法Container.this访问Container的封闭实例。

更多的核心解释如下:

如果您查看编译器为(非静态)嵌套类生成的Java字节码,它可能会变得更加清晰:

// class version 49.0 (49)
// access flags 33
public class Container$Item {

  // compiled from: Container.java
  // access flags 1
  public INNERCLASS Container$Item Container Item

  // access flags 0
  Object data

  // access flags 4112
  final Container this$0

  // access flags 1
  public getContainer() : Container
   L0
    LINENUMBER 7 L0
    ALOAD 0: this
    GETFIELD Container$Item.this$0 : Container
    ARETURN
   L1
    LOCALVARIABLE this Container$Item L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 1
  public <init>(Container,Object) : void
   L0
    LINENUMBER 12 L0
    ALOAD 0: this
    ALOAD 1
    PUTFIELD Container$Item.this$0 : Container
   L1
    LINENUMBER 10 L1
    ALOAD 0: this
    INVOKESPECIAL Object.<init>() : void
   L2
    LINENUMBER 11 L2
    ALOAD 0: this
    ALOAD 2: data
    PUTFIELD Container$Item.data : Object
    RETURN
   L3
    LOCALVARIABLE this Container$Item L0 L3 0
    LOCALVARIABLE data Object L0 L3 2
    MAXSTACK = 2
    MAXLOCALS = 3
}

正如你所看到的,编译器创建一个隐藏的字段Container this$0 。 这是在具有Container类型的附加参数的构造函数中设置的,以指定封闭实例。 您无法在源代码中看到此参数,但编译器为嵌套类隐式生成该参数。

马丁的例子

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

会被编译成类似于(在字节码中)

new InnerClass(outerObject)

为了完整起见:

匿名类一个非静态嵌套类的完美例子,它只是没有与之关联的名称,并且以后不能被引用。


我认为这里不需要添加太多的东西,大部分答案都能很好地解释静态嵌套类和Inner类之间的区别。 但是,使用嵌套类与内部类时请考虑以下问题。 正如在几个答案中提到的,内部类不能被实例化,因为它们的封闭类没有实例化,这意味着它们持有一个指向其封闭类的实例,这会导致内存溢出或堆栈溢出异常,因为GC即使不再使用封闭类,也不能垃圾收集。 为了清楚起见,请检查以下代码:

public class Outer {


    public  class Inner {

    }


    public Inner inner(){
        return new Inner();
    }

    @Override
    protected void finalize() throws Throwable {
    // as you know finalize is called by the garbage collector due to destroying an object instance
        System.out.println("I am destroyed !");
    }
}


public static void main(String arg[]) {

    Outer outer = new Outer();
    Outer.Inner inner = outer.new Inner();

    // out instance is no more used and should be garbage collected !!!
    // However this will not happen as inner instance is still alive i.e used, not null !
    // and outer will be kept in memory until inner is destroyed
    outer = null;

    //
    // inner = null;

    //kick out garbage collector
    System.gc();

}

如果你删除// inner = null;的注释// inner = null; 该计划将出“ 我被摧毁! ”,但保持这个评论它不会。
原因是白色的内部实例仍然被引用GC不能收集它,并且因为它引用(具有指向)外部实例,所以它也不会被收集。 在项目中有足够的这些对象并且可能会耗尽内存。
与静态内部类相比,内部类没有指向内部类实例,因为它不是实例相关的,而是与类相关的。 上面的程序可以打印出“ 我被摧毁了! ”如果你让Inner类是静态的并且用Outer.Inner i = new Outer.Inner();实例化的Outer.Inner i = new Outer.Inner();


我认为,通常遵循的惯例是这样的:

  • 顶级类中的静态类嵌套类
  • 顶级中的非静态类内部类 ,它还有两种形式:
    • 本地类 - 在方块或构造函数体内的块内声明的类
    • 匿名类 - 其实例在表达式和语句中创建的未命名类

但是,其他几点要记住的是:

  • 顶层类和静态嵌套类在语义上是相同的,只是在静态嵌套类的情况下,它可以静态引用其外部[父]类的私有静态字段/方法,反之亦然。

  • 内部类可以访问Outer [parent]类的封闭实例的实例变量。 但是,并非所有内部类都包含实例,例如静态上下文中的内部类,如静态初始化块中使用的匿名类,则不会。

  • 匿名类默认扩展父类或实现父接口,并且没有其他子句可以扩展任何其他类或实现更多接口。 所以,

    • new YourClass(){}; 表示class [Anonymous] extends YourClass {}
    • new YourInterface(){}; 意味着class [Anonymous] implements YourInterface {}

我觉得更大的问题仍然是开放的,何时使用? 那么这主要取决于你正在处理的场景,但阅读@jrudolph给出的回复可能会帮助你做出一些决定。


这些术语可以互换使用。 如果你想真的很迂腐,那么你可以定义“嵌套类”来引用一个静态内部类,它没有包含实例。 在代码中,你可能有这样的东西:

public class Outer {
    public class Inner {}

    public static class Nested {}
}

但这并不是一个广为接受的定义。


这里是Java内部类和静态嵌套类之间的主要区别和相似之处。

希望能帮助到你!

内部类

  • 可以访问外部类实例和静态方法和字段
  • 与封闭类的实例关联以实例化它首先需要一个外部类的实例(注意新的关键字位置):

    Outerclass.InnerClass innerObject = outerObject.new Innerclass();
    
  • 无法定义任何静态成员本身

  • 不能接口声明

静态嵌套类

  • 无法访问外部类实例方法或字段

  • 不与任何封闭类的实例关联所以实例化它:

    OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
    

相似

  • 两个内部类都可以访问外部类的 私有字段和方法
  • 外部类也可以访问内部类的 私有字段和方法
  • 这两个类都可以具有私有的,受保护的或公共访问修饰符

为什么使用嵌套类?

根据Oracle文档,有几个原因( 完整文档 ):

  • 它是一种逻辑分组的方法,它只在一个地方使用:如果一个类只对另一个类有用,那么将其嵌入该类并将它们保持在一起是合乎逻辑的。 嵌套这样的“帮助类”使得它们的包更加简化。

  • 它增加了封装:考虑两个顶级类A和B,其中B需要访问A的成员,否则这些成员将被声明为私有。 通过在类A中隐藏类B,可以将A的成员声明为私有,并且B可以访问它们。 另外,B本身可以被外界隐藏起来。

  • 它可以导致更易读和可维护的代码:在顶级类中嵌套小类会使代码更接近它的使用位置。





inner-classes