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


当前回答

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

例如:

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

其他回答

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

针对Java和/或嵌套类新手的学习者

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

1.内部类例子:

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

内部类是嵌套类的子集:

内部类是特定类型的嵌套类内部类是嵌套类的子集可以说内部类也是嵌套类,但不能说嵌套类也是内部类。

内层专业:

内部类的实例可以访问外部类的所有成员,即使是标记为“private”的成员

2.静态嵌套类:例子:

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中内部类和静态嵌套类的主要区别是什么?答:只需仔细阅读上面提到的每门课的细节。

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

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

考虑以下示例:

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”为true。

至少这是我在Java6.0中看到的。

Java教程说:

术语:嵌套类是分为两类:静态并且是非静态的。嵌套的类被声明为静态的静态嵌套类。非静态嵌套类称为内部类类。

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

类可以无限嵌套,例如类A可以包含B类,B类包含C类,C类包含D类等。但是,很少有一个以上的类嵌套,因为这通常是错误的设计。

创建嵌套类有三个原因:

组织:有时将一个类分类到另一个类的命名空间中似乎是最明智的,尤其是当它不会在任何其他上下文中使用时访问:嵌套类具有对其包含类的变量/字段的特殊访问权限(确切地说,哪些变量/字段取决于嵌套类的类型,无论是内部的还是静态的)。方便:必须为每个新类型创建一个新文件,这同样令人烦恼,尤其是当该类型只在一个上下文中使用时

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

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

让我详细说明一下。

静态类

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

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

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

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

那么这给我们带来了什么?内部类实例可以访问包含类实例的实例成员。这些封闭实例成员仅通过其简单名称在内部类中引用,而不是通过this(内部类中的this引用内部类实例,而不是关联的包含类实例):

public class Rhino {

    private String barry;

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

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

本地内部类

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

因为本地内部类既不是类或包的成员,所以它没有用访问级别声明。(但是,要清楚,它自己的成员拥有与普通类一样的访问级别。)

如果在实例方法中声明了本地内部类,则在创建实例时,内部类的实例化与包含方法的this所持有的实例相关联,因此包含类的实例成员可以像在实例内部类中一样访问。本地内部类仅通过其名称实例化,例如,本地内部类Cat被实例化为new Cat(),而不是您可能期望的new this.Cat()。

匿名内部类

匿名内部类是编写本地内部类的语法上方便的方法。最常见的情况是,本地内部类在每次运行其包含方法时最多实例化一次。那么,如果我们能够将本地内部类定义及其单个实例化组合成一种方便的语法形式,这将是很好的,如果我们不必为类想出一个名称(代码中包含的无用名称越少越好),这也是很好的。匿名内部类同时允许以下两种功能:

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

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

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

new *InterfaceName*() {*members*}

这样的声明创建了一个未命名类的新实例,该类扩展了Object并实现了InterfaceName。同样,您不能提供自己的构造函数;在本例中,Java隐式地提供了一个无参数、不做任何事情的构造函数(因此在本例中将不会有构造函数参数)。

即使您不能给匿名内部类一个构造函数,您仍然可以使用初始值设定项块(放置在任何方法外部的{}块)进行任何设置。

请注意,匿名内部类只是用一个实例创建本地内部类的一种不太灵活的方式。如果您想要一个实现多个接口的本地内部类,或者在扩展除Object之外的某个类时实现接口,或者指定自己的构造函数,那么您只能创建一个常规的命名本地内部类。

嗯……内部类是嵌套类……您是指匿名类和内部类吗?

编辑:如果您实际上是指内部v.s.匿名:内部类只是在类中定义的类,例如:

public class A {
    public class B {
    }
}

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

public class A {
}

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

进一步编辑:

维基百科声称Java存在差异,但我已经用Java工作了八年,这是我第一次听到这样的区别——更不用说那里没有引用来支持这一说法……总之,内部类是在类中定义的类(静态或非静态),嵌套只是另一个意思相同的术语。

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