What are the purposes of inner classes

前端 未结 10 1765
终归单人心
终归单人心 2020-11-29 23:14

I am reviewing the concept of inner classes in java. so far from what I\'ve understood and applied java inner classes has a link or access to the methods and fields of its o

相关标签:
10条回答
  • 2020-11-29 23:17

    A classic use for an inner class is the implementation of an iterator inside a container (ArrayList, for example - look for class Itr). All the container wants to expose to the rest of the world is an Iterator. However, it has to create some concrete implementation of that iterator, possibly familiar with the internals of the container. Using an inner class hides the implementation, while keeping it close to the container's implementation. And being inner (i.e. non-static), it is bound to a specific instance of that container, which lets it access private container members.

    There are a few types of inner classes - non-static nested class, local classes and anonymous classes. Each one has a somewhat different purpose, so when asking about an inner class, you should specify what kind are you talking about.

    Assuming you're referring to non-static inner classes, I'd say the reason to use them is the same as using regular classes (namely abstraction and dividing code into logical units), but there's no reason to make this use of classes visible to the rest of the world. You can also make nested classes public, of course, in which case you'd make them nested instead of independent in order to express their tight relation with the outer class.

    0 讨论(0)
  • 2020-11-29 23:22

    Inner classes are best for the purpose of logically grouping classes that are used in one-place. For example, if you want to create class which is used by ONLY enclosing class, then it doesn't make sense to create a separate file for that. Instead you can add it as "inner class"

    As per java tutorial:

    Compelling reasons for using nested classes include the following:

    • It is a way of logically grouping classes that are only used in one place.
    • It increases encapsulation.
    • It can lead to more readable and maintainable code.
    0 讨论(0)
  • 2020-11-29 23:22

    As a general rule, objects should be designed for a single responsibility (Highly cohesive). In other words, any object designed well, should perform a single coherent task. This would be considered best practice for object orientated design.

    Sometimes, however, a developer may design a class that requires a separate specialized class in order to work. This separate specialized class could be considered a helper class.

    If the helper class is not used by any other class, then it would be considered a prime candidate as an inner class

    As elicited by ncmathsadist above, an example of inner class use would be in the implementation of Event handlers.

    For example, in designing a graphical user interface (GUI), a developer may have created a button that performs a particular task after the user presses it.

    The button would need an event handler which listens for when that particular button is pressed.

    In this case, creating the event handler for the button as an inner class would be best practice as the inner class would not be utilized anywhere else other than with the specific button within the GUI class.

    0 讨论(0)
  • 2020-11-29 23:22

    I would just consider that this is just a feature of language. I would not recommend to use it if we adopt OOD and obey the SOLID principle.

    0 讨论(0)
  • 2020-11-29 23:31

    If you find that there is enough code which could be better done by class as class provides us to specify stats and behavior with fields and methods and you don't want this class needs to be used outside of enclosing class. you should use inner class.

    Here the inner class is hidden from the outside world. Inner class can access the private member of enclosing class which provides us encapsulation.

    Let me give example.. Suppose you want to set the gear to cycle and you have a business rule like there are only up to 6 gears. So you can create Inner Class Cycle which would have a method to set the gear. That method has some validation which are checked before setting gear.like the cycle is running...gear number is less than 6...

    best example is event handling code uses inner classes(sometimes anonymous inner classes) to create events and listeners without creating separate Event Object and Event Listener classes for your event..

    0 讨论(0)
  • 2020-11-29 23:33

    Lets say you have a type and its a class, called OuterClass, in a package called "com.custom.classes".

    Then here is how you begin to need an inner class or static class:

    Case 1:

    1. you need to package a group of classes
    2. but also kind of need certain global variables exposed to all these classes at that package level
    3. you understand you can do no such things with packages but realise that you could achieve this with inheritance, where the parent class members can act as global variables that become available for all of its child class instances.
    4. but you don't like the idea that you need to inherit the parent class and also that you need to instantiate the child class to access the global variables. Thats like asking to buy a coffee shop in order to have a coffee.
    5. and so you realise that you can create an OuterClass with the static members and house all the classes in this OuterClass as inner class or static class as needed and lo! The OuterClass static members become available as global variables for these nested classes and you could even access them without instantiating them.

    This code should explain better

    public class InnerClassTester{
      public static void main(String []args){
    
        // without the need to instantiate any class
        // static class without instantiation
        System.out.println(OuterClass.NestedStaticClass1.incrGlobalNum()); // outputs 1
    
        // static class instantiated
        OuterClass.NestedStaticClass2 koolObj = new OuterClass.NestedStaticClass2();
        // works with instantiation as well
        System.out.println(koolObj.incrGlobalNum()); // outputs 2
    
        // inner classes always need to be instantiated
        // and they can only be instantiated from within an instance of outer class
        // think of them as instance member of outer class and this would make sense
        OuterClass.NestedInnerClass1 koolObj2 = new OuterClass().new NestedInnerClass1();
        // works with inner classes as well
        System.out.println(koolObj2.incrGlobalNum()); // outputs 3
     }
    }
    
    class OuterClass{
        // global variable thats only accessible for select classes (or nested classes)
        // we also learn a purpose for private static fields
        private static int privateGlobalValue = 0;
    
        // classes to be grouped
        // static class
        public static class NestedStaticClass1{
            // no need to instantiate this class to access/update the global value
            public static int incrGlobalNum(){
                return ++privateGlobalValue;
            }
        }
    
        public static class NestedStaticClass2{
            // instantiate and still manipulate the global value
            public int incrGlobalNum(){
                return ++privateGlobalValue;
            }
        }
    
        // inner class
        public class NestedInnerClass1{
            // instantiate and still manipulate the global value
            public int incrGlobalNum(){
                return ++privateGlobalValue;
            }
        }
    
    }
    

    Does this remind you of closures in Javascript ? :)


    Most applications of nested classes see it being applied on basis of design decisions. What that means is, every case of a nested class can be replaced with other designs.

    But having said that, it is also true that we can also replace the inheritance pattern with composition pattern (and it is gaining momentum lately) although an inheritance pattern is definitely better when the dependencies between the classes is so much so that composing the dependencies entirely would be ugly.

    Case 2:

    1. you need to implement 2 interfaces, IShark and IMosquito, with the same signature, a public bite method, on the OuterClass.
    2. but you want to display 2 different messages since a shark's bite is a tad different from that of a mosquito's.
    3. however you know that's not possible since only one bite method can be implemented
    4. you know you can create 2 different classes in the same package that implement either interfaces and also implement separate bite methods and have them composed in OuterClass.
    5. but you wanted to get it done within OuterClass because it was your design decision to encapsulate the bite behaviour within it, maybe because there was a dependency on a private variable within the class.
    6. soon you realise you can implement both the interfaces via private static inner classes and make it appear to the outside world as though it was composed.

    Take a look at this code:

    // no additional classes in the package
    
    public class InterfaceTester{
    
         public static void main(String []args){
    
            // same class returns 2 instances - both compliant to 
            // either interfaces and yet different output
    
            IShark shark = OuterClass.getSharkInstance();
            System.out.println(shark.bite()); // outputs "Die fast bosedk!"
    
            IMosquito mosquito = OuterClass.getMosquitoInstance();
            System.out.println(mosquito.bite()); // outputs "Die slow bosedk!"
         }
    
    }
    
    interface IShark{
        public String bite();
    }
    
    interface IMosquito{
        public String bite();
    }
    
    class OuterClass implements IShark{
    
        // dependency of inner class on private variable
        private static String dieSlow = "Die slow bosedk!";
        private static String dieFast = "Die fast bosedk!";
    
        private static OuterClass outerInst;
        private static InnerClass innerInst;
    
        // private constructor to stop regular instantiation
        private OuterClass(){}
    
        // get a shark !
        public static IShark getSharkInstance(){
            return outerInst != null ? outerInst : new OuterClass();
        }
    
        // get a mosquito !
        public static IMosquito getMosquitoInstance(){
            return innerInst != null ? innerInst : new InnerClass();
        }
        // an implementation of bite
        public String bite(){
            return dieFast;
        }
    
        // inner class that implements the second interface
        private static class InnerClass implements IMosquito{
            // different implementation of bite
            public String bite(){
                return dieSlow;
            }
        }
    
    }
    

    These kind of design decision cases are numerous and all of the answers above list several such cases. So it would not be wrong to think that this feature was introduced more as a new pattern than as a feature or functionality.

    0 讨论(0)
提交回复
热议问题