Java内部类和静态嵌套类

Java内部类和静态嵌套类,java,inner-classes,static-classes,Java,Inner Classes,Static Classes,Java中内部类和静态嵌套类之间的主要区别是什么?设计/实现在选择其中一个方面起作用吗?嗯。。。内部类是嵌套类。。。你是说匿名类和内部类吗 编辑:如果你实际上是指内部vs匿名。。。内部类只是在类中定义的类,例如: public class A { public class B { } } 鉴于匿名类是匿名定义的类的扩展,因此没有定义实际的“类”,如: public class A { } A anon = new A() { /* you could change behav

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

嗯。。。内部类是嵌套类。。。你是说匿名类和内部类吗

编辑:如果你实际上是指内部vs匿名。。。内部类只是在类中定义的类,例如:

public class A {
    public class B {
    }
}
鉴于匿名类是匿名定义的类的扩展,因此没有定义实际的“类”,如:

public class A {
}

A anon = new A() { /* you could change behavior of A here */ };
进一步编辑:

Wikipedia在Java中,但我已经使用Java 8年了,这是我第一次听到这样的区别…更不用说没有引用来支持这一说法…底线是,内部类是在类中定义的类(静态或非静态),嵌套只是另一个术语,表示相同的意思


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

这些术语可以互换使用。如果您想真正学究化,那么可以定义“嵌套类”引用没有封闭实例的静态内部类。在代码中,您可能有如下内容:

public class Outer {
    public class Inner {}

    public static class Nested {}
}
但这并不是一个被广泛接受的定义。

来自:

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

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

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

OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
OuterClass outerObject = new OuterClass()
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
OuterClass.Inner1 nestedObject = new OuterClass.Inner1();
OuterClass.StaticNestedClass nestedObject =
 new OuterClass.StaticNestedClass(); 
OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();
作为内部类实例的对象存在于外部类的实例中。考虑下面的类:

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

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

OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
OuterClass outerObject = new OuterClass()
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
OuterClass.Inner1 nestedObject = new OuterClass.Inner1();
OuterClass.StaticNestedClass nestedObject =
 new OuterClass.StaticNestedClass(); 
OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();
见:

为完整起见,请注意,还有一种情况:


这里,
newa(){…}
是一个在静态上下文中定义的内部类,没有封闭实例。

嵌套类是一个非常通用的术语:每个不是顶级的类都是嵌套类。 内部类是非静态嵌套类。
Joseph Darcy写了一篇很好的解释。

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

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

OuterClass outer = new OuterClass();
OuterClass.Inner2 inner = outer.new Inner2();
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");
        }
    }
}

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

我认为上述答案中的真正区别并不明显

首先要正确使用条款:

  • 嵌套类是包含在源代码级别的另一个类中的类
  • 如果使用static修饰符声明它,则它是静态的
  • 非静态嵌套类称为内部类。(我使用非静态嵌套类。)
到目前为止,马丁的回答是正确的。然而,实际的问题是:声明嵌套类静态与否的目的是什么


如果您只想将属于局部的类保持在一起,或者如果嵌套类专用于封闭类,则可以使用静态嵌套类。静态嵌套类和其他所有类之间没有语义差异

非静态嵌套类是不同的beast。与匿名内部类类似,此类嵌套类实际上是闭包。这意味着它们捕获周围的作用域和封闭的实例,并使其可访问。也许一个例子可以说明这一点。请参见容器的此存根:

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来访问容器的封闭实例

更多核心解释如下:

如果查看编译器为(非静态)嵌套类生成的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
}
会被编译成类似(字节码)的调用吗

为了完整起见:

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

术语:嵌套类是 分为两类:静态 而且是非静态的。嵌套类 声明为静态的,只需调用 静态嵌套类。非静态 嵌套类称为内部类 上课

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

