Difference between Inner Class methods VS Instance Methods in Java - java

What is the exact purpose of inner classes in Java and creating methods in it. Can I get the same behavior if I create methods in a class instead of creating those methods inside Inner class?
We can access both Inner class methods as well as instance methods outside of outer class. So what is the exact purpose of Inner classes in Java? Is there any situation/possibility where we can't survive without inner classes?

Using them greatly depends on what you need to do. Sometimes you need a class that will be only used inside of one particular class, sometimes you need to quickly create an instance of Comparator and pass it to sort() method (anonymous inner class). Some inner classes are accessible outside of the class, some aren't. There are four different varieties of nested classes in java, for more I recommend reading this: http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

Inner class does not instantiate upon outer class instantiation unless you explicitly do it in the constructor. Therefore it's methods are not useful to the rest of the class unless they are static or you have created an instance of it and using them.
If you place your methods inside the inner class they can access the inner method, instance variables! You cannot access those variables in the outer class.

you can refer to this
basically inner class keep the object oriented programming more intact.
Also sometime when you have to implement an interface which has only one unimplemented method inner class comes handy. specially anonymous inner class.
also instead of writing complicated if-else structure or switch case we can use this inner classes for callbacks

Related

Why are interfaces static?

Why can I not have a interface inside of a inner class? Why are they inherently static? Sorry if it's a stupid question, I've tried my best to google this again and again but I can't seem to wrap it around my head. As in why cannot I declare these in inner classes/local classes?
Also just as a confirmation, the reason we can have static final variables in a interface is because they do not specify the state or any of that sort of the implementation right? If we lose static and use just a final, we need a instance which makes no sense cause you can't instantiate a interface. Sorry, I really am confused, and I know I should just make another question but I think these two questions are somewhat related.
Think about what static means - "not related to a particular instance". So, as you point out, a static field of class Foo is a field that does not belong to any Foo instance, but rather belongs to the Foo class itself.
Now think about what an interface is - it's a contract, a list of methods that classes which implement it promise to provide. Another way of thinking about this is that an interface is a set of methods that is "not related to a particular class" - any class can implement it, as long as it provides those methods.
So, if an interface is not related to any particular class, clearly one could not be related to an instance of a class - right?
*Note, as #Owlstead points out, there are ways of defining interfaces within classes. But, for the purposes of wrapping your head around what an interface is (which seems to be what you're working on), I would ignore those possibilities for now as they distract from and possibly obscure the purpose of interfaces in general.
Why are they [interfaces] inherently static?
The difference between a static and a non-static nested class is in whether their instances have implicit references to enclosing instances (of the containing class), as well as to local variables from the containing scope. Before Java 8, there was no way for an interface to make use of such implicit references, because an interface could not initialize any non-static fields or provide any method implementations. (It still can't initialize non-static fields, though now it can provide default method implementations.) So before Java 8, there was no meaning in a non-static nested interface.
Also, from an implementation standpoint, these implicit references are implemented as an extra fields on the inner class, and they also require extra arguments to the inner-class constructor (in order to initialize these fields). Interfaces don't have fields, or constructors, so there's no way to implement this.
(Note: I don't usually recommend trying to understand language design decisions in terms of the implementation, because a single language feature can have many different correct implementations. But I think this is one case where understanding the implementation helps to understand the specification, hence the previous paragraph.)
Why can I not have a interface inside of a inner class?
Because interfaces are implicitly static: JLS §8.5.1:
A member interface is implicitly static (§9.1.1). It is permitted for the declaration of a member interface to redundantly specify the static modifier.
and you can't have non-final statics in an inner class.
Why are they implicitly static?
Because that's the way they designed it.
why cannot I declare these in inner classes/local classes?
Because they're implicitly static.
the reason we can have static final variables in a interface is because they do not specify the state or any of that sort of the implementation right?
Right.
If we lose static and use just a final, we need a instance
Right.
which makes no sense cause you can't instantiate a interface.
Yes you can. You can instantiate a class which implements the interface, or you can instantiate a method-local anonymous implementation of it. The real issue here is multiple inheritance of interfaces.
You cannot have an interface inside of an inner class because an inner class only exists within the context of an instance of an 'outer class'. Since this is the case, your interface would be de facto non-static.
You can, however have an interface inside of a nested class. See #owlstead answer. By placing the 'static' keyword on a the declaration of an 'inner class', it becomes a first class citizen, referencable from outside the outer class and (mostly) independent of the context of the outer class. Nested classes can be instantiated outside of the outer class; inner classes cannot.
After Java 16 release we can have static members inside Inner classes and static variables can be declared if they are final or effectively final. See this image
https://docs.oracle.com/en/java/javase/17/language/java-language-changes.html#GUID-8FD2B5E3-46C7-4C6C-8E8A-64AB49ABF855

Java Inner Class Access and Best Practices

I know that an inner class has access to everything in the outer class (because it's a member of that class) but what about the other way around?
Does the outer class have access to private variables and methods within an inner class?
I've seen articles mentioning that inner classes should be private so that they are accessible only to the outer class. What does that do to the accessibility of that inner class?
What is best practices in dealing with access levels when it comes to your inner classes? I'm assuming more encapsulation the better but does that come at the expense of accessibility?
This topic is covered in some detail by Effective Java (2nd edition) Item 22: "Favor static member classes over nonstatic".
A brief summary:
An inner class should not have access to an outer class instance, unless that access is required, i.e. inner classes should be static by default. To get technical, Effective Java calls these static member classes, as opposed to inner classes, and uses the term nested class to encompass both the static and nonstatic versions.
An outer class always has access to the members of its inner classes, even when those members are private. In this way, an inner class can expose itself only to its outer class.
"An inner class should exist only to serve its outer class."
Personally, I'm inclined to implement an inner class whenever doing so allows the inner class's constructors to be private, i.e. when a class can only be instantiated from one other (outer) class. Any additional encapsulation, such as making the entire inner class private, is desirable; but public inner classes are perfectly acceptable. There are many examples in Java, such as AbstractMap.SimpleEntry.

Why can we access a variable in an inner class from an outer class?

If I declare a variable as private in an inner class, the variable is visible to the outer class. I am unable to understand the logic here. Shouldn't it ideally be only accessible within an inner class?
I think the answer is subjective as the question basically seems to be asking why Sun/Oracle's language designers decided to allow a certain behavior.
That said, here is an attempt at an answer...
First some terminology, a class declared within a class is a nested class. An inner class is a non-static nested class which must reside within an instance of the outer class. So the inner class is a part of the outer class and in that sense, all members of the inner class are to an extent members of the outer class.
http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.
Another thought is that the valid use cases for an inner class preclude the necessity to allow the inner class to hide members from the outer class. That is, there is no notion that the outer class would not be coupled to the inner class.
Why allow private at all then? Because private members can still be hidden from other classes which may gain access to an instance of an inner class.

How do I garbage collect objects which have created instances of their inner classes?

The Java garbage collector is failing to collect dead objects in a program I wrote, and I believe this is because the dead objects have created instances of their inner classes.
When I look at the instances of the inner class in Debug mode, after the creator should have been collected, I find a reference titled this$0, which points to the should-be-dead object.
Is there a way to prevent an Outer.this reference from being created by java in each instance of Inner? This field has no use in the program, and all it does is prevent garbage collection, quickly causing the heap to run out of memory. Moving Inner out of Outer is not an option because it has public data fields that should only be visible to Outer.
Your inner class maintains this$0 so it can get at the private fields and methods of the outer class. If your inner class does not need to use anything in the outer class, you can mark the inner class static to prevent it from maintaining a reference to an instance of the containing class.
Regardless, though, I need my inner class to be non-static, because each instance of it needs to invoke non-static methods that use it's non-static instance data.
In that case, the outer objects shouldn't be garbage collected ... because the outer objects are where that instance data resides!
FOLLOWUP
What would you recommend then? I have no idea how use packages, but I need to create instances of Inner which have public data fields accessible only to Outer, and can survive past the destruction of Outer. Am I out of luck?
Before I answer your question:
"I have no idea how use packages ..." - you ought to learn about them then. Packages and "package private" access are an important part of the Java language.
Now to your question ...
If you want fields only to be accessible to the Outer class (and classes nested within) then you have to use nested or inner classes. (If you try to do this using a package and package-private access, then other classes declared in the same package can also access the fields. However, if that's acceptable, then packages are a simpler way to do this.)
Assuming that you are going to do this using nested or inner classes, then there are two ways to do this:
If you declare the Inner class as private static class Inner, then methods in the Inner class CANNOT call instance methods or access instance fields of Outer ... unless they have a reference to and Outer instance (e.g. passed as a parameter). If Inner is static, the lifetime of instances of Inner and Outer are independent.
If you declare the Inner class as private class Inner, then methods in the Inner class CAN call instance methods or access instance fields of Outer. But the flip side is that the lifetime of an Outer instance and its Inner instances are now dependent. Specifically, an Outer instance will exist as long as at least one of its Inner instances continues to exist. (The reverse is not true ... unless the Outer instance is holding references for Inner instances in (say) a collection-typed field.)
Just to restate what I said previously. If an Inner instance needs to access instance fields or call instance methods on an Outer instance, then it needs an explicit or reference to that Outer instance. That means that the Outer instance is reachable, and is not a candidate for deletion by the garbage collector.
The other point is an instance of Inner won't go away if it is still reachable; i.e. if some part of your running application has a reference to the instance that it could possibly use. In Java, objects DON'T get garbage collected if there is any possibility that they could be used by the running application. Instances of inner/nested classes are not special in this regard.
Actually, there may be a (really nasty!) way to do it break the linkage between the Inner and Outer instances. If you can find all of the Inner instances, you can use reflection to assign null to the this$0 hidden variable in each one. However, if you do that, any code in the Inner class that refers to the Outer instance state will break. If you are going to resort to this kind of nastiness, you are better off declaring Inner as a static class.
About all you can do is make the inner classes static, or not use inner classes at all.
You can, of course, make use of package scoping to limit visibility of fields in the classes without having to resort to inner classes.

Java: Why internal class has to be static?

I know that internal class has to be static because will link between public and internal classes and internal class will be created all times that created public classes.
And my question how to check it?
I mean write some simple application and make some loop for creating objects and see that objects do not deleted by GC in some profiler, Can I to do something like that nad some one done it?
Thanks.
internal class will be created all times that created public classes
If you mean that an instance of the inner class will always be created when you create an instance of the outer class, that is not true.
You can have outer instances with no attached inner instances, and the same outer instance can have any number of attached inner instances (and of different inner classes, too).
It is (somewhat) the opposite rather: When you create an instance of the (non-static) inner class, that instance will contain a reference to its outer instance (but that is a reference to an already existing object, not a new one: You cannot create the inner instance without having the outer one first).
This can be done using static analysis. If you are using Eclipse check out the FindBugs plugin, it can detect the lack of static inner classes and a bunch of other useful problems.
An internal class does not have to be static. In fact, one of their most common manifestations - anonymous inner classes - are never static.
The phrase "static class" does not cause a class to get created at runtime - classes are only "created" once, by the classloader, when they are loaded. What you meant to say is that the instance of the internal class will be created every time an instance of the outer class is created. And this too is false in general (see Thilo's answer).
Don't worry - I misunderstood internal classes in exactly the same way as you when I first learned about them!
A non-static inner class will have an implicit (i.e. it's there automatically, you don't declare it) reference to the instance of the outer class which created it. This will prevent the instance of the outer class being GCed as long as the instance of the inner class exists, just like a normal Java reference.
A static internal class will not have such a reference, because it is not created by an outer instance but by the classloader.

Categories