Way to call inner class by outer class - java

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.

Related

Nested virtual classes in Java

If we consider the following code, polymorphism should happen as it is allowed in nested classes in java but, when invoking the inner class constructor polymorphism does not apply that is the new Innner1() apply to the declared type of the instance
not on the actual type.
public class Outer {
public class In {
public In() {
System.out.println("I am In");
}
}
public static void main(String[] args) {
Outer obj = new Outer2();
obj.new In();
Outer2 in2 = (Outer2) obj;
in2.new In();
}
}
class Outer2 extends Outer {
public class In extends Outer.In {
public In() {
System.out.println("I am In2");
}
}
}
Can some help me understand this behavior.
Guys i have updated the Code and it is compiling fine and there is no class cast exception
Please check the output below.
I am In
I am In
I am In2
What´s happening here and why is this special output produced:
public static void main(String[] args) {
Outer obj = new Outer2(); // Step 1
obj.new In(); // Step 2
Outer2 in2 = (Outer2) obj; // Step 3
in2.new In(); // Step 4
}
Step 1:
You create an instance of Outer2 and assign it to a variable obj declared as Outer. This will execute the Outer2 and Outer default constructors.
Step 2:
You create an In. The behaviour what would really be created would be better to understand when both inner classes wouldn´t be called In, but as obj is declared as Outer the call obj.new In(), due to the type of obj, will create an Outer > In.
Here you get your first output :
I am In
Step 3:
You once again create an instance of Outer2 and assign it to a variable in2 declared as Outer2!! <-- this is really important here.
This will execute the Outer2 and Outer default constructors.
Step 4:
You create an In again. But now, as in2 is declared as Outer2, the call in2.new In(), due to the type of in2, will create an Outer2 > Innow.
Here you get your second and third output now:
I am In
I am In2
As per your code you are trying to create an object of child class in parent.
public static void main(String[] args) {
Outer obj = new Outer();
obj.new Innner1();
Outer2 obj2 = (Outer2) obj;
obj2.new Innner1();
}
Ideally this is not a valid case, because first the parent class should be created then child, else this it becomes a never ending hierarchy. That the parent will have child object, which again will have a parent relation and thereon. This is the reason when you execute your current code you get a response like
Exception in thread "main" java.lang.ClassCastException: Outer cannot be cast to Outer2
at Outer.main(Outer.java:14)
I am In
Ideally you should have
public class Outer {
public class Innner1 {
public Innner1() {
System.out.println("I am In");
}
}
}
and outer2 as
class Outer2 extends Outer {
public class Innner1 extends Outer.Innner1 {
public Innner1() {
System.out.println("I am In2");
}
}
public static void main(String[] args) {
Outer obj = new Outer();
obj.new Innner1();
Outer2 obj2 = new Outer2();
obj2.new Innner1();
}
}
In this case the result would be
I am In
I am In
I am In2
You see here the constructor of parent's Inner class in invoked before the child class'.

Can an innerclass also be a subclass and also

Can a innerclass also be a subclass. Also one more thing in this set of java planguage it's not allowing me to create a instance of subclass even though I already created a instance of my encapsulating class for the innerclass.
public class Main {
Main OpTypes[] = new Main[3];
public static void main(String[] args) {
Main c = new Main();
c.OpTypes[0] = new Division(6,3);
Jool x = new Jool();
}
public class Jool {
public Jool() {
}
}
}
If you try it, you'll find that an inner class can extend a class.
Also, since the inner class is not static, it requires an instance of the outer class when constructing it. In the code below, you'll see two ways of doing that.
Method test shows the most common way, which is to do it from an instance (non-static) method of the outer class, in which case the outer class is implicit.
Method main shows how to do it outside of an instance method of the outer class, in which case you have to give an outer class instance before the new operator.
class MyBaseClass {
}
class Main {
public static void main(String[] args) {
Main c = new Main();
Jool x = c.new Jool(); // "c" explicitly used as outer class instance
}
public void test() {
Jool x = new Jool(); // "this" implicitly used as outer class instance
}
public class Jool extends MyBaseClass { // Inner class extends unrelated class
}
}

Using a non static data member in to a non static nested class withourt using object

