Understanding inner class in Java - java

Consider the following class:
package test;
public class Container {
public class Contained {
public void foo() {
System.out.println("printed");
}
}
}
and the Main.java:
package test;
public class Main {
public static void main(String[] args){
Container c = new Container();
}
}
So, we right here have created the instance of the Container class. Does it mean that we've also created the instance of the inner class? I thought, yes it does, because the inner class is a non-static nested class. But how can we get access to the instance of the inner class? Can we ever create the instance outside of the Container class?
It would be very useful if you provided some references to the JLS.

To instantiate an inner class, you must first instantiate the outer class. Then, create the inner object within the outer object with this syntax:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
So in your case it will be
Container container = new Container();
Container.Contained containedClass = container.new Contained();
This is called Inner Class. In inner class you can access the container class members
To create an object for the static nested class, use this syntax:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
This is called Static Nested Class. In Static Nested Class you can not access the container class instance members but only static members

Creating an instance of Container doesn't create an instance of the Contained class, since there can many many instances of Contained associated with the same instance of Container. You create instances of Contained explicitly.
Yes, you can create an instance outside Container class by specifying the instance of Container that would be associated with it :
Container cr = new Container();
Container.Contained cd = cr.new Contained ();
Inner classes are described in JLS 8.1.3.

Related

Java object instantiation from nested class - What's wrong with this:

I would love to understand why the following instantiation will not compile:
Superclass.Subclass myObject = new Superclass.Subclass();
The error message reads:
No enclosing instance of type Superclass is accessible. Must qualify the allocation with an enclosing instance of type Superclass (e.g. x.new A() where x is an instance of Superclass).
What is meant by enclosing instance? Why is this necessary?
It seems this message is stating that the syntax must be:
Superclass mySuperObj = new Superclass();
Superclass.Subclass mySubObj = mySuperObj.new Subclass();
BUT it fails to explain what is wrong with my method or why this alternative syntax must be used.
The new [enclosing class].[enclosed class](...) idiom is used to initialize static nested classes, that is nested classes that are declared as a static member of their enclosing class.
The [enclosing class instance].new [enclosed class](...) idiom is used to initialize inner classes, that is, nested classes that are declared as an instance member of their enclosing class.
Examples
With...
class A {
static class B {}
class C {}
}
You will use:
new A.B()
new A().new C(), or with a given instance of A called a,
a.new C()
Note
See documentation
in this case you dont talk from sub class but inner class instead....
so, in this case to create an instance of an inner class you need an instance of the outer class, so you can do:
public class Foo {
public static void main(String[] args) {
Foo myFooObject = new Foo();
Foo.InnerClass myFooInnerClass = myFooObject.new InnerClass();
System.out.println(myFooObject);
System.out.println(myFooInnerClass);
}
class InnerClass {
#Override
public String toString() {
return "Am inner class";
}
}
}
The syntax to create an Inner class object is
InnerClass innerObj = new OuterClass().new InnerClass();
NOT the
Superclass.Subclass myObject = new Superclass.Subclass();
Because :
An instance of InnerClass can exist only within an instance of OuterClass.
To instantiate an inner class, you must first instantiate the outer class. Then, create the inner object within the outer object with this syntax:
InnerClass innerObj = new OuterClass().new InnerClass();
Read Java Docs for more details

How can I fill an Arraylist with inner classes?

This is my main class:
import java.util.ArrayList;
public class MainClass {
public static void main(String[] args){
ArrayList<SecondClass.InnerClass> list=new ArrayList<SecondClass.InnerClass>();
list.add(new SecondClass.InnerClass()); //error here (read below)
}
}
Here is the second class:
public class SecondClass {
public class InnerClass{
}
}
At MainClass, at list.add, I get this error:
No enclosing instance of type SecondClass is accessible. Must qualify
the allocation with an enclosing instance of type SecondClass (e.g.
x.new A() where x is an
instance of SecondClass).
I need to have InnerClass non-static because InnerClass needs to make a static reference to a non-static method. How can I add elements in the ArrayList?
I think you need:
new SecondClass().new InnerClass()
I'd do some reading up on nested classes, and in particular the differences between static and non-static nested classes.
If you choose to make InnerClass a static nested class, note the following:
A static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class. In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.
This means you don't need an instance of SecondClass in order to make an instance of InnerClass - You can instantiate it as you do at the moment.
If however you make InnerClass a non-static nested class (I believe these are sometimes referred to as inner classes, but double check this terminology), you need to create an instance of SecondClass in order to create an instance of InnerClass:
new SecondClass().new InnerClass()
When you want to use an innerClass you must create an instance of the class it contain innerclass. After that you'll use it. Example how to use an innerclass following the tutorial of Oracle:
SecondClass sc=new SecondClass();
SecondClass.InnerClass in=sc.new InnerClass();
And you can see detail here: http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
Make InnerClass static
public class SecondClass {
public static class InnerClass{
}
}

