Java: Inner class inside an inner class - java

Please excuse me if this question has been asked before.
I have searched around the web and here at stack overflow.
Case:
I am stuck at my java project and the compiler won't compile my project when I try to use
an inner class inside another.
Code:
public class outer {
public class middle {
public class inner {
public int variable = "8";
}
}
}
Declaration:
I am trying to declare the classes like this:
outer outerObject = new outer();
outerObject.middle middleObject = outerObject.new middle();
outerObject.middleObject.inner innerObject = outerObject.middleObject.new inner();
Compilation results:
source\start.java:8: error: cannot find symbol
outerObject.middleObject.inner innerObject = outerObject
.middleObject.new inner();
^
Any reply would be much appreciated! Wether my intentions are impossible or if I am simply doing something wrong.
Have a nice day!

The line
outerObject.middleObject.inner innerObject = outerObject.middleObject.new inner();
should be
outer.middle.inner innerObject = middleObject.new inner();
outerObject does not have a middleObject field. Unfortunately Java allows statics to be qualified with variable expressions, so you get some strange code actually compiling.
This would probably be clearer if you stuck with the Java naming conventions.

Your code will never compile as:
public int variable = "8";
This line should be
public int variable = 8;
First change this line.

use this
public class outer {
public class middle {
public class inner {
public int variable = 8;
}
}
public static void main(String[] a) {
outer outerObject = new outer();
middle middleObject = outerObject.new middle();
middle.inner innerObject = middleObject.new inner();
}
}

Please try this :
Outer outerObject = new Outer();
Outer.middle middleObject = outerObject.new middle();
Outer.middle.inner innerObject = middleObject.new inner();
Also you need to change:
public int variable = "8";
to
public String variable = "8";

Related

How instantiating an inner class in Java really works?

I'm making an instance from an inner class, but I can't understand what does this syntax mean.
OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
I know that I can't get an object from an inner class without getting an object from the outer one OuterClass outerObject = new OuterClass();, then we use the object from the outer class outerObject to get an instance from the inner class outerObject.new InnerClass();, so what does OuterClass.InnerClass actually means as it is not explained in the Java documentation as it states:
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();
If I recall correctly, the syntactic meaning is as follows:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
InnerClass The class InnerClass
. which is an inner class of
OuterClass OuterClass
innerObject has an instance named innerObject
= which is assigned the value
new InnerClass() of a new InnerClass instance
. such that when you use
OuterClass.this from within
InnerClass methods invoked on
innerObject, it refers to
outerObject outerObject.
The key here is that inner classes are created through a reference to the outer class. If your InnerClass is static (one InnerClass for the entire OuterClass class), you'll see that the reference to the outer class is static:
static class InnerClass { ... }
...
//Initialization will become:
OuterClass.InnerClass innerObject = new OuterClass.InnerClass();
^ this part is a static OuterClass reference
On the other hand, in your current scenario (InnerClass is not static), the inner class must be created with a reference to the OuterClass in the form of an object - outerObject. Furthermore, you are actually able to access outerObject from within InnerClass by referring to OuterClass.this:
OuterClass.java
public class OuterClass
{
class InnerClass
{
public OuterClass getOuterClassReference()
{
return OuterClass.this;
}
}
}
Main.java
class Main
{
public static void main(String[] args)
{
OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
System.out.println(outerObject);
System.out.println(innerObject.getOuterClassReference());
System.out.println(outerObject == innerObject.getOuterClassReference());
}
}
Output:
OuterClass#36baf30c
OuterClass#36baf30c
true
Here, 36baf30c in the output is an arbitrary memory address. These two output lines will always be the same. As you can clearly see, referring to OuterClass.this from within an InnerClass instance will return the OuterClass instance that was provided at initialization. This is part of the reason that you can't just call new InnerClass() - the reference OuterClass.this cannot be initialized properly without being provided with an instance.
This is the name of the class, and it's likely named this way to make it easier for the compiler to find the definition.
If you declare your variable as just being of type InnerClass, it will look for the file InnerClass.java, but there is no such file.
The dot notation indicates that it's actually a member of OuterClass, so it will look for the definition within the file OuterClass.java.
This is the same thing as using a class from a library,
com.example.MyLibrary.ExternalClass myExternalObject;
JVM does not make a difference between OuterClass and InnerClass: both classes are POJO and separate classes. But InnerClass is not static and therefore it has internal this refers to the instance of OuterClass (therefore it should be created only with existed OuterClass instance)
public class OuterClass {
public class InnerClass {
public OuterClass getOuterClassReference() {
return OuterClass.this;
}
}
}
OuterClass outerObject = new OuterClass();
OuterClass.InnterClass innerObject = outerObject.new InnerClass(); // innerObject has this reference to outerObject
public class OuterClass {
public static class InnerClass {}
}
OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = new OuterClass.InnerClass(); // innerObject does not have this reference to outerObject
In other words, you can emulate InnterClass by yourself like this:
public class OuterClass {
}
public class InnerClass {
private final OuterClass outer;
public InnerClass(OuterClass outer) {
this.outer = outer;
}
}
Outerclass.Innerclass is just a part of the Innerclass' full path.
The full path would be something like packagename.Outerclass.Innerclass.
Thus,
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
is really no different from something like:
java.util.ArrayList<T> varName = new java.util.ArrayList<T>();
You can define the inner class as static member of OuterClass
public class OuterClass {
public static class StaticInnerClass {
int i = 0;
public String call() {
i++;
return this.getClass().getName() + " i=" + i;
}
}
}
so defining the static inner class the compile knows that members is a class, the memory area is instanced at compile time (it is accessible in static way) and you can apply the new operator and the new operator instances the class in another memory area.
For example in a main class
public class Main {
public static void main(String[] args) {
/**
* https://stackoverflow.com/questions/57581397/how-instantiating-an-inner-class-in-java-really-works
*
* ### New instance of Inner class
*/
OuterClass.StaticInnerClass staticInnerClass = new OuterClass.StaticInnerClass();
System.out.println(staticInnerClass.call());
System.out.println(staticInnerClass.call());
staticInnerClass = new OuterClass.StaticInnerClass();
System.out.println("\n" + staticInnerClass.call());
System.out.println(staticInnerClass.call());
}
}
with output
// new of inner class and i = 0
innerclass.OuterClass$StaticInnerClass i=1
innerclass.OuterClass$StaticInnerClass i=2
// new of inner class and i = 0
innerclass.OuterClass$StaticInnerClass i=1
innerclass.OuterClass$StaticInnerClass i=2
References: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html.

