提问



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

最佳参考


来自Java教程:[68]



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



使用封闭的类名访问静态嵌套类:


OuterClass.StaticNestedClass


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


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


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


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


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


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


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


请参阅:Java教程 - 嵌套类[69]


为了完整性,请注意还有一个内部类没有封闭实例:


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


这里,new A() { ... }是在静态上下文中定义的内部类,并且没有封闭实例。

其它参考1


Java教程说:[71]



  术语:嵌套类是
  分为两类:静态
  和非静态的。嵌套类
  声明为static的简单调用
  静态嵌套类。非静态
  嵌套类称为内部
  类。



一般来说,术语嵌套和内部可以被大多数程序员互换使用,但我会使用正确的术语嵌套类,它涵盖了内部和静态。


类可以嵌套 ad infinitum ,例如类A可以包含类B,其中包含类C,其中包含类D等。但是,多级类嵌套很少见,因为它通常是糟糕的设计。


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



  • 组织:有时将类排序到另一个类的命名空间中是最明智的,特别是当它不能在任何其他上下文中使用时

  • access:嵌套类可以对其包含类的变量/字段进行特殊访问(确切地说,哪些变量/字段取决于嵌套类的类型,无论是内部还是静态)。

  • 方便:必须为每个新类型创建一个新文件是麻烦的,特别是当该类型只在一个上下文中使用时



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



  • 静态类:声明为另一个类的静态成员

  • 内部类:声明为另一个类的实例成员

  • 本地内部类:在另一个类的实例方法中声明

  • 匿名内部类:类似于本地内部类,但写为返回一次性对象的表达式



让我详细说明一下。


点击


静态类



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


静态类是声明为另一个类的静态成员的类。就像其他静态成员一样,这样的类实际上只是一个使用包含类作为其命名空间的hanger,例如类 Goat 被声明为类的静态成员<包 pizza 中的em> Rhino 名称为 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 的限定类,但在包含类中,它可以通过其简单名称来识别。但是,内部类的每个实例都绑定到其包含类的特定实例:上面, jerry 中创建的 Goat 隐式绑定到 Rhino jerry 中实例此。否则,当我们实例化 Goat 时,我们会将关联的 Rhino 实例显式化:


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


(请注意,您在奇怪的 new 语法中将内部类型称为 Goat :Java从 rhino 部分推断出包含类型。并且,是的新的rhino.Goat()对我来说也更有意义。)


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


public class Rhino {

    private String barry;

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


在内部类中,您可以将包含类的 this 称为 Rhino.this ,您可以使用 this 来引用其成员,例如Rhino.this.barry 。


点击


本地内部课程



本地内部类是在方法体中声明的类。这样的类只在其包含方法中是已知的,因此它只能被实例化并且在其包含方法中访问其成员。获得的是本地内部类实例绑定并可以访问其包含方法的最终局部变量。当实例使用其包含方法的最终本地时,该变量将保留实例创建时保留的值,即使该变量已超出范围(这实际上是Java的粗略,有限的版本)闭包)。


由于本地内部类既不是类或包的成员,也不会使用访问级别声明它。 (但要明确的是,它自己的成员具有像普通类一样的访问级别。)


如果在实例方法中声明了本地内部类,则在创建实例时,内部类的实例化与包含方法s this 所持有的实例相关联,因此包含类的实例成员可以在实例内部类中访问。本地内部类只是通过通过实例化例如本地内部类 Cat 被实例化为 new Cat(),而不是你想象的新的this.Cat()。


点击


匿名内部课程



匿名内部类是编写本地内部类的一种语法上方便的方法。最常见的是,每次运行包含方法时,本地内部类最多只被实例化一次。那么,如果我们可以将本地内部类定义和它的单个实例化组合成一个方便的语法形式,那将是很好的,如果我们不必为该类想出一个名称也会很好(无用的更少)你的代码包含的名称越多越好。。匿名内部类允许这两样:


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