class Outer
{
int x=10;
class Inner
{
void show()
{
System.out.println(x);
}
}
public static void main(String args[])
{
Outer obj=new Outer();
Inner obj1=new Outer().new Inner();
obj1.show();
}
}
I tried making a non static nested class and tried to use non static data member of outer class in non static inner class. I did not get that if x is non static, how i am using it without object. Kindly give me the answer?
You're not using it without an object. Inner (non-static nested) classes have a reference to the outer object, whose x is used.
Inner class is just a syntactic sugar to have an implicit reference to an outer class. Internally (after javac compilation) your class Inner looks like this:
static class Inner
{
private final Outer this$0;
public Inner(Outer outer) {
this$0 = outer;
}
void show()
{
System.out.println(this$0.x);
}
}
And when you write Inner obj1=new Outer().new Inner(); the compiler changes it to something like Inner obj1=new Inner(new Outer());.

Java: How to check if an object is an instance of a non-static inner class, regardless of the outer object?

If I have an inner class e.g.
class Outer{
class Inner{}
}
Is there any way to check if an arbitrary Object is an instance of any Inner, regardless of its outer object? instanceof gives false when the objects are not Inners from the same Outer. I know a workaround is just to make Inner a static class, but I'm wondering if what I'm asking is possible.
Example:
class Outer{
Inner inner = new Inner();
class Inner{}
public boolean isInner(Object o){
return o instanceof Inner;
}
}
Outer outer1 = new Outer();
Outer outer2 = new Outer();
boolean answer = outer1.isInner(outer2.inner); //gives false
And what about?
public static boolean isInnerClass(Class<?> clazz) {
return clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers());
}
The method isMemberClass() will test if the method is a member (and not an anonymous or local class) and the second condition will verify that your member class is not static.
By the way, the documentation explains the differences between local, anonymous and nested classes.
Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are simply called static nested classes. Non-static nested classes are called inner classes.
o instanceof Outer.Inner gives false when o is an instance of an Inner of any Outer other than the one you're calling it from.
This doesn't happen for me - I get true for o instanceof Inner regardless of which particular enclosing instance of Outer the o belongs to:
class Outer {
class Inner {}
void test() {
// Inner instance that belongs to this Outer
Inner thisInner = new Inner();
// Inner instance that belongs to a different Outer
Outer other = new Outer();
Inner otherInner = other.new Inner();
// both print true
System.out.println(thisInner instanceof Inner);
System.out.println(otherInner instanceof Inner);
}
public static void main(String[] args) {
new Outer().test();
}
}
Tested with both Java 6 and 7.
Did you try using getEnclosingClass():
Returns the immediately enclosing class of the underlying class. If the underlying class is a top level class this method returns null.
Outer.class.equals(object.getClass().getEnclosingClass())
Getting the correct enclosing class of the object , IMHO is not so easy . Read this.
Somewhat of a hack would be :
object.getClass().getName().contains("Outer$");
you could always:
getClass().getName()
and do a String comparison.
EDIT : to account for inheritance (among inner classes? who would do that?!) you could always loop through getSuperclass() and check for them as well, and even go after implemented interfaces.
The java.lang.Class.getEnclosingClass() method returns the immediately enclosing class of the underlying class. If this class is a top level class this method returns null.
The following example shows the usage of java.lang.Class.getEnclosingClass() method:
import java.lang.*;
public class ClassDemo {
// constructor
public ClassDemo() {
// class Outer as inner class for class ClassDemo
class Outer {
public void show() {
// inner class of Class Outer
class Inner {
public void show() {
System.out.print(getClass().getName() + " inner in...");
System.out.println(getClass().getEnclosingClass());
}
}
System.out.print(getClass().getName() + " inner in...");
System.out.println(getClass().getEnclosingClass());
// inner class show() function
Inner i = new Inner();
i.show();
}
}
// outer class show() function
Outer o = new Outer();
o.show();
}
public static void main(String[] args) {
ClassDemo cls = new ClassDemo();
}
}
Output
ClassDemo$1Outer inner in...class ClassDemo
ClassDemo$1Outer$1Inner inner in...class ClassDemo$1Outer
I was googling for finding out better answers, to find out that there are none out there.
Here is what I have which works pretty well:
public static boolean isStatic(Class klass) {
return Modifier.isStatic(klass.getModifiers());
}
/**
* Non static inner class
*/
public static boolean isInnerclass(Class klass) {
return klass.getDeclaringClass() != null && !isStatic(klass);
}
Will return true for local inner classes. isMemberClass and others do not work for this purpose.

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