Way to call inner class by outer class

I know that to instantiate a member inner class, you have two different constructors:
First:
Outer out = new Outer();
Outer.Inner in = out.new Inner();
Second:
Outer.Inner in = new Outer().new Inner();
Now, I don't know why this code compiles:
public class Outer {
private String greeting="Hi";
protected class Inner {
public int repeat=3;
public void go() {
for (int i =0; i<repeat; i++) {
System.out.println(greeting);
}
}
}
public void callInner() {
Inner in = new Inner(); //in my opinion the correct constructor is Outer.Inner in = new Inner()
in.go();
}
public static void main(String[] args) {
Outer out = new Outer();
out.callInner();
}
}
Why does it compile?
Thanks a lot!
As you are instantiating Inner within the scope of Outer (inside an instance method), you do not need to explicitly instantiate referencing the Outer clas, like in your example:
Outer.Inner in = new Outer().new Inner();
It is fine to instantiate by just referencing Inner:
Inner in = new Inner();
This applies to all instance methods within a class, as long as they are not static.
First main method will be called
public static void main(String[] args){
Outer out = new Outer();
out.callInner();
}
from here you have create an object of Outer class and called callInner method like below
public void callInner() {
Inner in = new Inner(); //in my opinion the correct constructor is Outer.Inner in = new Inner()
in.go();
}
and now you have created an object of Inner and called go method.
protected class Inner {
public int repeat=3;
public void go() {
for (int i =0; i<repeat; i++) {
System.out.println(greeting);
}
}
}
so it's a simple call all are in a same scope. so need for outer.Inner concept to call.
It's important to understand that Outer and Inner are related. More specifically, you need an Outer instance in order to create an Inner instance.
As your explanation shows, you need an instance of Outer to create an instance of Inner. Since the method callInner is an instance method of Outer (it is not declared static) there is already an instance of Outer present: this
The code could also be written like that:
public void callInner() {
Outer out = this;
Inner in = out.new Inner();
in.go();
}
Now the code looks similar to your first example.
But let's keep the code as shown:
public void callInner() {
Inner in = new Inner();
in.go();
}
Now if we look under the hood it's basically the same:
public void callInner();
Code:
0: new #21 // class playground/Outer$Inner
3: dup
4: aload_0
5: invokespecial #23 // Method playground/Outer$Inner."<init>":(Lplayground/Outer;)V
8: astore_1
9: aload_1
10: invokevirtual #26 // Method playground/Outer$Inner.go:()V
13: return
On line 4 we get aload_0 which loads in instance methods this.
Compare: Java Tutorials - Inner Class Example
When you call the callInner method, you are actually within the scope of Outer class. And the reason, why the compiler accepts calling new Inner() is exactly the same, why you don't have to write explicitly what class your some imagined static variable comes from (when it's the part of the same class you call it). See example below:
public class Outer {
private static int x = 1;
private void innerCall() {
x++;
}
}
In above case, you do exactly the same as in your example with exception, that you use the class and not the variable (which is not really relevant in here). Your syntax would be necessary if wanted to access the class/variable from the outside of the class (scope). It would then look like the thing below:
public class Outer {
public static int x = 1;
}
Outer.x++;
Above, you have to explicitly specify what scope you want to access your variable x from. It's just like you wanted to access the file from within the given directory. If you're in this directory, you just access the file by it's name. However, when you are outside of it, you have to write also the directory's name to see the file you want to get.