这是一个返回未命名类的新实例的表达式,该实例扩展了 ParentClassName 。你不能提供自己的构造函数;相反,一个是隐式提供的,只是调用超级构造函数,因此提供的参数必须适合超级构造函数。 (如果父级包含多个构造函数,则称为最简单的构造函数,最简单,由一组相当复杂的规则决定,不值得详细学习 - 只需注意NetBeans或Eclipse告诉您的内容。)


或者,您可以指定要实现的接口:


new *InterfaceName*() {*members*}


这样的声明创建了一个未命名类的新实例,它扩展了Object并实现了 InterfaceName 。同样,你不能提供自己的构造函数;在这种情况下,Java隐式地提供了一个no-arg,do-nothing构造函数(因此在这种情况下永远不会有构造函数参数)。


即使您不能给匿名内部类构造函数,您仍然可以使用初始化程序块(放置在任何方法之外的{}块)进行任何您想要的设置。


要明确的是,匿名内部类只是一种使用一个实例创建本地内部类的灵活性较低的方法。如果你想要一个实现多个接口的本地内部类,或者在扩展除 Object 之外的某个类或者指定自己的构造函数时实现接口的本地内部类,那么你就会陷入创建一个常规命名的本地内部类的问题。

其它参考2


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


首先要使条款正确:



  • 嵌套类是一个类,它包含在源代码级别的另一个类中。

  • 如果使用 static 修饰符声明它,则为静态。

  • 非静态嵌套类称为内部类。 (我留在非静态嵌套类。)



到目前为止,马丁的答案是正确的。然而,实际问题是:声明嵌套类静态与否的目的是什么?


如果只是想将类放在一起,或者如果嵌套类专门用于封闭类,则使用静态嵌套类。静态嵌套类与每个其他类之间没有语义差异。


非静态嵌套类是一种不同的野兽。与匿名内部类相似,这种嵌套类实际上是闭包。这意味着他们捕获周围的范围及其封闭的实例,并使其可访问。或许一个例子可以澄清这一点。看到这个容器的存根:


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)


为了完整起见:


匿名类非静态嵌套类的完美示例,它没有与之关联的名称,以后不能引用。

其它参考3


我认为上述答案都没有向您解释嵌套类和静态嵌套类在应用程序设计方面的真正区别:


概述



嵌套类可以是非静态的或静态的,并且在每种情况下是在另一个类中定义的类。 嵌套类应仅存在于包含类,如果嵌套类对其他类(不仅是封闭的)有用,则应声明为顶级类。


差分



非静态嵌套类:与包含类的封闭实例隐式关联,这意味着可以调用封闭实例的方法和访问变量。非静态嵌套类的一个常见用途是定义Adapter类。


静态嵌套类:无法访问封闭的类实例并在其上调用方法,因此在嵌套类不需要访问封闭类的实例时应该使用它。静态嵌套类的一个常见用途是实现外部对象的组件。


结论



因此,从设计的角度来看,两者之间的主要区别是:非静态嵌套类可以访问容器类的实例,而静态可以t 。

其它参考4


简单来说,我们需要嵌套类主要是因为Java不提供闭包。


嵌套类是在另一个封闭类的主体内定义的类。它们有两种类型 - 静态和非静态。


它们被视为封闭类的成员,因此您可以指定四个访问说明符中的任何一个 - private, package, protected, public。我们没有顶级课程的奢侈品,只能宣布public或包装私密。


内部类也称为非堆栈类可以访问顶级类的其他成员,即使它们被声明为私有,而静态嵌套类也无法访问顶级类的其他成员。


public class OuterClass {
    public static class Inner1 {
    }
    public class Inner2 {
    }
}


Inner1是我们的静态内部类,Inner2是我们的内部类,它不是静态的。它们之间的关键区别是,你不能在没有外部的情况下创建Inner2实例,因为你可以独立创建Inner1对象。


你什么时候使用内心课?


考虑Class AClass B相关的情况,Class B需要访问Class A成员,而Class B仅与Class A相关。内部课程进入了画面。


要创建内部类的实例,需要创建外部类的实例。


