I read that an instance of an inner class cannot be created without an instance of outer class. But when I tried to create an instance of my inner class using it as an instance member of my outer class, it worked.
I understand that it is creating an inner object through a reference to my outer class object, but is it the right way to do it?
Below is my code snippet:
public class TestInner {
private Nonstatic non = null;
private static int access = 4;
public class Nonstatic {
void hello() {
access = 90;
}
}
public static void main(String[] args) {
TestInner outer = new TestInner();
TestInner.Nonstatic innern= outer.new Nonstatic();
System.out.println("Non static obj1 is "+innern);
outer.testinnerObj();
}
public void testinnerObj() {
non = new Nonstatic();
System.out.println("Non static obj2 is "+non);
non.hello();
}
}
You're writing "An instance of Inner class cannot be created without an instance of outer class". And that's exactly what you are doing.
First, you create an instance of the "outer" class:
TestInner outer = new TestInner();
Then, you create an instance of the "inner" class - it only lives
in the scope of outer:
TestInner.Nonstatic innern= outer.new Nonstatic();
So, the question maybe boils down to this: yes, you are creating the object in the static main method. But that does not matter, because you are using the syntax outer.newwhich creates it in the scope of outer.
Hope that helps.
Related
I know how to make an instance of an inner class. But I want to know why we can not do that in the following way:
class outerclass{
public static void main(String[] args){
innerclass in=new innerclass();
}
class innerclass{
}
}
If I do this then I get the following error:
No enclosing instance of type outerclass is accessible. Must qualify the allocation with an enclosing instance of type outerclass (e.g. x.new A() where x is an instance of outerclass).
Why?
class Demo{
public static void main(String[] args){
System.out.println(innerclass.a);
}
static class innerclass{
static int a=1;
}
}
Gives the output 1.
See here while making the inner class as static You can easily access in your outer class,In order to create an instance of the Nested class you must reference it by prefixing it with the Outer class name, like this:
Outer.Nested instance = new Outer.Nested();
Non-static Nested Classes (Inner Classes)
Non-static nested classes in Java are also called inner classes. Inner classes are associated with an instance of the enclosing class. Thus, you must first create an instance of the enclosing class to create an instance of an inner class. Here is an example inner class definition:
public class Outer {
public class Inner {
}
}
Here is how you create an instance of the Inner class:
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
Notice how you put new after the reference to the outer class in order to create an instance of the inner class.
Non-static nested classes (inner classes) have access to the fields of the enclosing class, even if they are declared private. Here is an example of that:
public class Outer {
private String text = "I am private!";
public class Inner {
public void printText() {
System.out.println(text);
}
}
}
Your innerclass is not static. This means it must have a reference to the outerclass. main is static and has no implicit outerclass.
The simple solution is to make your inner class a static nested class.
You must either make your inner class static (as already mentioned) or create your inner class from a non-static context, e.g. from a non-static method.
I.e. either this:
class outerclass{
void myMethod() {
innerclass in = new innerclass();
}
class innerclass{
}
}
or this
class outerclass{
public static void main(String[] args){
innerclass in=new innerclass();
}
static class innerclass{
}
}
outerclass thats encapsulates innerclass is not instantiated, hence, calling innerclass directly would throw an error since there is no outerclass to attach innerclass.
Therefore as suggested by the previous answers, making innerclass static would resolve the problem, allowing access to the innerclass without instantiation.
There are lot of existing answers with regards to this topic. A quick google brings this up.
Java - No enclosing instance of type Foo is accessible
Is there any way to access the methods of local inner classes in Java. Following code is the sample code that I tried before. According to that what is the mechanism to access the mInner() method?
class Outer{
int a=100;
Object mOuter(){
class Inner{
void mInner(){
int y=200;
System.out.println("mInner..");
System.out.println("y : "+y);
}
}
Inner iob=new Inner();
return iob;
}
}
class Demo{
public static void main(String args[]){
Outer t=new Outer();
Object ob=t.mOuter();
ob.mInner(); // ?need a solution..
}
}
As ILikeTau's comment says, you can't access a class that you define in a method. You could define it outside the method, but another possibility is to define an interface (or abstract class). Then the code would still be inside your method, and could access final variables and parameters defined in the method (which you couldn't do if you moved the whole class outside). Something like:
class Outer {
int a = 100;
public interface AnInterface {
void mInner(); // automatically "public"
}
AnInterface mOuter() { // note that the return type is no longer Object
class Inner implements AnInterface {
#Override
public void mInner() { // must be public
int y = 200;
System.out.println("mInner..");
System.out.println("y : " + y);
}
}
Inner iob = new Inner();
return iob;
}
}
class Demo {
public static void main(String[] args) { // the preferred syntax
Outer t = new Outer();
Outer.AnInterface ob = t.mOuter();
ob.mInner();
}
}
Note: not tested
Note that the return type, and the type of ob, have been changed from Object. That's because in Java, if you declare something to be an Object, you can only access the methods defined for Object. The compiler has to know, at compile time (not at run time) that your object ob has an mInner method, and it can't tell that if the only thing it knows is that it's an Object. By changing it to AnInterface, the compiler now knows that it has an mInner() method.
The scoping rules of a local class are pretty much the same as the scoping rules of a variable, that is, it is confined to the enclosing block.
The same way you cannot access variable iob from main, you cannot access local class Inner from main.
Outside the enclosing block, there's no difference between a local class and an anonymous class. Neither can be accessed. The difference is that within the enclosing block, the local class can be accessed by name, especially useful if you need to access it repeatedly, e.g. to create multiple instances.
The only way to interact with a local/anonymous class outside the enclosing block, is through any superclass or interface implemented by the class in question.
To access the inner class create an object of inner class..
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
from your example
outer t=new outer();
outer.inner inner1=t.new inner();
Hope this helps you...
On changing non-static inner class to static why there are compile time error on running code says-
Illegal enclosing instance specification
public class TestingInnerStatic{
public static void main(String args[]) {
InnerSame innerSame = new TestingInnerStatic().new InnerSame();//compile fail
Outer.InnerDiff innerDiff = new Outer().new InnerDiff();//compile fail
}
public void main() {
InnerSame innerSame = new InnerSame();
Outer.InnerDiff innerDiff = new Outer().new InnerDiff();//compile fail
}
static class InnerSame{}
}
class Outer{
static class InnerDiff{}
}
take a example of other member,this is only a convention and a good practice to call a static member on reference of class but if U call them on object they works not show compile fail.So why there is a compile fail?
If an inner class is non-static then you require an instance of the outer class to make an instance of the inner class. But that is not the case for static classes, an instance of an inner static class can exist without an instance of the outer class.
static example:
InnerClass ic = new Outer.InnerClass();
Notice I am not making a new instance of the outer class.
EDIT: reference
Here is the code where I am updating the instance variable x of OuterClass by static variable of StaticInner. I understand that the static inner classes cannot refer directly to instance variable of outer classes. I am using an instance of outerclass to refer to its instance variable 'x' and update it. This goes into stackoverflow error. The code complies fine. The last line in the code does not compile which I commented out. I don't understand what the problem with that line.
public class OuterClass {
private int x = 10;
private static int y = 15;
private static StaticInner si=null;
public OuterClass() {
setStaticInner();
this.x=si.ic.x;
}
public static class StaticInner {
private static int z = 20;
private OuterClass ic = new OuterClass();
public void increment() {
OuterClass.y+=z;
z+=OuterClass.y;
ic.x+=10;
}
}
public void setStaticInner(){
si=new StaticInner();
}
public static void main(String[] args){
OuterClass ic = new OuterClass();
ic.si.increment();
System.out.println(ic.x);
//OuterClass.StaticInner sb1 = ic.new StaticInner(); This line does not compile.
}
}
You have a circular dependency in the constructors, resulting in a recursive call between them
Outer(){
createInner()
}
Inner(){
createOuter()
}
This won't work (unless you use reflection, but that defeats the purpose).
You need to structure the classes so there is a linear dependency. I recommend passing the outer instance to the inner constructor
Outer(){
inner = new Inner(this);
}
Inner(Outer o){
myouter = o;
}
Don't qualify "new" with an outer class instance. That only applies to inner classes. Just instantiate the nested class like any other.
You should not need to mention the outer class at all when working with a static nested class inside the outer class.
I created a non-static inner class like this:
class Sample {
public void sam() {
System.out.println("hi");
}
}
I called it in main method like this:
Sample obj = new Sample();
obj.sam();
It gave a compilation error: non-static cannot be referenced from a static context When I declared the non-static inner class as static, it works. Why is that so?
For a non-static inner class, the compiler automatically adds a hidden reference to the "owner" object instance. When you try to create it from a static method (say, the main method), there is no owning instance. It is like trying to call an instance method from a static method - the compiler won't allow it, because you don't actually have an instance to call.
So the inner class must either itself be static (in which case no owning instance is required), or you only create the inner class instance from within a non-static context.
A non-static inner class has the outer class as an instance variable, which means it can only be instantiated from such an instance of the outer class:
public class Outer{
public class Inner{
}
public void doValidStuff(){
Inner inner = new Inner();
// no problem, I created it from the context of *this*
}
public static void doInvalidStuff(){
Inner inner = new Inner();
// this will fail, as there is no *this* in a static context
}
}
An inner class needs an instance of the outer class, because there is an implicit constructor generated by compiler. However you can get around it like the following:
public class A {
public static void main(String[] args) {
new A(). new B().a();
}
class B {
public void a() {
System.err.println("AAA");
}
}
}
Maybe this will help : http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html
the non-static inner class cannot be called in a static context (in your example there is no instance of the outer class).