8

I am reading about inner classes in an interface and class. I could not understand about the real use. However I dont want to discuss anything about inner classes inside an interface in this post.

I have used inner classes as a callback till now. I can do the same declaring the class outside somewhere.

Suppose that I have a list of students and I want to sort them by id. I have to implement Comparator interface and provide it as an argument to Collections's sort method.

public class StudentList {

    public static void main(String[] args) {

        List<Student> students = new ArrayList<Student>();

        Student student = new Student();
        student.setId(1);
        student.setName("Krishna");
        students.add(student);

        student = new Student();
        student.setId(2);
        student.setName("Chaitanya");
        students.add(student);

        Collections.sort(students, new StudentList().new MyComparator());
    }

    public class MyComparator implements Comparator<Student> {

        @Override
        public int compare(Student o1, Student o2) {

            if (o1.getId() < o2.getId()) {
                return 1;
            } else if (o1.getId() > o2.getId()) {
                return -1;
            } else {
                return 0;
            }
        }

    }

}

I can do the same like this also

public class StudentList {

    public static void main(String[] args) {

        List<Student> students = new ArrayList<Student>();

        Student student = new Student();
        student.setId(1);
        student.setName("Krishna");
        students.add(student);

        student = new Student();
        student.setId(2);
        student.setName("Chaitanya");
        students.add(student);

        Collections.sort(students, new MyComparator());
    }

}

class MyComparator implements Comparator<Student> {

    @Override
    public int compare(Student o1, Student o2) {

        if (o1.getId() < o2.getId()) {
            return 1;
        } else if (o1.getId() > o2.getId()) {
            return -1;
        } else {
            return 0;
        }
    }

}

I dont think inner class in the above example adds any significant importance unless it is declared as a private class. When I declare it as private, only the enclosing class can use it. It means the class is strongly binded with the enclosing class and I see some advantage of having so.

Can anyone please explain me the true importance/significance of using/writing inner classes in an application.