OuterClass outer = new OuterClass();
OuterClass.Inner2 inner = outer.new Inner2();


要么


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


你什么时候使用静态内部类?


当您知道它与封闭类/顶级类的实例没有任何关系时,您将定义一个静态内部类。如果你的内部类没有使用外部类的方法或字段,那只是浪费空间,所以让它静止。


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


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


静态嵌套类的优点是它不需要包含类/顶级类的对象。这可以帮助您减少应用程序在运行时创建的对象数量。

其它参考5


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



    顶级类中的
  • 静态类嵌套类

  • 顶级类中的
  • 非静态类内部类,进一步
    还有两种形式:

    • 本地类 - 在方块或构造函数体内的块内声明的命名类

    • 匿名类 - 在表达式和语句中创建实例的未命名类




但是,很少有其他要记住的要点:



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

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

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



    • new YourClass(){};表示class [Anonymous] extends YourClass {}

    • new YourInterface(){};表示class [Anonymous] implements YourInterface {}







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

其它参考6


以下是Java内部类和静态嵌套类之间的主要差异和相似之处。


希望能帮助到你!


内部课程




  • 可以访问外部类实例和静态方法和字段

  • 与封闭类的实例相关联所以要实例化它首先需要一个外部类的实例(注意 new 关键字的地方):


    Outerclass.InnerClass innerObject = outerObject.new Innerclass();
    

  • 无法定义任何静态成员本身

  • 无法拥有接口声明



静态嵌套类




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

  • 与封闭类的任何实例无关因此要实例化它:


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



相似性




  • 内部课程都可以访问外部课程的私有字段和方法
  • 此外,外部课程可以访问内部课程的私有字段和方法

  • 这两个类都可以拥有私有,受保护或公共访问修饰符



为什么要使用嵌套类?



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



  

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

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

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

  •   


其它参考7


嵌套类:类内部的类


类型:



  1. 静态嵌套类

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



区别:


非静态嵌套类[[Inner class]]


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


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


静态嵌套类


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


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


如果要访问x,请编写以下内部方法


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

其它参考8


在创建外部类的实例时,将创建内部类的实例。因此,内部类的成员和方法可以访问外部类的实例(对象)的成员和方法。当外部类的实例超出范围时,内部类实例也不再存在。


静态嵌套类没有具体的实例。它只是在第一次使用时加载(就像静态方法一样)。它是一个完全独立的实体,其方法和变量没有任何实体。访问外部类的实例。


静态嵌套类不与外部对象耦合,它们更快,并且它们不占用堆/堆栈内存,因为它不需要创建此类的实例。因此经验法则是尝试定义静态嵌套class,尽可能限制范围(private>=class>=protected>=public),然后将其转换为内部类(通过删除静态标识符)并放宽范围,如果它确实是必要的。

其它参考9


关于嵌套静态类的使用有一些微妙之处,这些静态类在某些情况下可能很有用。


而静态属性在通过实例化类之前实例化它的构造函数,
嵌套静态类中的静态属性似乎不会被实例化,直到之后
类的构造函数被调用,或者至少在第一次引用属性之后才被调用,
即使它们被标记为最终。


考虑这个例子:


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");
    }
}


即使嵌套和innerItem都被声明为静态最终。那个设定
在实例化类之后(或至少在实例化之后),nested.innerItem不会发生
直到首次引用嵌套静态项之后,就像你自己看到的那样
通过评论和取消注释我在上面引用的行。同样不成立
对于outerItem为true。


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

其它参考10


在创建实例的情况下,非实例
静态内部类是使用引用创建的
定义它的外部类的对象。这个
意味着它有实例。
但是静态内部类的实例
是使用外类的引用创建的,而不是
外类对象的借鉴。这意味着它
没有透露实例。


例如:


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….
  }
}

其它参考11


