Access methods within local inner classes in Java - java

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...

Related

Non static inner class object creation without explicit enclosing instance

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.

How to access "this" reference of anonymous outer class in java

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();
}
};
}
};

Does a constructor of private class has to be private?

If a class is private then must the constructor be private as well?
No, there is no such restriction. See JLS ยง8.8.3. Constructor Modifiers.
It's worth pointing out that only a nested class can be declared private. The JLS permits the constructors for such a class to use any valid access modifiers.
If you mean nested class, the answer is no. Making the inner class private makes it only usable within the outer class.
Edit: It appears that outer classes have full access to the innards of the inner classes regardless of their access modifiers. This invalidates my above reasoning, but regardless, there is no such restriction. Curiously though, now it appears that if the inner class is private, its constructor is essentially private, regardless of its access modifier, since noone else can call it.
No it hasn't. On the contrary, if you create an instance of the inner class using a private constructor (which is default for a private class) from the outer class Java will create an additional class to prevent access violation and keep JVM happy
If you compile this class
class Test {
private class Test2 {
Test2() {
}
}
Test() {
new Test2();
}
}
javac will create Test.class, Test#Test2.class
and if you compile this class
class Test {
private class Test2 {
}
Test() {
new Test2();
}
}
javac will create Test.class, Test#Test2.class, Test$1.class
No it is not fix, you can set it private/public/any you want.
But in some case I prefer to make constructor private, when you don't want to allow other classes to create object of this class. then in that case you can do something like this, by setting constructor private.
private class TestClass{
private TestClass testClass=null;
private TestClass(){
//can not accessed from out side
// so out side classes can not create object
// of this class
}
public TestClass getInstance(){
//do some code here to
// or if you want to allow only one instance of this class to be created and used
// then you can do this
if(testClass==null)
testClass = new TestClass();
return testClass;
}
}
Btw it depends on your requirement.
It does not have to be private. But it can. Example:
public class Outer {
// inner class with private constructor
private class Inner {
private Inner() {
super();
}
}
// this works even though the constructor is private.
// We are in the scope of an instance of Outer
Inner i = new Inner();
// let's try from a static method
// we are not in the scope of an instance of Outer
public static void main(String[] args) {
// this will NOT work, "need to have Inner instance"
Inner inner1 = new Inner();
// this WILL work
Inner inner2 = new Outer().new Inner();
}
}
// scope of another class
class Other {
// this will NOT work, "Inner not known"
Inner inner = new Outer().new Inner();
}
It doesn't make a difference if you use private or public constructor on private inner classes. The reason is that the inner class instance is part of the outer class instance. This picture says it all:
Note that we are talking about an inner class. If the nested class was static, the official terminology is static nested class, which is different from an inner class. A public static nested class would be accessible without outer class instance just by calling new Outer.Inner(). See here for more information about inner- and nested classes. http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

How to pass object into implements and pass out the local object?

How do I pass a object to an implement and pass the local object to object that is outside? I think the SwingUtilities.invokeLater is nessasary for a Swing object , right?
Sensors sens = new Sensors();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
GUI application = new GUI(sens);
application.getJFrame().setVisible(true);
}
});
SMS sms = new SMS(application);
this is me try to solve the problem , but i get a No enclosing instance of type GUI is accessible. Must qualify the allocation with an enclosing instance of type GUI (e.g. x.new A() where x is an instance of GUI). problem.
// in main
Sensors sens = new Sensors();
GUI application = null;
SwingUtilities.invokeLater(new GUIthread(sens , application));
SMS sms = new SMS(application);
//a class inside GUI.java , but not inside GUI class
class GUIthread implements Runnable{
Sensors s;
GUI g;
public GUIthread(Sensors s , GUI g){
this.s = s;
this.g = g;
}
#Override
public void run() {
// TODO Auto-generated method stub
g = new GUI(s);
g.getJFrame().setVisible(true);
}
}
the sourcecode
This problem arises when you try to create an instance of a non-static inner class in a context that does not specify (or imply) an instance of the enclosing class.
From this, I deduce that you have declared one of your classes as a non-static inner class; e.g. something like this:
public class Outer {
...
public class Inner {
public Inner() {
...
}
...
}
...
}
If you now try to create an instance of Inner in some other code using new Inner(), you will get a compilation error like the one you are seeing.
You can do one of two things to "fix" the problem:
If you change public class Inner { to public static class Inner {, you can use new Inner() as you are currently doing. But this will mean that the code of Inner cannot access the (final) instance variables of the enclosing class; i.e. Outer.
If you don't want to change Inner to a static class, you will need to instantiate it as follows:
Outer outer = ...
...
Inner inner = outer.new Inner(); // qualified creation
FOLLOWUP
any down side using static class to call swing?
Only the one that I identified above.
SO , all the instantiate happen inside Outer constructor? right?
No. The code in the "qualified creation" example above can appear anywhere that the Inner class is accessible. And since we declared it as public ...
If you instantiate Inner inside a constructor (or instance method) for Outer, you can just use new Inner(). The enclosing Outer instance is the same as this.
Try
final Sensors sens = new Sensors();
instead.
Easy, declare the reference final and it will be seen by the anon class code.
I agree with Zach and suspect that GUIthread is an inner class. If so, you may do well to make it a stand-alone class or a static inner class, but it's difficult to know if this is the true solution without more information and without the actual error message.

Must the inner class be static in Java?

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).

Categories

Resources