What's the advantage of making an inner class as static with Java?

I have an inner class in my Java class.
When I run find bugs, it recommends(warns) to make it as static.
What's the point of this warning? What's the advantage of making a inner class as static?
If the nested class does not access any of the variables of the enclosing class, it can be made static. The advantage of this is that you do not need an enclosing instance of the outer class to use the nested class.
An inner class, by default, has an implicit reference to an object of the outer class. If you instantiate an object of this from the code of the outer class, this is all done for you. If you do otherwise you need to provide the object yourself.
A static inner class does not have this.
That means it can be instantiated outside the scope of an outer class object. It also means that if you 'export' an instance of the inner class, it will not prevent the current object to be collected.
As a basic rule, if the inner class has no reason to access the outer one, you should make it static by default.
A static inner class is a semantically simpler thing. It's just like a top-level class except you have more options for visibility (e.g. you can make it private).
An important reason to avoid non-static inner classes is that they are more complex. There is the hidden reference to the outer class (maybe even more than one). And a simple name in a method of the inner class may now be one of three things: a local, a field, or a field of an outer class.
An artifact of that complexity is that the hidden reference to the outer class can lead to memory leaks. Say the inner class is a listener and could be a static inner class. As long as the listener is registered, it holds a reference to the instance of the outer class, which may in turn hold on to large amounts of memory. Making the listener static may allow the outer instance to be garbage collected.
A Non-static inner class has an implicit reference to outer class. If you make the class as static, you could save some memory and code.
Benefits of static inner classes:
Instantiation of static inner class does not rely on external class guidance, and the memory overhead of instantiation.
Static inner class does not hold external class guidance, does not affect the collection of external class, to avoid the extension of the external class in memory survival time leading to memory leakage.
We already have good answers, here are my 5 cents:
Both static and non-static inner classes are used when we need to separate logical functionalities yet using the methods and variables of the outer class. Both of the inner classes have access to the private variables of the outer class.
Advantages of static inner class:
1) static classes can access the static variables from outer class
2) static classes can be treated like an independent class
Non-static inner class:
1) cannot use static members of the outer class
2) cannot be treated like an independent class
public class NestedClassDemo {
private int a = 100;
int b = 200;
private static int c = 500;
public NestedClassDemo() {
TestInnerStatic teststat = new TestInnerStatic();
System.out.println("const of NestedClassDemo, a is:"+a+", b is:"+b+".."+teststat.teststat_a);
}
public String getTask1(){
return new TestInnerClass().getTask1();
}
public String getTask2(){
return getTask1();
}
class TestInnerClass{
int test_a = 10;
TestInnerClass() {
System.out.println("const of testinner private member of outerlcass"+a+"..."+c);
}
String getTask1(){
return "task1 from inner:"+test_a+","+a;
}
}
static class TestInnerStatic{
int teststat_a = 20;
public TestInnerStatic() {
System.out.println("const of testinnerstat:"+teststat_a+" member of outer:"+c);
}
String getTask1stat(){
return "task1 from inner stat:"+teststat_a+","+c;
}
}
public static void main(String[] args){
TestInnerStatic teststat = new TestInnerStatic();
System.out.println(teststat.teststat_a);
NestedClassDemo nestdemo = new NestedClassDemo();
System.out.println(nestdemo.getTask1()+"...."+nestdemo.getTask2());
}
}
Accessing the static inner and non-static inner class from outside:
public class TestClass {
public static void main(String[] args){
NestedClassDemo.TestInnerClass a = new NestedClassDemo().new TestInnerClass();
NestedClassDemo.TestInnerStatic b = new NestedClassDemo.TestInnerStatic();
}
}
The official java doc for static inner class can be found at https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