class outerclass A {
    static class nestedclass B {
        static int x = 10;
    }
}
  outerclass.nestedclass.x;  i.e. System.out.prinltn( outerclass.nestedclass.x);
 public static class A {} //ERROR

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

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

 }
OuterClass.InnerClass inner = new OuterClass().new InnerClass();
OuterClass.InnerClass inner = new OuterClass.InnerClass();
public class OuterClass {
    public static class Inner1 {
    }
    public class Inner2 {
    }
}
OuterClass outer = new OuterClass();
OuterClass.Inner2 inner = outer.new Inner2();
OuterClass.Inner2 inner = new OuterClass().new Inner2();
OuterClass.Inner1 nestedObject = new OuterClass.Inner1();
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….
  }
}
class OuterClass  {
/*  some code here...*/
     class InnerClass  {  }
/*  some code here...*/
}
class EnclosingClass {
  static class Nested {
    void someMethod() { System.out.println("hello SO"); }
  }
}
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"
  }
}
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"
  }

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

}
Outerclass.InnerClass innerObject = outerObject.new Innerclass();
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
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);
        }
    }
}
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);
     }

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

    }

}
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");
        }
    }
}
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");
        }
    }
}
    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);
                        }*/
                    //}
                }
    }
class OuterClass {
...
class NestedClass {
    ...
    }
}
OuterClass.StaticNestedClass nestedObject =
 new OuterClass.StaticNestedClass(); 
OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();
public class Bank {

    // maximum limit as per current bank policy
    // is subject to change
    private int maxLimit = 7000;

    // ------- PUBLIC METHODS ---------

    public CreditCard issueCard(
            final String firstName,
            final String lastName
    ) {
        final String number = this.generateNumber();
        final int expiryDate = this.generateExpiryDate();
        final int CVV = this.generateCVV();
        return new CreditCard(firstName, lastName, number, expiryDate, CVV);
    }


    public boolean setLimit(
            final CreditCard creditCard,
            final int limit
    ) {
        if (limit <= this.maxLimit) {    // check against current bank policy limit
            creditCard.setLimit(limit);  // access private method Bank.CreditCard.setLimit(int)
            return true;
        }
        return false;
    }

    // ------- PRIVATE METHODS ---------

    private String generateNumber() {
        return "1234-5678-9101-1123";   // the numbers should be unique for each card
    }


    private int generateExpiryDate() {
        return 202405;                  // date is YYYY=2024, MM=05
    }


    private int generateCVV() {
        return 123;                     // is in real-life less predictable
    }


    // ------- PUBLIC STATIC NESTED CLASS ---------

    public static final class CreditCard {
        private final String firstName;
        private final String lastName;
        private final String number;
        private final int expiryDate;
        private final int CVV;

        private int balance;
        private int limit = 100; // default limit

        // the constructor is final but is accessible from outer class
        private CreditCard(
                final String firstName,
                final String lastName,
                final String number,
                final int expiryDate,
                final int CVV
        ) {
            this.firstName = firstName;
            this.lastName = lastName;
            this.number = number;
            this.expiryDate = expiryDate;
            this.CVV = CVV;
        }

        // ------- PUBLIC METHODS ---------

        public String getFirstName() {
            return this.firstName;
        }

        public String getLastName() {
            return this.lastName;
        }

        public String getNumber() {
            return this.number;
        }

        public int getExpiryDate() {
            return this.expiryDate;
        }

        // returns true if financial transaction is successful
        // otherwise false
        public boolean charge(final int amount) {
            final int newBalance = this.balance - amount;
            if (newBalance < -this.limit) {
                return false;
            }
            this.balance = newBalance;
            return true;
        }

        // ------- PRIVATE METHODS ---------

        private int getCVV() {
            return this.CVV;
        }

        private int getBalance() {
            return this.balance;
        }

        private void setBalance(final int balance) {
            this.balance = balance;
        }

        private int getLimit() {
            return limit;
        }

        private void setLimit(final int limit) {
            this.limit = limit;
        }
    }
}