The Java tutorials that I read, like to use nested classes to demonstrate a concept, a feature or use.
This led me to initially implement a sample project I created just like that: Lots of nested classes in the main activity class.
It works, but now I got a monstrous monolithic .java file. I find it somewhat inconvenient and I now intend to break to multiple .java files/classes.
It occurred to me, however, that sometimes there may be reasons not to take classes out of their enclosing class.
If so, what are good reasons to keep a module large, considering modularity and ease of maintenance?
Are there cases in which it is impractical (or even impossible) to convert a nested class to a toplevel class? In other words, is there a case in which only a nested class could satisfy certain functionality?
It can be easier to read all the classes if they are in the same file. This is why this approach is good for example code.
However for real code, you should break your files/classes into manageable sizes. The longest class file in Java 6 is about 9000 lines long. I tend to keep classes shorter than this. ;)
a non-static nested class has an implicit reference to the creator instance of the enclosing class, and also it can access every member of the enclosing class (even private members). You lose this if you make the nested class top-level:
public class Outer {
private String s;
public void setS(String s) {
this.s = s;
}
public class Inner {
public String getOuterS() {
// This is legal only if Inner is
// non-static and nested in Outer
return s;
}
}
}
public class Main {
public static void main(String[] args) {
Outer o = new Outer();
o.setS("Hello world!!!");
// i now has access to every o member
Outer.Inner i = o.new Inner();
// Prints "Hello world!!!"
System.out.println(i.getOuterS());
}
}
Yes. Inner classes (non-static nested classes) may refer to instance variables of the containing class.
Also, nested classes may access private members of the containing class.
In addition to the benefit of closure (already pointed out in an other answer), nested classes also help you achieve multiple implementation inheritance (ref: Thinking in Java, page 369 - section "Why inner classes"?). As far I know, there is no other way to achieve it. So, if your nested class is helping you achieve multiple implementation inheritance, then it would not be possible for you to make the nested a top-level class.
Nested classes allow you to cleanly separate some functionality that belongs to the outer class and at the same time keep that functionality close to the outer class. In such cases, nested classes provide the best option from a design perspective and that alone can be the reason for not making it a top-level class (which can lead to class pollution in the main package).
Related
Quite often I see people using inner enums, for example:
public class Person {
enum Gender {
MALE,
FEMALE,
OTHER
}
...
}
I am unsure how it works internally, so I am wondering whether there will be new instances of this enum class each time someone creates a new person, such as new Person()?
Will the inner enum keep costing more memory or will there only be a single one?
Follow up:
Just have a quick test on the accepted answer in code editor(Java 11):
public class Person {
String name;
int Age;
Address address = new Address();//Usual way we see
public class Address {
String city;
String Country;
int number;
}
}
public class test {
public static void main(String[] args) {
var a = new Person.Address();//complains "innerclass.Person' is not an enclosing class, make Address Static"
var p = new Person();
var a1 = p.new Address();//correct syntax to create inner clas object outside its outer class
}
}
TBH, never expect such weird syntax of creating an inner class object. But considering we usually just use it in the outer class like how iterator is used in different data structure, it still makes sense that I feel strange about this.
Finally, inner class object are created based on the actual needs and dependency on the outer class, so there is no efficiency issue
Regarding discussion between #Zabuzard and #user207421, both make a good point. user207421 points out that class is considered inner only when they are non-static. Enum and Record by nature are static: Oracle doc. It is good to learn from the root. But I do appreciate how Zabuzard explains everything in a way we can easily understand from scratch.
Explanation
Nested enums are essentially static nested classes. They do not belong to instances of the outer class.
Regardless of how many persons you create, you will always only have a single enum Gender floating around, thats it.
Same goes for its values, there are only 3 values of this enum - regardless of how many persons you create.
Inner classes
However, even if you have an inner (non-static) class, such as
class A {
class B { ... }
...
}
You will only have a single class B in memory (as you worded it). There is essentially always just a single class.
Now, when you create instances of B, you will have to create them based on a previously created instance of A, since instances of B now belong to instances of A and can only exist within their context.
Therefore, they also share non-static properties of that particular A instance. You will often see that being used for Iterator implementations of data-structures.
Static nested vs decoupled
If you have a static nested class, such as
class A {
static class B { ... }
}
you might ask what the only real difference to actually fully decoupling them, as in
class A { ... }
class B { ... }
would be that the nesting makes clear that they somehow belong to each other, topic-wise. An example would be the Entry class in Map.
Notes on efficiency
You should actually stop bothering about efficiency on those minor things. Instead, think about readability for readers.
Efficiency, in the way you have in mind, is rarely ever a factor. And if, usually only in a very small spot in the whole code base (which is usually identified using a profiler).
So basically, unless you have a really good reason to not, always strive for the most readable and understandable solution.
This question already has answers here:
When to use inner classes in Java for helper classes
(10 answers)
Closed 8 years ago.
So I have a ClassA:
public ClassA {
String key;
List<ClassB> value;
}
And this ClassA is mapped to a database table (with 2 columns having key -> list of values) and the values here get stored as a row in there.
public ClassB {
Integer data1;
...
String dataN;
/* constructors and some getters/setters follow */
}
To clarify, ClassB just contains some data that is being stored in database.
When ClassA is being saved, List<ClassB> is being converted to JSON string and getting saved.
There are 2 ways to define ClassB.
Either have it as a regular class
Define it as a inner class(not sure if static or not) inside classA.
ClassB is currently not being used anywhere else in the project.
What do you think should be the right way and why?
I am bit confused regarding nested classes and I cannot distinguish if they are being misused or not.
Personally, if the class is small (for example just an helper) and is not to be used anywhere else, I would prefer doing an inner class. However, this is mostly a matter of opinion.
I think the best in these case is to make sure everyone in your dev team work the same way so it is easier for everyone to debug.
Note that there is a difference between inner class and nested class. A nested (static) class is an inner class declared static, while a simple inner class is normally not static.
Nested static class can be accessed anywhere using Class.NestedStaticClass.
See Nested class documentation for more details and example.
Here an interesting quote from the link I gave u before :
Serialization of inner classes, including local and anonymous classes,
is strongly discouraged. When the Java compiler compiles certain
constructs, such as inner classes, it creates synthetic constructs;
these are classes, methods, fields, and other constructs that do not
have a corresponding construct in the source code. Synthetic
constructs enable Java compilers to implement new Java language
features without changes to the JVM. However, synthetic constructs can
vary among different Java compiler implementations, which means that
.class files can vary among different implementations as well.
Consequently, you may have compatibility issues if you serialize an
inner class and then deserialize it with a different JRE
implementation. See the section Implicit and Synthetic Parameters in
the section Obtaining Names of Method Parameters for more information
about the synthetic constructs generated when an inner class is
compiled.
You might also consider using Anonymous inner class. An anonymous inner class is a class coded directly in the instanciation. For example
new ParentClassName(constructorArgs) {
members..
}
ClassB is currently not being used anywhere else in the project.
I think the key word here is "currently".
If you imagine a situation in which ClassB might be useful in other places in the project (say, if that project grows in a particular way, or if there are other tables that might map to the same structure in the future), then it should probably be a "normal" class.
If the class is logically tied to ClassA. For example, ClassA represents a train and ClassB train cars, which are always related to trains and never to other vehicles which are not trains, then you should define it as a nested class or inner class of ClassA.
Whether to make it nested or inner depends on the type of connection between an object of class ClassB and one of ClassA. It's not always a clear-cut issue, but remember that static nested classes can exist independently of their parent class. (e.g. you can manufacture a train car before you ever create a train object that it will be part of, and you can move train cars between trains), while inner classes always contain an invisible reference to their parent object, and such an object has to exist before you can create an object of the inner class.
All else being equal, I think I would gamble on a static nested class as an initial solution. If I realize that there are other places that need the same class, it's going to be relatively easy to refactor it.
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 outer/ enclosing class.
My Question:
When should create or define an inner class?
are inner classes considered to be called as "Helper classes" ?
What are the indicators for you to make an inner class and what's their other purpose?
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.
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.
See the Java tutorial for the main reasons.
If by "helper class" you mean something for internal use only, then no, not necessarily. You might want to do something like
class Outer {
private static class Inner implements InterestingInterface {
// whatever
}
public InterestingInterface make_something_interesting() {
return new Inner();
}
}
Here, Inner is not a "helper class" in the sense that the outside world does get to see instances of it, but its implementation is entirely hidden -- the outside world only knows it gets some object that implements InterestingInterface.
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.
One purpose of inner classes is to attach listeners. For example, suppose you have a JMenuItem. You can make it quit your app as shown in this code:
JMenuItem quitItem = new JMenuItem("Quit");
quitItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
//cleanup code before exiting
System.exit(0);
}
});
You may also want a class to have access to outer class state variables which is entirely subservient to that class. For example, consider writing a simple color calculator. It might have a text area into which you type a hex code. When you hit enter, you want a JPanel to display the color. Here is a crude outline of what you might do.
public class ColorCalc extends JPanel implements Runnable
{
Color displayedColor;
JTextArea colorEnterArea;
public ColorCalc()
{
displayedColor = Color.white
colorEnterArea = new JTextArea();
}
public void run()
{
//build GUI here
}
public static void main(String[] args)
{
ColorCalc cc = new ColorCalc();
javax.swing.SwingUtilities.invokeLater(cc);
}
//subservient inner class with access to outer class state variable.
class ColorPanel extends JPanel
{
public void paintComponent(Graphics g)
{
g.setColor(displayedColor);
g.fillRect(0,0,getWidth(), getHeight());
}
}
}
This is a style question. Anything that can be done with an inner class can also be done as a as series of external classes. Inner classes are especially useful for classes that are lightweight or tightly bound to the enclosing class. For example, a comparator is frequently both these things. It needs intimate knowledge of the implementation of the class, and may only be a few lines long. It may be an ideal candidate as an internal class.
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..
The inner class used for grouping classes logic, for example, if you have class B and this class used only at class A, So it is better to put class B as an inner class at class A, as this will give readability and reusability for your code.
Happy code :)
Adding from my personal notes, for future visitors:
Sources: https://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html
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:
you need to package a group of classes
but also kind of need certain global variables exposed to all these classes at that package level
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.
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.
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:
you need to implement 2 interfaces, IShark and IMosquito, with the same signature, a public bite method, on the OuterClass.
but you want to display 2 different messages since a shark's bite is a tad different from that of a mosquito's.
however you know that's not possible since only one bite method can be implemented
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.
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.
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.
Conceptually inner classes can be used to represent types in the universe that would not exist without that parent type. In other words, with a language that allows inner classes, the types are all 'type definers'. A type can then be considered something that explicitly or implicitly defines new types.
For example, imagine we have a universe where "Food" can be applied to anything. Even itself. Food is a fundamental concept in our universe. We introduce a subclass of Food called Meat. Without that concept, there is no such thing as "Meat Eater". So we can (note 'can') define a nested type "Meat.Eater" (which could implement an IEater interface) and define animals as being a containment structure of lists of different IEaters.
Once we remove Meat from the universe, Meat Eater disappears to.
This same philosophy applies neatly to more abstract and technically useful arrangements such as Mementos in the Memento Design Pattern , a configuration object defined as a nested class, and other type-specific behaviours or structures.
It also increases encapsulation because inner classes can be declared private.
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.
In some of my projects and in some books was said to not use inner class (anonymous or not, static or not) - except in some restricted conditions, like EventListeners or Runnables - is a best practice. They even were 'forbiden' in my first industry project.
Is this really a best practice? Why?
(I have to say that I'm using them a lot...)
-- EDIT ---
I can't pick a right answer in all these responses: there's part of rightness on mostly all of them: I'll still use inner classes, but I'll try to use them less often !
In my view, 90% of inner classes in Java code are either entities that are associated with a single class and were thus "shoved in" as inner classes, or anonymous inner classes that exist because Java does not support Lambdas.
I personally don't like seeing complex inner classes. They add complexity to the source file, they make it bigger, they're ugly to deal with in terms of debugging and profiling, etc. I like separating my project into many packages, in which case I can make most entities top-level classes that are restricted to the package.
That leaves me with necessary inner classes - such as action listeners, fake "functional" programming, etc. These are often anonymous and while I'm not a fan (would have preferred a Lambda in many cases), I live with them but don't like them.
I haven't done any C# in years, but I'm wondering if the prevalence of inner classes or whatever the C# equivalent is dropped when they introduced Lambdas.
Cleanliness. It's easier to comprehend code if it's broken into logical pieces, not all mushed into the same file.
That said, I do not consider the judicious use of inner classes to be inappropriate. Sometimes these inner classes only exist for one purpose, so I would then have no problem with their being in the only file in which they are used. However, this does not happen that much in my experience.
Anonymous classes are good to use when doing event based programming especially in swing.
Yes, forbidding inner classes is a useful practice, in that finding out a place forbids them is a good way to warn me off working there, hence preserving my future sanity. :)
As gicappa points out, anonymous inner classes are the closest Java has to closures, and are extremely appropriate for use in situations where passing behaviour into a method is suitable, if nothing else.
As some others said, many times, when you use an anonymous inner class, it is also used on some other places too...
Thus you may easily duplicate inner class code to many places...
This seems not a problem when you are using very simple inner classes to filter/sort collections, using predicates, comparator or anything like that...
But you must know that when you use 3 times an anonymous innerclass that does exactly the same thing (for exemple removing the "" of a Collection), you are actually creating 3 new classes on the java PermGen.
So if everyone use inner classes everywhere, this may lead to an application having a bigger permgen. According to the application this may be a problem... If you are working on the industry, you may program embedded applications that have a limited memory, that should be optimized...
Note this is also why the double curly brace syntax (anonymous innerclass with non-static initialization block) is sometimes considered as an antipattern:
new ArrayList<String>() {{
add("java");
add("jsp");
add("servlets");
}}
You should ask to people who forbids you to use them...
IMHO it all depends on the context...
Anonymous inner classes has benefits in being able to see the fields and variables around the "new" statement. This can make for some very clean design and is a quite nice (but a bit wordy) approach to "how can we make a simple version of lambda statements".
Named inner classes has the benefit of having a name, hopefully telling, which can be documented in the usual way, but which is tied together to the surrounding class. A very nice example is the Builder pattern, where the inner class is responsible for providing state for the initialization process instead of having numerous constructors. Such builders cannot be reused between classes, so it makes perfect sense to have the Builder tied closely to the parent class.
I suggest being cautious when using it if it needs a method parameter. I just found a memory leak related to that. It involves HttpServlet using GrizzlyContinuation.
In short here is the buggy code:
public void doGet(HttpServletRequest request, final HttpServletResponse response){
createSubscription(..., new SubscriptionListener(){
public void subscriptionCreated(final CallController controller) {
response.setStatus(200);
...
controller.resume();
}
public void subscriptionFailed(){
...
}
public void subscriptionTimeout(){
...
}});
}
So since the listener is kept by the subscription the HttpServletResponse is also kept in case the listener needs it (not obvious). Then the HttpServletResponse instance will be release only if the subscription is deleted. If you use an inner class that gets the response in it constructor it can be set to null once the call was resume releasing memory.
Use them but be careful!
Martin
One item that is not mentioned here is that a (non-static) inner class carries a reference to it's enclosing class. More importantly, the inner class has access to private members of it's enclosing class. It could, potentially, break encapsulation.
Don't use an inner-class if you have an option.
Code without inner classes is more maintainable and readable. When you access private data members of the outer class from inner class, JDK compiler creates package-access member functions in the outer class for the inner class to access the private members. This leaves a security hole. In
general we should avoid using inner classes.
Use inner class only when an inner class is only relevant in the
context of the outer class and/or inner class can be made private so that only outer class can access it. Inner classes are used primarily to implement helper classes like Iterators, Comparators etc which are used in the
context of an outer class.
Certain frameworks, like Wicket, really require anonymous inner classes.
Saying never is silly. Never say never! An example of good use might be a situation where you have some legacy code that was written by someone where many classes operate directly on a Collection field, and for whatever reason, you cannot change those other classes, but need to conditionally mirror operations to another Collection. The easiest thing to do is to add this behavior via an anonymous inner class.
bagOfStuff = new HashSet(){
#Override
public boolean add(Object o) {
boolean returnValue = super.add(o);
if(returnValue && o instanceof Job)
{
Job job = ((Job)o);
if(job.fooBar())
otherBagOfStuff.add(job);
}
return returnValue;
}
}
That said, they can definitely be used like a poor man's closures.
Inner classes are appropriate when trying to emulate multiple inheritance. It is similar to what happens under the hood with C++: when you have multiple inheritance in C++, the object layout in memory is actually a concatenation of several object instances; the compiler then works out how the "this" pointer shall be adjusted when a method is invoked. In Java, there is no multiple inheritance, but an inner class can be used to provide a "view" of a given instance under another type.
Most of the time, it is possible to stick to single inheritance, but occasionally multiple inheritance would be the right tool to use, and this is the time to use an inner class.
This means that inner classes are somehow more complex than usual classes, in the same way that multiple inheritance is more complex than single inheritance: many programmers have some trouble wrapping their mind around that concept. Hence the "best practice": avoid inner classes because it confuses your coworkers. In my view, this is not a good argument, and at my workplace we are quite happy to use inner classes when we deem it appropriate.
(A minor drawback of inner classes is that they add one extra level of indentation in the source code. This is a bit irksome at times, when one wants to keep the code within 79 columns.)
Anonymous inner classes are often used when we need to implement interface with one method, like Runnable, ActionListener and some other.
One more great appliance of anonymous inner classes is when you don't want to make a subclass of some class but you need to override one (or two) of its methods.
Named inner classes can be used when you want achieve tight coherence between two classes. They aren't so useful as anonymous inner classes and I can't be sure that it's a good practice to use them ever.
Java also has nested (or inner static) classes. They can be used when you want to provide some special access and standard public or default access levels aren't enough.
Inner classes are often used to "pass a behavior" as a parameter of a method. This capability is supported in an elegant way by other languages with closures.
Using inner classes produces some not elegant code (IMHO) because of a language limitation but it's useful and widely used to handle events and blocks in general with inner classes.
So I would say that inner classes are very useful.
yes it is good to use them, when you are trying to keep a class cohesive, and the classes should never be instantiated from outside their context of the outer class, make the constructors private and you have really nice cohesive encapsulation. Anyone that says you should NEVER use them doesn't know what they are talking about. For event handlers and other things that anonymous inner classes excel at they are way better than the alternative of cluttering up your package namespace with lots of event handlers that only apply to a specific class.
I tend to avoid non-static inner classes for the reasons given by other posters. However I have a particularly favourite pattern where a non-static inner class works very effectively: Lazy loading stateful classes.
A typical lazy loading stateful class is constructed with an entity ID and then on demand can lazily load additional entity information. Typically to lazily load the additional information we will require dependencies. But dependencies + state == anti pattern!
Non-static inner classes provide a way to avoid this anti-pattern. Hopefully the following simple example illustrates this better than words can:
/*
* Stateless outer class holding dependencies
*/
public class DataAssembler {
private final LoadingService loadingService;
#Inject
DataAssembler(LoadingService loadingService) {
this.loadingService = loadingService;
}
public LazyData assemble(long id) {
return new LazyData(id);
}
/*
* Stateful non-static inner class that has access to the outer
* class' dependencies in order to lazily load data.
*/
public class LazyData {
private final long id;
private LazyData(long id) {
this.id = id;
}
public long id() {
return id;
}
public String expensiveData() {
return loadingService.buildExpensiveDate(id);
}
}
}
Worth noting that there are many other patterns beyond the above example where inner classes are useful; inner classes are like any other Java feature - there are appropriate times where they can be used and inappropriate times!
When use or avoid inner class in Java?
The inner class has the following characters.
Anyway the .class file is separated as OuterClassName$InnerClassName.class
The class name and the class file name of the inner class always contain the outer class name.
The above characters disclose this fact. The outer class name is the mandatory information for the inner class.
We can derive this result from the fact. The inner class is good to be defined when the outer class is mandatory information of the inner class.
The characters of the inner class make developers sometimes annoying to debug. Because it forces the developer to know the outer class name with the inner class.
Suggestion
It can be a design principle to avoid defining the inner class except when the outer class name is the mandatory information of the inner class for the above two reasons.
I have inherited code which contains static nested classes as:
public class Foo {
// Foo fields and functions
// ...
private static class SGroup {
private static Map<Integer, SGroup> idMap = new HashMap<Integer, SGroup>();
public SGroup(int id, String type) {
// ...
}
}
}
From reading SO (e.g. Java inner class and static nested class) I believe that this is equivalent to two separate classes in two separate files:
public class Foo {
// Foo fields and functions
// ...
}
and
public class SGroup {
static Map<Integer, SGroup> idMap = new HashMap<Integer, SGroup>();
public SGroup(int id, String type) {
// ...
}
}
If this is correct is there any advantage to maintaining the static nested class structure or should I refactor?
It depends on what the class is used for. If it's coupled to the outer class, for example, just like Map.Entry, just leave it in. However, if it makes sense to use the class without its enclosing type, you may as well promote it to a top level class.
Jorn statement is correct and it's usually manifests itself as the following rule of thumb:
Nested classes should be made private, Meaning that the hold auxiliary logic for the hosting class and nothing more. If you cant make them private- thet probably should not be nested.
The exception is when you define a nested class to allow easy access to the state of the hosting class, in that case you should consider simply merging both classes to increase cohesion.
It is not improper to say that "static nested classes" are not nested classes at all. It is convenient to discuss static nested classes in the context of inner classes because the way they are declared in code is similar and also because a static nested class still has to be named with the enclosing class as a context.
However, here is an important thing to keep in mind about static nested classes: from the point of view of the compiler and the JVM, static nested classes are top level classes. In fact, the compiler implements them logically at compile time as top level classes (at least it used to; I think it still does).
Why, then, should anyone ever use static nested classes? Why not just write top level classes all the time?
For me, static nested classes provide a convenient mechanism for logically grouping closely related classes in a manner that keeps my project hierarchy nice and tidy. For example, say that I have a database with the following tables: Clients, Encounters, and Services. I -could- model these tables with separate top-level classes and it would work fine, but since these tables are all in the same database and relate to the same data, I find it convenient to model these as:
class DB {
static class Client {
...
}
static class Encounter {
...
}
static class Service {
...
}
}
To use an instance of one of the models:
DB.Encounter enc = new DB.Encounter();
In my view, this makes code more readable since it is immediately clear in the code that the object that is being created derives from one of my database models. It also keeps the class definitions for the models linked under a common heading which I also think helps make projects simpler to understand.
But from the point of view of the JVM (and the compiler, which implements them as top level classes anyway [just as it also gives "anonymous" inner classes names at compile time]), these objects are instantiated from top level classes. Making them does not depend on any instance of any object, nor can objects instantiated from a static nested class access any private members of the enclosing class.
I like static inner classes as they provide loose coupling from the enclosing class (no access to private members of the enclosing class) static inner classes are also easy to promote to top level (because of the loose coupling attribute).
There is a simple rule of the thumb when to promote them:
If another class (other than the enclosing) needs to reference \ use the inner class.