首页 文章

Java内部类和静态嵌套类

提问于
浏览
1540

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

25 回答

  • 1533

    我不认为这里有很多内容,大多数答案完美地解释了静态嵌套类和内部类之间的区别 . 但是,在使用嵌套类与内部类时请考虑以下问题 . 正如在几个答案中提到的那样,内部类不能在没有它们的封闭类的实例化的情况下实例化,这意味着它们的封闭类的实例可以导致内存溢出或堆栈溢出异常,因为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; 上的注释,程序将输出“ I am destroyed ! ”,但保留此注释不会 .
    原因是仍然引用了白色内部实例GC无法收集它,并且因为它引用(有指针)外部实例它也没有被收集 . 在项目中有足够的这些对象,并且内存不足 .
    与不支持内部类实例的静态内部类相比,因为它与实例无关但与类相关 . 如果你使Inner类静态并使用 Outer.Inner i = new Outer.Inner(); 实例化,上面的程序可以打印“ I am destroyed !

  • 8

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

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

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

  • -1

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

    当你有一个非静态的嵌套类声明(也称为内部类)时,除了通过封闭类之外,Java不允许你实例化它 . 从内部类创建的对象链接到从外部类创建的对象,因此内部类可以引用外部的字段 .

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

  • 3

    简单来说,我们需要嵌套类主要是因为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();
    

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

  • 0

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

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

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

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

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

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

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

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

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

  • 31

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

    What is Inner Class in 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");
            }
        }
    }
    

    What is nested static class in Java?

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

    1)它可以访问外部类的静态数据成员,包括private .
    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");
            }
        }
    }
    

    参考:Inner class and nested Static Class in Java with Example

  • 15

    来自Java Tutorial

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

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

    OuterClass.StaticNestedClass
    

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

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

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

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

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

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

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

    见:Java Tutorial - Nested Classes

    为了完整性,请注意还有inner class without an enclosing instance这样的东西:

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

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

  • 7

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

    OverView

    A nested class 可以是非静态的或静态的,并且在每种情况下都是 is a class defined within another class . A nested class should exist only to serve is enclosing class ,如果嵌套类对其他类(不仅是封闭的)有用,则应声明为顶级类 .

    差异

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

    Static Nested Class :可以't access enclosing class instance and invoke methods on it, so should be used when the nested class doesn' t要求访问封闭类的实例 . 静态嵌套类的一个常见用途是实现外部对象的组件 .

    结论

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

  • 5

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

    顶级类中的

    • static classnested class
      顶级类中的

    • non static classinner class ,还有两种形式:

    • local class - 在块内部声明的命名类,如方法或构造函数体

    • anonymous class - 未命名的类,其实例是在表达式和语句中创建的

    但是,很少有其他 points to remembers

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

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

    • 匿名类默认扩展父类或实现父接口,没有进一步的子句扩展任何其他类或实现更多接口 . 所以,

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

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


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

  • 11

    Java编程语言允许您在另一个类中定义类 . 这样的类称为嵌套类,如下所示:

    class OuterClass {
    ...
    class NestedClass {
        ...
        }
    }
    

    嵌套类分为两类:静态和非静态 . 声明为static的嵌套类称为静态嵌套类 . 非静态嵌套类称为内部类 . 我们应该记住的一件事是非静态嵌套类(内部类)可以访问封闭类的其他成员,即使它们被声明为私有 . 静态嵌套类只能访问封闭类的其他成员(如果它们是静态的) . 它无法访问外部类的非静态成员 . 与类方法和变量一样,静态嵌套类与其外部类相关联 . 例如,要为静态嵌套类创建对象,请使用以下语法:

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

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

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

    为什么我们使用嵌套类

    • 这是一种逻辑分组仅在一个地方使用的类的方法 .

    • 它增加了封装 .

    • 它可以使代码更具可读性和可维护性 .

    source

  • 85

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

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

    考虑这个例子:

    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中看到的 .

  • 0

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

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

    public class A {
        public class B {
        }
    }
    

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

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

    进一步编辑:

    维基百科claims there is a difference在Java中,但我've been working with Java for 8 years, and it'是我第一次听到这样的区别...更不用说那里没有引用来支持声明...底线,内部类是一个类中定义的类(静态或者没有),嵌套只是另一个意思相同的术语 .

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

  • 7

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

    希望能帮助到你!

    内课

    • Can access 到外类 both instance and static 方法和字段

    • Associated with instance of enclosing class 所以要实例化它首先需要一个外部类的实例(注意新关键字的地方):

    Outerclass.InnerClass innerObject = outerObject.new Innerclass();
    
    • Cannot 定义任何 static members 本身

    • CannotClassInterface 声明

    静态嵌套类

    • Cannot access 外类 instance 方法或字段

    • Not associated with any instance of enclosing class 所以要实例化它:

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

    相似之处

    • Inner classes 都可以访问 outer class 23372

    • 此外 Outer class 可以访问 private fields and methods inner classes

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

    为什么使用嵌套类?

    根据Oracle文档,有几个原因(full documentation):

    这是一种逻辑分组仅在一个地方使用的类的方法:如果一个类只对另一个类有用,那么将它嵌入该类并将两者保持在一起是合乎逻辑的 . 嵌套这样的“帮助类”使得它们的包更加简化 . 它增加了封装:考虑两个顶级类A和B,其中B需要访问A的成员,否则这些成员将被声明为私有 . 通过将类B隐藏在类A中,可以将A的成员声明为私有,并且B可以访问它们 . 此外,B本身可以隐藏在外面的世界里 . 它可以带来更易读和可维护的代码:在顶级类中嵌套小类会使代码更接近于使用它的位置 .

  • 26

    嵌套类是一个非常通用的术语:每个不是顶级的类都是嵌套类 . 内部类是非静态嵌套类 . 约瑟夫达西写了一篇关于Nested, Inner, Member, and Top-Level Classes的非常好的解释 .

  • 5

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

    嵌套类可以是:
    1.静态嵌套类 .
    2.非静态嵌套类 . (也称为 Inner classes )=>请记住这一点

    1.Inner classes
    例:

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

    Inner classes are subsets of nested classes:

    • inner class是一种特定类型的嵌套类

    • 内部类是嵌套类的子集

    • 你可以说内部类也是一个嵌套类,但你可以 NOT 说嵌套类也是一个内部类 .

    Specialty of Inner class:

    • 内部类的实例有 access to all 外部类的成员,甚至那些标记为“私有”的成员

    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:

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

    Conclusion:
    问题:Java中内部类和静态嵌套类之间的主要区别是什么?
    答:只需详细说明上述每个类别 .

  • 6

    Java中静态和非静态嵌套类之间的区别

    1)嵌套静态类不需要引用外部类,但非静态嵌套类或内部类需要外部类引用 . 如果不创建Outer类的实例,则无法创建Inner类的实例 . 在使嵌套类静态或非静态时,这是最重要的考虑因素 .

    2)static class实际上是类的静态成员,可以在静态上下文中使用,例如外类的静态方法或静态块 .

    3)静态和非静态嵌套类之间的另一个区别是你不能访问非静态成员,例如方法和字段直接嵌入到静态类中 . 如果这样做,您将收到类似“非静态成员不能在静态上下文中使用”的错误 . 而Inner类可以访问Outer类的静态和非静态成员 .

    public class OuterClass {
        private static String message = "Hello JAVA";
    
        // How to create instance of static and non static nested class
        public static void main(String... args) {
    
            // creating instance of nested Static class
            InnerClassStatic printer = new InnerClassStatic();
    
            //calling non static method of nested static class
            printer.printMessage();
    
            // creating instance of non static nested class or InnerClass class
            // In order to create instance of InnerClass class you need an OuterClass class instance
            OuterClass outerClass = new OuterClass(); //outerClass class instance for creating non static nested class
    
            InnerClass innerClass = outerClass.new InnerClass();
            innerClass.display();  //calling non static method of InnerClass class
    
            // we can also combine above steps in one step to create instance of InnerClass class
            InnerClass nonStaticIner = new OuterClass().new InnerClass();
    
            nonStaticIner.display(); // similarly you can now call InnerClass class method
        }
    
    
        // Static nested class
        private static class InnerClassStatic {
            //Only static member of OuterClass class is directly accessible in nested static class
    
            public void printMessage() {
                // Compile time error if message field is not static
                System.out.println("Message from nested static class : " + message);
            }
        }
    
        //non static nested class - also called InnerClass class
        private class InnerClass {
    
            // Both static and non static member of OuterClass class is accessible in this InnerClass class
            public void display() {
                System.out.println(" Message from non static nested or InnerClass class : " + message);
            }
        }
    }
    

    输出:

    Message from nested static class : Hello JAVA
    Message from non static nested or Inner class : Hello JAVA
    Message from non static nested or Inner class : Hello JAVA
    

    这就是Java中静态和非静态嵌套类之间的区别 . 到目前为止,我们只触及成员Inner类,而没有讨论Inner类的其他两种类型,例如本地类和Anonymous Inner类 . 在这个Java教程中,我们已经看到了什么是Java中的嵌套静态类以及如何在Java中创建嵌套静态和非静态类的实例 .

    总之,它易于创建嵌套静态类的实例,因为它不需要Outer类的实例,而非静态嵌套类,例如内部类总是需要一个外部类实例,没有外部类就不能存在 . 如果你可以使用它,那么你必须在静态类和非静态类之间进行选择,而不是选择静态嵌套类 .

  • 0

    以下是 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()); 
    
        }
    
    }
    
  • 10

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

    首先要使条款正确:

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

    • 如果使用 static 修饰符声明它,则它是静态的 .

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

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

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

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

    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实例语法为 Container.this .

    更多核心解释如下:

    如果查看编译器为(非静态)嵌套类生成的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)
    

    为了完整起见:

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

  • 11

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

    public class Outer {
        public class Inner {}
    
        public static class Nested {}
    }
    

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

  • 0

    Java tutorial says

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

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

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

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

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

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

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

    four kinds of nested class in Java . 简而言之,它们是:

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

    • inner class :声明为另一个类的实例成员

    • local inner class :在另一个类的实例方法中声明

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

    让我详细说明一下 .

    静态类

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

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

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

    (注意你用奇怪的新语法将内部类型称为Goat:Java从rhino部分推断出包含类型 . 而且,新的rhino.Goat()对我来说也更有意义 . )

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

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

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

    本地内部类

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

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

    如果在实例方法中声明了本地内部类,则在实例's creation, and so the containing class'实例成员可以像实例内部类一样访问时,内部类的实例化与包含方法所拥有的实例相关联 . 本地内部类仅通过其名称实例化,例如,本地内部类Cat被实例化为新的Cat(),而不是你想象的新的this.Cat() .

    匿名内部类

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

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

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

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

    new *InterfaceName*() {*members*}
    

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

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

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

  • 128

    我想这里的人应该注意到海报: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 !!!
    
     }
    

    因此,总结一下,静态类不依赖于它包含哪个类 . 所以,他们不能在正常 class . (因为普通类需要一个实例) .

  • 540

    在创建实例的情况下,非静态内部类的实例是使用外部类的对象的引用创建的,在该对象中定义它 . 这意味着它有实例 . 但是静态内部类的实例是使用外部类的引用创建的,而不是使用外部类的对象的引用 . 这意味着它没有包含实例 .

    例如:

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

    我已经说明了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);
                            }*/
                        //}
                    }
        }
    
  • 8

    嵌套类:类内部的类

    类型:

    • 静态嵌套类

    • 非静态嵌套类[内部类]

    区别:

    Non-static nested class [Inner class]

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

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

    Static nested class

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

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

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

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

相关问题