我不认为这里有很多内容,大多数答案完美地解释了静态嵌套类和内部类之间的区别。但是,在使用嵌套类和内部类时,请考虑以下问题。
正如在几个答案中提到的那样,内部类不能在没有封闭类的实例的情况下实例化,这意味着它们 HOLD 一个指针到它们的封闭类的实例,它可以导致内存溢出或堆栈溢出异常,因为即使不再使用GC,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;上的注释,程序将会输出
我被摧毁了!,但保留这个评论它不会。

原因是仍然引用了白色内部实例GC无法收集它并且因为它引用(有一个指针)外部实例它也没有被收集。在项目中有足够的这些对象,并且内存不足。

与不支持内部类实例的静态内部类相比,因为它与实例无关但与类相关。
如果你使Inner类静态并用Outer.Inner i = new Outer.Inner();实例化,上面的程序可以打印我被销毁了!

其它参考12


这些术语可互换使用。如果你想对它真的很迂腐,那么你可以定义嵌套类来引用一个静态内部类,一个没有封闭实例的内部类。在代码中,您可能会遇到以下情况:


public class Outer {
    public class Inner {}

    public static class Nested {}
}


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

其它参考13


嵌套类是一个非常通用的术语:每个不是顶级的类都是嵌套类。
内部类是非静态嵌套类。
Joseph Darcy写了关于嵌套,内部,成员和顶级类的非常好的解释。[73]

其它参考14


嗯......内部类是一个嵌套类...你的意思是匿名类和内部类吗?


编辑:如果你实际上意味着内部与匿名......内部类只是在类中定义的类,例如:


public class A {
    public class B {
    }
}


而匿名类是匿名定义的类的扩展,因此没有定义实际的类,如:


public class A {
}

A anon = new A() { /* you could change behavior of A here */ };


进一步编辑:


维基百科声称Java存在差异,但我已经使用Java工作了8年,这是我第一次听到这样的区别......更不用说那里没有提及支持声明了。 。底线,内部类是在类中定义的类(静态或非静态),而嵌套只是另一个术语,意思是相同的东西。[74]


静态和非静态嵌套类之间存在细微差别...基本上非静态内部类具有对实例字段的隐式访问和封闭类的方法(因此它们不能在静态上下文中构造,它将是一个编译器错误)。另一方面,静态嵌套类不具有对实例字段和方法的隐式访问权限,并且可以在静态上下文中构造。

其它参考15


针对学习者,他们是Java和/或嵌套类的新手


嵌套类可以是:

1.静态嵌套类。

 2.非静态嵌套类。 (也称为内部类)=>请记住这个



点击
1.内部课程

例:


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



内部类是嵌套类的子集:



  • 内部类是嵌套类的特定类型

  • 内部类是嵌套类的子集

  • 您可以说内部类也是嵌套类,但您可以 NOT 说嵌套类也是内部类。



内部专业:



  • 内部类的实例具有访问外部类成员的所有,甚至是那些标记为私有的成员



点击
2.Static Nested Classes:

例:


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


案例1:从非封闭类中实例化静态嵌套类


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"
  }
}


案例2:从封闭类中实例化静态嵌套类


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"
  }

}


静态类的专长:



  • 静态内部类只能访问外部类的静态成员,并且无法访问非静态成员。



结论:结果
问题: Java中内部类和静态嵌套类之间的主要区别是什么?
答案:只是详细介绍上面提到的每个课程。

其它参考16


Java中的内部类嵌套静态类都是在另一个类中声明的类,在Java中称为顶级类。在Java术语中,如果声明嵌套类为static,则它将在Java中调用嵌套静态类,而非静态嵌套类则简称为内部类。


Java中的内部类是什么?


任何不是顶级或在另一个类中声明的类都称为嵌套类,在这些嵌套类中,声明为非静态的类在Java中称为Inner类。 Java中有三种内部类:


1)本地内部类 - 在代码块或方法中声明。

2)匿名内部类 - 是一个没有名称可以引用并在创建它的同一位置初始化的类。

3)成员内部类 - 被声明为外部类的非静态成员。