Krishna Chaitanya
  • 2,533
  • 4
  • 40
  • 74
  • 3
    You use them if you don't have a need to expose it to the outside world. It's a good thing to restrict accessibility whenever possible, that way your classes won't get used when they're not intended to. – Jeroen Vannevel Nov 26 '13 at 04:00
  • They can have access to the instance of the class they are inside of. – NormR Nov 26 '13 at 04:02
  • Also they can provide a nice mechanism for encapsulating certain algorithms (like a lambda). Consider accessing a final field from inside an anonymous inner class. Also Java 8 will actually have [lambdas](http://openjdk.java.net/projects/lambda/). – Elliott Frisch Nov 26 '13 at 04:02
  • @NormR I can have a class declared somewhere outside and still can pass the class instance as a constructor argument. – Krishna Chaitanya Nov 26 '13 at 04:06
  • @JeroenVanneval What about public inner classes? What is the use of having them? Why dont the compiler restrict only to use private inner classes? Why is the design isn't so? – Krishna Chaitanya Nov 26 '13 at 04:07
  • @ElliottFrisch I did not understand properly. Can you please explain about "Consider accessing a final field from inside an anonynous inner class" – Krishna Chaitanya Nov 26 '13 at 04:09
  • 1
    There are many features in Java that are unnecessary, in the sense that what the feature does can also be done by other means. Inner classes make some code simpler and cleaner, and avoid distracting readers with top level classes that have purely local meaning. – Patricia Shanahan Nov 26 '13 at 04:11
  • @KrishnaChaitanya See [here](http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html#accessing) - the second bullet point, reads "An anonymous class cannot access local variables in its enclosing scope that are not declared as final or effectively final.". – Elliott Frisch Nov 26 '13 at 04:12
  • 1
    One idea behind a public inner class could be to expose methods from that inner class to the outside world while still keeping some sort of separation in the actual code. Nested classes are more a means of keeping code organized rather than an actual functional thing. Some observations as to why you would want this can be found here: http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html – Jeroen Vannevel Nov 26 '13 at 04:13
  • @ElliottFrisch Okay now I understood what you said. But I still can write a getter method to return the final variable and I can declare a class somewhere outside and pass the instance of this class to it and call the getter method. Finally I undertood that I can accomplish what I want to do using inner classes or a class written somewhere. But inner classes provide a means to organize the code and adds meaning to the code. If I understood properly. – Krishna Chaitanya Nov 26 '13 at 04:21
  • Try going through principles of Functional Programming. You will have the answer. i will recommend this book "functional Programming for Java Developers" by Dean Wampler. – Prateek Nov 26 '13 at 04:35

8 Answers8

5

You should inner classes if you need something specific to the class your working with. A good example of an inner class can be found here: java.awt.geom.Ellipse2D and the corresponding Ellipse2D.Double and Ellipse2D.Float (Ellipse2D source code). You could place those classes in a package, but they make a lot more sense as nested classes. They directly correspond to Ellipse2D and will have no use elsewhere; also, the fact that they are nested improves readability in code that uses them. On another note, if an inner class is very likely to be useful when more general, it is often better to generalize it and make a regular class.

Also, inner classes can directly access variables in the outer class. That means that an inner class can be used to change the outer class. It is still possible to get an instance of it to be used outside of either class. To illustrate what I am saying:

public class Example {
    public static void main(String[] args) {
        Foo foo = new Foo();
        Foo.Bar bar = foo.getBar(); //note, cannot call new Foo.Bar(); as Bar is dependent on Foo
        for (int i = 0; i < 50; i++){
            System.out.println(bar.get());
        }
    }
}
class Foo {
    int val;
    Bar b;

    public Foo(){
        b = new Bar();
    }
    public Bar getBar(){
        return b;
    }
    public class Bar{
        public Bar(){
            val++;
        }
        public int get(){
            return val++;
        }
    }
}

Another possible use of inner classes is to create something like a wrapper class for an the truly wanted inner class, especially useful for a recursive class. This is used for implementing a LinkedList. At one time, I implemented such a list, not realizing that anything of the sort had been made before. The idea is that you have your LinkedList class, and a Node class within it (where each node only points to the next/previous node and holds a single value). Doing it this way simplifies the code. However, it doesn't make any sense for the Node class to be external to LinkedList, because what type of "node" would it be? Thus it should be an internal class.

Justin
  • 24,288
  • 12
  • 92
  • 142
2

There are two advantages that I see. I haven't used them myself too much so there are just my observations.

  1. If inner class is very small, it might be more easy to define as inner rather than creating a separate file for it. It would help in manageability in big projects which already have too many files.

  2. Second, if inner class can only be used in it's parent class's context, defining it as inner class would give it namespace containing parents class.

    public class FileProcessor {
     public class Output {
       //will be namespaced as FileProcessor.Output, more readable.
     }
    }
    

From answer Inner Class. What is its purpose?

So what does this gain us? Well, the inner class instance has access to the instance members of the containing class instance. These enclosing instance members are referred to inside the inner class via just their simple names, not via this (this in the inner class refers to the inner class instance, not the associated containing class instance)

Also see What are the uses of inner classes in Java? Are nested classes and inner classes the same?

Community
  • 1
  • 1
RandomQuestion
  • 6,778
  • 17
  • 61
  • 97
1

Some classes don't make make much sense on their own - they only make sense in the context of another class. Inner classes are helpful at defining this kind of relationship - they allow the developer to express the relation between highly cohesive classes more explicitly.

see more

As an example consider a Node in a Graph. A Node has a list of peer Nodes which it can reach itself. It makes sense to define a Peer class as an inner class of Node. For example:

public class Node
{
private String name;
private List peers = new ArrayList();

private Node( String name )
{
this.name = name;
}

/**
* Represents a peer node that is reachable from this node
*/
class Peer
{
private Node node;
private int distance;
}
}
Rakesh KR
  • 6,357
  • 5
  • 40
  • 55
  • 1
    This is a rather small answer. You can at least look at the comments and make a nice writeup of the good arguments given there. Free rep for you to grab! – Jeroen Vannevel Nov 26 '13 at 04:07
1

Purpose of Inner class

Inner classes represent a special type of relationship that is it can access all the members (data members and methods) of outer class including private. Nested classes can lead to more readable and maintainable code because it logically group classes in one place only.

0

An example of when inner classes are necessary

Suppose you have a Java GUI (Graphical User Interface) class that acts as a chat client like Gchat or Facebook Chat. Think about what methods would need to be present in a class like that which represents a chat client – you will need a method that will read user input from the chat box, methods to actually send the user input to the server and to whoever the user is chatting with, even a method that detects that you are typing so that Gchat can display the “XZY is typing” text to your friends, etc.

There are two types of methods needed in our example

So, it should be clear that there will need to be two different types of methods that will drive your chat client application: 1. Chat client specific methods like those that will read user input from the chat box and send user input to the server. 2. Event handling methods that will respond to actual events that occur in the chat client window – like hitting the “RETURN” key, detecting consistent typing, etc.

Because it’s clear that there will need to be two different types of methods, then from an Object Oriented Design perspective, it seems like we should have two different classes: one class for the chat client specific methods and one class for the event handling methods. That does follow the normal object oriented design practices – because we are creating classes that specialize in what they do.

The problem with having two separate classes

But, in this particular example, there is a problem with having two separate classes. And that problem is the fact that the event handling code is very much related/tied to the code that belongs to the chat client. This makes sense, as we talked about earlier with our GChat example; as soon as a user in GChat hits “RETURN” or “ENTER” on the keyboard that should trigger an event, which should then grab the text from the chat client window. And, the chat client window would be a particular instance (basically an object) of the chat client class. For example, if you are talking to your friend Bob in GChat, he will have one window in Gmail and you will have one window open in Gmail, and each window is an object of the chat client class. So there will be two separate objects of the chat client class – one for you and one for Bob.

Now, if Bob types something and hits the RETURN key, the event handler code that responds to the RETURN key being pushed will need to be able to communicate with Bob’s chat client class object so that it can grab the text from Bob’s chat client class window, or the text field where that text is actually stored. The key here is thinking in terms of objects – an object of the chat client class is created for each person using GChat, so you will have your own object and Bob will have his own object. This means that the event handling code will need to access an chat client object’s text field – which is a member of the class, and an instance variable. So, it should be clear that the event handling code needs access to the members of a chat client class object in order to be able to effectively help.

Why don’t we just combine the event handling code with the chat client code?

Combining the event handling methods with the chat client specific methods in one big class sounds like a good idea at first, but there is one big problem: If both the event handling code and the chat client code need to inherit some code from different classes then you are in trouble, because Java does not support multiple inheritance – meaning that our one “big class” can not inherit from two different classes.

Inner classes to the rescue

Now, this is why inner classes were created – for situations exactly like the one we described above. An instance of an inner class can access members of an instance of the outer class, because an inner class is just another member of the outer class. And, inner classes can even access the private members of the outer class – yes you did read that correctly!

Read this - When should inner classes be used in Java?

0

Static Inner class reaches private static fields of Outer classes. It means that if I extend Outer.Inner class anywhere,(because Inner is static, I don't have to make object before extend) I cannot reach the private fields of Outer class. This is perfectly good for context security.

Erdal76t
  • 113
  • 1
  • 9
0

1) Nested classes represent a special type of relationship that is it can access all the members (data members and methods) of outer class including private.

2) Nested classes are used to develop more readable and maintainable code because it logically group classes and interfaces in one place only.

3) Code Optimization: It requires less code to write.

0

I will give my explanation from a different point of view. Please first check out the memory model of Java's inner class. Then with some basic skills in programming, you will know why bother using inner class.

See How inner class object resides in memory?

Besides, usually you should instantiate the inner class object in outer class's constructor to "make sense", and sometimes you can provide a getter method to retrieve the inner class instance which resides in outer class instance if you really want to mess with that inner class instance.

Han XIAO
  • 1,148
  • 9
  • 20