Oracle documentation(in below link) says that:
Non-static nested classes (inner classes) have access to other members
of the enclosing class, even if they are declared private.
But in below example I created an object objin (of inner class) and it couldn't access any of the method or variable of its enclosing outer class. Below is the code, could you any one clarify on the same?
http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
package Package_1;
public class Outer {
int k;
public void Multiply()
{
System.out.println("inside outer class' method multiply");
}
public class Inner {
int l;
public void Division()
{
System.out.println("inside inner class' method Divison");
}
}
}
Class with Main method
package Package_1;
public class D {
public static void main(String[] args) {
Outer objout = new Outer();
objout.k = 5;
objout.Multiply();
Outer.Inner objin = objout.new Inner();
objin.l = 7;
objin.Division();
}
}
With objin object I couldn't access that Multiple method in its enclosing class.
I see your "privates"!
From the code of the non-static nested class (inner class) you have access to both public and private members of the enclosing class.
But it's your "privates", not mine!
This is what you're thinking when you try do objin.Multiply(): you are accessing Multiply() as though it's a member of the inner class, but it's not. Remember, you can see it from within the code of the inner class, but it will not be exposed as though it's yours.
This is what the specification says
public class Outer{
private int x;
private void method(){
}
public void publicMethod(){}
public class Inner{
//has access to even private properties of x
method(); //can be called
//NOTE: Only has ACCESS and does not INHERIT those methods
}
}
What you are trying is to access the publicMethod() with the instance of Inner, which does not have any method of that name.
THE CRUX:
The non-static nested classes just has the access to all properties and methods of container class, but does not inherit those methods.
objin.Multiply() cannot work as the crux explains that Multiply() is defined on Outer and not Inner, so there is no method Multiply() on Inner
The documentation doesn't say that you can access to fields and methods of the outer class by using a reference to the inner class. So you can't do
objin.Multiply();
because Multiply is not a method of Inner. What you can do is:
public class Inner {
int l;
public void Division()
{
System.out.println("I can access the field k in outer: " + k);
System.out.println("I can access the method Multiply in outer (even if Multiply was private): ");
Multiply();
// which is a shortcut for
Outer.this.Multiply();
}
}
PS: please respect the Java naming conventions. Methods start with a lowercase letter.
You are trying to access the method by using instance of the Inner class object. It can be accessed outside only by Outer class method. You can call the method inside the class definition of the Inner class directly but not by using the instance of inner class. if you still want to do this try :
package Package_1;
public class Outer {
int k;
public void Multiply()
{
System.out.println("inside outer class' method multiply");
}
public class Inner {
int l;
public void Division()
{
System.out.println("inside inner class' method Divison");
}
public void Multiply() {
Outer.this.Multiply(); //Outer class method.
}
}
}
Related
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...
I have the following problem. Two nested anonymous types. I want to access "this" reference of the outer anonymous class inside the most inner class. Usually if one has anonymous nested class in a named outer class (lets call it "class Outer") he/she would type inside the nested class Outer.this.someMethod(). How do I refer the outer class if it's anonymous ?
Example Code:
public interface Outer {
void outerMethod();
}
public interface Inner {
void innerMethod();
}
...
public static void main(String[] args) {
...
new Outer() {
public void outerMethod() {
new Inner() {
public void innerMethod() {
Outer.this.hashCode(); // this does not work
} // innerMethod
}; // Inner
} // outerMethod
}; // Outer
...
} // main
The error I get is
No enclosing instance of the type Outer is accessible in scope
I know that I can copy the reference like this:
final Outer outerThisCopy = this;
just before instantiating the Inner object and then refer to this variable. The real goal is that I want to compare the hashCodes of outerThisCopy and the object accessed inside the new Inner object (i.e the Outer.this) for debugging purposes. I have some good arguments to think that this two objects are different (in my case).
[Context: The argument is that calling a getter implemented in the "Outer" class which is not shadowed in the "Inner" class returns different objects]
Any ideas how do I access the "this" reference of the enclosing anonymous type ?
Thank you.
You cannot access an instance of anonymous class directly from inner class or another anonymous class inside it, since the anonymous class doesn't have a name. However, you can get a reference to the outer class via a method:
new Outer()
{
public Outer getOuter()
{
return this;
}
public void outerMethod()
{
new Inner()
{
public void innerMethod()
{
getOuter().hashCode();
}
};
}
};
//below class is the example where in subclass extends the innerclass and from the subclass i am trying to access the methods of outer class i.e encapsulating class of inner class.
package innerClass;
public class outterclass {
private int outer=24;
protected int get_outer(){
return outer;
}
protected static class innerclass{
private int outer=25;
protected int get_outer(){
return outer;
}
}
}
package innerClass;
public class subclass_B extends outterclass.innerclass {
void parent_class_info_fetch(){
System.out.println(get_outer());
//i want to access the outer class get_outer method and how do i achieve that?
}
public static void main(String[] args) {
InheritanceStaticInnerClass_B isb=new InheritanceStaticInnerClass_B();
isb.parent_class_info_fetch();
}
}
Your innerclass is not an inner class. It is a static nested class and bears no special relationship to its enclosing class. You cannot reach an instance of the enclosing class because no such instance is available to innerclass or its subclasses.
If innerclass was indeed inner, then you would have to instantiate it with an enclosing instance:
outterclass outer = new outerclass();
subclass_B b = outer.new subclass_B();
Then, in parent_class_info_fetch() you could write
outterclass.this.get_outer()
to reach that method.
Of course, there would be several layers of bad practices in such code, so consider this just an academic execrise.
You should also learn about the basic naming conventions in Java.
The class outterclass.innerclass is a static class field, which means you don't necessarily have an enclosing instance of outterclass. On the other hand, the method get_outer of outterclass is an instance method, so you'll need the enclosing instance to call it.
With the class hierarchy you have, you'd have to make get_outer static (which requires making outer static as well).
public class InnerClass {
class Inner
{
public void method()
{
System.out.println("Innerclass");
}
}
}
class Sample extends InnerClass.Inner
{
public static void main(String [] arg)
{
Sample s = new Sample(new InnerClass());
s.method();
}
//why is this mandatory???
Sample(InnerClass i) {
i.super();
}
#Override
public void method() {
System.out.println("derived class");
}
}
when i make a class that derives from an innerclass (Innerclass.Inner) default constructor doesn't works. later i came to know that it requires to include a constructor taking Enclosing class reference why is it so?
Non static inner classes in Java have an implicit reference to the enclosing instance. You can solve your problem with:
public class InnerClass {
static class Inner // can make it public too
{
public void method()
{
System.out.println("Innerclass");
}
}
}
Just don't expect to be able to call any methods on InnerClass without a specific instance.
Because non-static inner classes have an implicit member that points back to their outer class, and you can't create an instance of the inner class without giving it that pointer. If you directly create an instance of an inner class, you have to use new outer.Inner() (or it might be outer.new Inner(), I can never remember). But Sample isn't an inner class, it just inherits one, so the outer instance must be passed in its constructor to the base constructor. Thus, it needs to have some instance of outer available, or create it itself.
The following Java program just calculates the area of a circle. It uses the concept of inner classes available in Java. One of the inner classes (FirstInner) inherits it's enclosing class named Outer and the SecondInner class derives the FirstInner in turn. The program is working just fine. There is no problem at all. Let's have look at it.
package innerclass;
import innerclass.Outer.SecondInner; // Need to be inherited.
import java.util.Scanner;
class Outer
{
protected double r;
public Outer()
{
}
public Outer(double r)
{
this.r=r;
}
public class FirstInner extends Outer
{
public FirstInner(double r)
{
super(r);
}
}
final public class SecondInner extends FirstInner
{
public SecondInner(double r)
{
Outer.this.super(r); //<-------------
}
public void showSum()
{
System.out.print("\nArea of circle = "+(Math.pow(r, 2)*Math.PI)+"\n\n");
}
}
}
final public class Main
{
public static void main(String[] args)
{
Scanner s=new Scanner(System.in);
System.out.print("\nEnter radius:->");
double r=s.nextDouble();
Outer o=new Outer();
SecondInner secondInner = o.new SecondInner(r);
secondInner.showSum();
}
}
Now in the SecondInner class, I'm qualifying it's super class which is the FirstInner class first with this and again with Outer like Outer.this.super(r); which simply looks like just super(r);.
The use of only super(r) rather than Outer.this.super(r); causes a compiler-time error indicating that "cannot reference this before supertype constructor has been called". Why is it so? I mean why I have to use Outer.this.super(r); rather than just super(r)?
One more point when I make the FirstInner class static, the program issues no compile-time error and allows to use just super(r) in place of Outer.this.super(r);. Why?
I get a different error from my Eclipse environment:
"No enclosing instance of type Outer is available due to some intermediate constructor"
This one is clearer and can be linked to the fact that you cannot instantiate a non-static inner class before the outer class has been instantiated.
Please see the example that is described here.
15.11.2 Accessing Superclass Members using super
From the java tut
http://download.oracle.com/javase/tutorial/java/javaOO/nested.html
An instance of InnerClass can exist only within an instance of
OuterClass and has direct access to the methods and fields of its
enclosing instance.
Going by that statement, the following approach makes sense. You are accessing the instance using "this" by resolving with the help of the class name, which is defined here
in primary expressions .
http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#20860
class SecondInner extends FirstInner
{
public SecondInner(double r)
{
Outer.this.super(r); //<-------------
}
public void showSum()
{
System.out.print("\nArea of circle = "
+(Math.pow(r, 2)*Math.PI)+"\n\n");
}
}
}
For example if your SecondInner were to be declared within FirstInner it has to be accessed using FirstInner.this.super()