public class InnerClassTest {
    public static void main(String args[]) {      
        //creating local inner class inside method i.e. main() 
        class Local {
            public void name() {
                System.out.println("Example of Local class in Java");

            }
        }      
        //creating instance of local inner class
        Local local = new Local();
        local.name(); //calling method from local inner class

        //Creating anonymous inner class in Java for implementing thread
        Thread anonymous = new Thread(){
            @Override
            public void run(){
                System.out.println("Anonymous class example in java");
            }
        };
        anonymous.start();

        //example of creating instance of inner class
        InnerClassTest test = new InnerClassTest();
        InnerClassTest.Inner inner = test.new Inner();
        inner.name(); //calling method of inner class
    }

     //Creating Inner class in Java
    private class Inner{
        public void name(){
            System.out.println("Inner class example in java");
        }
    }
}


什么是Java中的嵌套静态类?


嵌套静态类是另一个类,它在类中声明为成员并且是静态的。嵌套静态类也被声明为外部类的成员,可以像任何其他成员一样使其成为私有,公共或受保护。嵌套静态类相对于内部类的主要好处之一是嵌套静态类的实例未附加到外部类的任何封闭实例。 您也不需要任何外层实例来创建Java中嵌套静态类的实例。


1)它可以访问外部类的静态数据成员,包括私有。

2)静态嵌套类无法访问非静态(实例)数据成员或方法。


public class NestedStaticExample {
    public static void main(String args[]){  
        StaticNested nested = new StaticNested();
        nested.name();
    }  
    //static nested class in java
    private static class StaticNested{
        public void name(){
            System.out.println("static nested class example in java");
        }
    }
}


参考:Java中的内部类和嵌套静态类,带示例[75]

其它参考17


我想这里的人应该注意到海报:Static Nest Class只是第一个内部类。
例如:


 public static class A {} //ERROR

 public class A {
     public class B {
         public static class C {} //ERROR
     }
 }

 public class A {
     public static class B {} //COMPILE !!!

 }


因此,总结一下,静态类并不依赖它所包含的类。因此,它们不能在正常的类中。(因为普通类需要一个实例)。

其它参考18


当我们在类中声明静态成员类时,它被称为顶级嵌套类或静态嵌套类。它可以证明如下:


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


当我们在类中声明非静态成员类时,它被称为内部类。内部类可以如下所示:


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

其它参考19


以下是static nested classinner 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()); 

    }

}

其它参考20


不同之处在于,静态的嵌套类声明可以在封闭类之外实例化。


当你有一个嵌套的类声明 not static,也称为内部类时,Java不会让你实例化它,除非通过封闭的类。创建的对象out内部类链接到从外部类创建的对象,因此内部类可以引用外部的字段。


但是如果它是静态的,那么链接就不存在了,外部字段不能被访问(除了通过像任何其他对象那样的普通引用),因此你可以自己实例化嵌套类。

其它参考21


首先没有这样的类叫做静态类。静态修饰符用于内部类(称为嵌套类)表示它是外部类的静态成员,这意味着我们可以像其他静态成员一样访问它而没有任何静态成员外类的实例。 (这最初是静电的好处。)


使用嵌套类和常规Inner类之间的区别是:


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


首先我们可以实例化Outerclass然后我们可以访问Inner。


但如果Class是嵌套的,那么语法是:


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


其中使用静态语法作为静态关键字的正常实现。

其它参考22


我已经说明了java代码中可能出现的各种可能的正确和错误情况。


    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);
                        }*/
                    //}
                }
    }

其它参考23


在您阅读了类和对象中的oracle的java教程之后,只需要一些补充。如果您了解内部类和静态嵌套类的Java内存模型,这可能会有所帮助。请阅读以下三个问题,以了解为什么内部类和静态嵌套类是由Java以这种方式设计的。然后你可能知道何时使用内部类以及何时使用静态嵌套类。


内部类对象如何驻留在内存中?


内存管理 - Java中的内部静态类


何时将静态嵌套类(以及其中的静态成员)加载到内存中?


然后阅读此内容以比较内部类和静态嵌套类。


使用Java将内部类设置为静态有什么好处?