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'.
Related
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.
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
}
}
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.
So, here is the class with private Inner class declared inside and a private attribute.
I need to use Java reflection writing a test program in main function to execute this class.
public class Outter {
private Inner in;
public Outter(){
in = new Inner();
}
private class Inner{
private void test(){
System.out.println("test");
}
}
}
Here is test code:
my questions are listed following the statement.
public class Test
{
public static void main(String[] args) throws Exception
{
// 1. How do i create a Class type for Inner class since its modifier
// is private, if I am going to need .setAccessible() then how do i
// use it?
Class outter1 = Outter.class;
// 2. How do I pass parameters of type Inner to the Class object?
Constructor con = outter1.getConstructor(new Class[]{int.class});
// 3. Like this?
Field fields = outter1.getField("test");
fields.setAccessible(true);
// 4. Well I am lost what is the logic route for me to follow when
// using java reflection to execute a class like this!
Object temp = outter1.newInstance();
Outter outter = (Outter)temp;
System.out.println(fields.get(outter));
}
}
Here's a self-contained example of what you're trying to do.
Code you're running
try {
// gets the "in" field
Field f = Outer.class.getDeclaredField("in");
// sets it accessible as it's private
f.setAccessible(true);
// gets an instance of the Inner class by getting the instance of the
// "in" field from an instance of the Outer class - we know "in" is
// initialized in the no-args constructor
Object o = Object o = f.get(Outer.class.newInstance());
// gets the "execute" method
Method m = o.getClass().getDeclaredMethod("test", (Class<?>[])null);
// sets it accessible to this context
m.setAccessible(true);
// invokes the method
m.invoke(o, (Object[])null);
}
// TODO better handling
catch (Throwable t) {
t.printStackTrace();
}
Classes (inner/outer)...
public class Outer {
private Inner in;
public Outer() {
in = new Inner();
}
private class Inner {
private void test() {
System.out.println("test");
}
}
}
Output
test
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.