I've got trouble with inner and static inner class at java

Firstly, Thanks everybody that read that topic.
How can if statement become true in test class? I couldnt find any solution.I couldnt write any code in these method.I tried to send from Room class numberOfTiger to class Question's method but I didnt achieve that.
That's question about ,How can I change int variable(numberofTiger) to Cat.Tiger variable.After that if statement become true to invoke (getNumberOfTiger) method.
public class Test {
public static void main(String[] args) {
Animal an = new Animal();
Animal.Cat an1 = an.new Cat();
Animal.Cat.Tiger an2 = an1.new Tiger(3, 900, 2);
if (Animal.Question.getnumberOfTiger(an2) == 3) {
System.out.println("True");
}
}
}
public class Animal {
Cat[] c;
// inner class
class Cat {
Tiger[] t;
// inner class
class Tiger {
private int numberOfTiger;
private int averageOfTigerWeigth;
private int youngTiger;
public Tiger(int numberOfTiger, int averageOfTigerWeigth, int youngTiger) {
super();
this.numberOfTiger = numberOfTiger;
this.averageOfTigerWeigth = averageOfTigerWeigth;
this.youngTiger = youngTiger;
}
static class Question {
static int getnumberOfTiger(Cat.Tiger a) {
return 0;
}
}
}
In addition to either making Cat a static class, or using its instance,
you also need a getter for a.numberOfTiger since it is private, in Tiger class:
public getNumberOfTiger() {
return numberOfTiger;
}
Then:
return a.getNumberOfTiger();
In getNumberOfTiger() you need to return the number of tigers associated with that object. You are currently just returning 0, so it will always evaluate to false.
I see the issue. The Tiger class and the Cat class needs to be static. The reason is, a non-static inner class can call on its outer class (e.g. Cat.this.something). A non-static inner type is called like this:
instanceOfOuterClass.innerClass
whereas a static inner type is called like this:
outerClassName.innerClass
The simplest way to call on a non-static inner type is new Outer().new Inner(); The main issue with beginners in Java is that they try to do this:
new (new Outer()).Inner()
But the actual way to call it is
new Outer().new Inner()
Also, your method is always returning 0 for the count of tigers.

Call inner class member from a different class

Please forgive me if this question is silly as i'm completely new to JAVA program. I'm looking into nested classes concept and come across the following program.
// Demonstrate an inner class.
class Outer {
int outer_x = 100;
void test() {
Inner inner = new Inner();
inner.display();
}
// this is an inner class
class Inner {
void display() {
System.out.println("Display: outer_x = " + outer_x);
}
}
}
class NestedClass {
public static void main(String args[]) {
Outer outer = new Outer();
outer.test();
// Inner inner = new Outer().Inner();
// inner.display();
}
}
And my doubt is how to access members of Inner class from NestedClass. In "Java - The complete reference", it is given that "You can, however, create an instance of Inner outside of
Outer by qualifying its name with Outer, as in Outer.Inner". But if i try to use it as,
Inner inner = new Outer().Inner();
inner.display();
it is throwing error. So please help me experts.
You need to create a new Inner instance by using the new keyword.
Inner inner = new Outer().new Inner(); // "new" keyword is required to create a new Inner instance.
If you do not have the import for import com.java.test.Outer.Inner; added, add it. Or else, you can do something like this
Outer.Inner inner = new Outer().new Inner();
Outer st = new Outer();
Outer.Inner fl = st.new Inner();
Note that the code above would be exactly the same whether the main() method is inside the outer class (because main is a static method) or even in some other class. Some other class could only run the code if it has access to outer class . But, Outer Class will have default, or package access since access modifiers are not specified when Outer Class is declared. This essentially means that any class within the same package as OuterClass will be able to run the code above without any issues.
You first have to create an instance of the outer class. After that, you can create an instance of that nested inner class by the outer class' instance.
Outer outer = new Outer();
Outer.Inner a = outer. new Inner();
a.display();
Inner class can be accessed only through live instance of outer class.
Try this:
class NestedClass {
public static void main(String args[]) {
Outer outer = new Outer();
outer.test();
Outer.Inner inner = outer.new Inner();
inner.display();
}
}
Use this:
Outer.Inner inner=new Outer().new Inner();
as you need to create object of Inner class too as it is not static inner class.
So your code becomes:
class NestedClass {
public static void main(String args[]) {
Outer outer = new Outer();
outer.test();
Outer.Inner inner = outer.new Inner();
inner.display();
}
}

Android & Java inner class concept

i followed the link http://developer.android.com/reference/android/app/AlertDialog.html and i try to create new AlertDialog like this
AlertDialog myAlertDialog = new AlertDialog.Builder(MainActivity.this).create();
as per the document AlerDialog is the outerclass and Builder is the inner class within AlertDialog. Now i linked the same concept with java in accessing the inner class like this Outer myOuter2 = new Outer.Inner(); this piece of gives error when i try to access, here is the complete java code
package com.test;
public class Outer {
public void OuterMethod() {
System.out.println("OuterMethod");
}
public static void main(String[] args) {
Outer myOuter = new Outer();
myOuter.OuterMethod();
Outer myOuter2 = new Outer.Inner();//this piece of code gives error
}
class Inner {
Inner() {
System.out.println("constructor Inner");
}
public void InnerMethod() {
System.out.println("Inside InnerMethod");
}
}
}
so my question over here is how to understand the same inner class concept in android and accessing the methods within that
You have created an inner non-static class (an inner instance class), whereas AlertDialog.Builder is a static class.
To get your code to work as is you need an interesting way of invoking new that goes like this:
Outer.Inner myOuter2 = myOuter.new Inner();
This is because it acts much like any other non-static field within Outer - it requires an instance of Outer in order to be valid. In any event, this is often not a good idea as public inner non-static classes are rare.
More likely you want Inner to be a static class, i.e. one declared as:
static class Inner {
Essentially this decouples Inner from its containing class, it just happens to live inside it and so can be instantiated via new Outer.Inner(). It could happily live as a public class in its own right in a new .java file instead.
Inner static classes are useful when the inner class is only used in relation the outer class, so it shows the relationship between them.
In Android's case you use an AlertDialog.Builder only when building an AlertDialog. If it was a general Builder used by other classes (e.g. a plain Dialog) is would have instead been declared as its own public class (i.e. a standalone class that is not nested inside another).
There is no relationship between Outer and Inner except that they share a class file. Hence, you cannot type:
Outer myOuter2 = new Outer.Inner();
Perhaps you meant:
Outer.Inner myInner = new Outer.Inner();
The Inner class will need to be declared as static for this to work.
Note that a normal builder will return a type that is equal to the enclosing type. Here's a small example using similar class names to your code:
public class Outer {
public static void main(String[] args) {
Outer outer = new Outer.Builder().withParam("foo").build();
}
private final String someParam;
private Outer(String someParam) {
this.someParam = someParam;
}
public static class Builder {
private String someParam;
public Builder() {
}
public Builder withParam(String value) {
this.someParam = value;
return this;
}
public Outer build() {
return new Outer(someParam);
}
}
}
You may also wish to read Item #2 of Joshua Bloch's Effective Java, 2nd Edition for a good description of builder design and rationale. Available online: here.
Your inner class is non static type.
We should first create instance of your outer class:
Outer o=new Outer();
Outer.Inner oi=o.new Inner();
This is the basic way of create non static inner class object.
Suppose if your inner is of type static (i.e. static class Inner{....}),
then for creating object:
Outer.Inner oi=new Outer.inner();
The AlertDialog.Builder class is a static inner class as you can see here.
public static class Builder {...}
Finally i figured out here is the code
package com.test;
public class Outer {
public void OuterMethod() {
System.out.println("OuterMethod");
}
public static void main(String[] args) {
Outer myOuter = new Outer();
myOuter.OuterMethod();
Outer myOuter2 = new Outer.Inner().InnerMethod();
}
static class Inner {
Inner() {
System.out.println("constructor Inner");
}
public Outer InnerMethod() {
Outer myOuter = new Outer();
System.out.println("Inside InnerMethod");
return myOuter;
}
}
}

Categories