Java inner class and static nested class

2018-12-30 23:35发布

What is the main difference between an inner class and a static nested class in Java? Does design / implementation play a role in choosing one of these?

24条回答
余生无你
2楼-- · 2018-12-31 00:01

Here is key differences and similarities between Java inner class and static nested class.

Hope it helps!

Inner class

  • Can access to outer class both instance and static methods and fields
  • Associated with instance of enclosing class so to instantiate it first needs an instance of outer class (note new keyword place):

    Outerclass.InnerClass innerObject = outerObject.new Innerclass();
    
  • Cannot define any static members itself

  • Cannot have Class or Interface declaration

Static nested class

  • Cannot access outer class instance methods or fields

  • Not associated with any instance of enclosing class So to instantiate it:

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

Similarities

  • Both Inner classes can access even private fields and methods of outer class
  • Also the Outer class have access to private fields and methods of inner classes
  • Both classes can have private, protected or public access modifier

Why Use Nested Classes?

According to Oracle documentation there're several reasons (full documentation):

  • It is a way of logically grouping classes that are only used in one place: If a class is useful to only one other class, then it is logical to embed it in that class and keep the two together. Nesting such "helper classes" makes their package more streamlined.

  • It increases encapsulation: Consider two top-level classes, A and B, where B needs access to members of A that would otherwise be declared private. By hiding class B within class A, A's members can be declared private and B can access them. In addition, B itself can be hidden from the outside world.

  • It can lead to more readable and maintainable code: Nesting small classes within top-level classes places the code closer to where it is used.

查看更多
与君花间醉酒
3楼-- · 2018-12-31 00:04

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

    }

}
查看更多
人气声优
4楼-- · 2018-12-31 00:06

The instance of the inner class is created when instance of the outer class is created. Therefore the members and methods of the inner class have access to the members and methods of the instance (object) of the outer class. When the instance of the outer class goes out of scope, also the inner class instances cease to exist.

The static nested class doesn't have a concrete instance. It's just loaded when it's used for the first time (just like the static methods). It's a completely independent entity, whose methods and variables doesn't have any access to the instances of the outer class.

The static nested classes are not coupled with the outer object, they are faster, and they don't take heap/stack memory, because its not necessary to create instance of such class. Therefore the rule of thumb is to try to define static nested class, with as limited scope as possible (private >= class >= protected >= public), and then convert it to inner class (by removing "static" identifier) and loosen the scope, if it's really necessary.

查看更多
泪湿衣
5楼-- · 2018-12-31 00:08

I think, the convention that is generally followed is this:

  • static class within a top level class is a nested class
  • non static class within a top level class is a inner class, which further has two more form:
    • local class - named classes declared inside of a block like a method or constructor body
    • anonymous class - unnamed classes whose instances are created in expressions and statements

However, few other points to remembers are:

  • Top level classes and static nested class are semantically same except that in case of static nested class it can make static reference to private static fields/methods of its Outer [parent] class and vice versa.

  • Inner classes have access to instance variables of the enclosing instance of the Outer [parent] class. However, not all inner classes have enclosing instances, for example inner classes in static contexts, like an anonymous class used in a static initializer block, do not.

  • Anonymous class by default extends the parent class or implements the parent interface and there is no further clause to extend any other class or implement any more interfaces. So,

    • new YourClass(){}; means class [Anonymous] extends YourClass {}
    • new YourInterface(){}; means class [Anonymous] implements YourInterface {}

I feel that the bigger question that remains open which one to use and when? Well that mostly depends on what scenario you are dealing with but reading the reply given by @jrudolph may help you making some decision.

查看更多
长期被迫恋爱
6楼-- · 2018-12-31 00:08

Nested class: class inside class

Types:

  1. Static nested class
  2. Non-static nested class [Inner class]

Difference:

Non-static nested class [Inner class]

In non-static nested class object of inner class exist within object of outer class. So that data member of outer class is accessible to inner class. So to create object of inner class we must create object of outer class first.

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

Static nested class

In static nested class object of inner class don't need object of outer class, because the word "static" indicate no need to create object.

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

If you want to access x, then write the following inside method

  outerclass.nestedclass.x;  i.e. System.out.prinltn( outerclass.nestedclass.x);
查看更多
低头抚发
7楼-- · 2018-12-31 00:09

There is a subtlety about the use of nested static classes that might be useful in certain situations.

Whereas static attributes get instantiated before the class gets instantiated via its constructor, static attributes inside of nested static classes don't seem to get instantiated until after the class's constructor gets invoked, or at least not until after the attributes are first referenced, even if they are marked as 'final'.

Consider this example:

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

Even though 'nested' and 'innerItem' are both declared as 'static final'. the setting of nested.innerItem doesn't take place until after the class is instantiated (or at least not until after the nested static item is first referenced), as you can see for yourself by commenting and uncommenting the lines that I refer to, above. The same does not hold true for 'outerItem'.

At least this is what I'm seeing in Java 6.0.

查看更多
登录 后发表回答