Concept Behind Static classes in Java

Consider the following code
class A {
static class B{
int a = 0;
}
public static void main(String argc[]) {
B var1 = new B();
B var2 = new B();
var1.a = 5;
var2.a = 6;
System.out.println(var1.a+" and "+var2.a);
}
}
It outputs 5 and 6.
Static members are loaded only once.But the output contradicts with that statement.So surely the concept of static classes is different from static data members.So what does static mean in case of static classes
A copy paste from oracle:
Static Nested Classes
As with class methods and variables, a static nested class is associated with its outer class. And like static class methods, a static nested class cannot refer directly to instance variables or methods defined in its enclosing class — it can use them only through an object reference.
Note: A static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class. In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.
Static nested classes are accessed using the enclosing class name:
OuterClass.StaticNestedClass
For example, to create an object for the static nested class, use this syntax:
OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
An example:
There is no need for LinkedList.Entry or Map.Entry to be top-level class as it is only used by LinkedList aka Map. And since they do not need access to the outer class members, it makes sense for it to be static - it's a much cleaner approach.
Static, in case of classes, means that they are not related to an instance of their outer class:
class A{
class B{
...
}
}
...
new A.B(); //error
is invalid. Because B is not static, it holds an implicit reference to an instance of A. This means you cannot create an instance of B without an instance of A.
class A{
static class B{
...
}
}
...
new A.B();
is perfectly valid. Since B is static, it doesn't hold a reference to A, and can be created without an instance of A existing.
Static class is a class that doesn't hold an implicit reference to its enclosing class. Static class behaves just like an ordinary class except its namespace being within another class.
Non-static inner class holds an implicit reference to its enclosing class. The enclosing class' variables are directly accessible to an instance of the inner class. A single instance of the outer class can have multiple instances of its inner class(es).
You've misunderstood the concept. B is a static class with an int a attribute. In your code, you're creating two instances of the B class and each instance has its own a attribute with its value 5 and 6 respectively. Don't confuse the static class with the static attribute/method of a class.
The behavior you're trying to get can be done if you add the static modifier to the a attribute on the B class. Otherwise, your code it's like this:
class B{
int a = 0;
}
class A {
public static void main(String argc[]) {
B var1 = new B();
B var2 = new B();
var1.a = 5;
var2.a = 6;
System.out.println(var1.a+" and "+var2.a);
}
}

Why instantiation of static nested class object is allowed?

I have started learning Java language for Android Application developement.
As per my understanding based on static class, we cannot instantiate object of static class.
But why instantiation of static nested class object is allowed in following situaltion?
class EnclosingClass
{
//...
class static StaticInnerClass
{
//...
}
}
Why we can create object of inner class if it is marked as static?
EnclosingClass.StaticInnerClass s = new EnclosingClass.StaticInnerClass()
As per my understanding based on static class, we cannot instantiate object of static class.
Your understanding of the meaning of "static class" is incorrect. Basically a "static class" in Java is a nested class which doesn't have an implicit reference to an instance of the containing class. See section 8.5.1 of the JLS for more information, in particular:
The static keyword may modify the declaration of a member type C within the body of a non-inner class or interface T. Its effect is to declare that C is not an inner class. Just as a static method of T has no current instance of T in its body, C also has no current instance of T, nor does it have any lexically enclosing instances.
Perhaps you were thinking of static classes in C#, which are completely different?
Why we can create object of inner class if it is marked as static?
You may need to use a nested class in a static context, for example:
public class Test {
public static void main(String args[]) {
InnerClass innerClass = new InnerClass();
}
class InnerClass {
}
}
In this case, when you try to instantiate the innerClass you get the error:
No enclosing instance of type Test is accessible. Must qualify the
allocation with an enclosing instance of type Test (e.g. x.new A()
where x is an instance of Test).
To avoid this, you could instantiate an object of type Test and create an instance of innerClass from it:
Test test = new Test();
InnerClass innerClass = test.new InnerClass();
or better, declare also the innerClass as static and instantiate it in a static context:
public class Test {
public static void main(String args[]) {
InnerClass innerClass = new InnerClass();
}
static class InnerClass {
}
}
check it, maybe it can help you
Nested Classes

Categories

Resources