Java Inner Class (not static) [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have a question about this topic:
An instance by a inner class need everytime an object of the same type of the guest class of the inner class. example:
public class GuestClass {
class innerClass {
}
public static void main(String[] args) {
innerClass test = new innerClass(); //does not work because
//I need a object of type GuestClass
GuestClass iNeedYou = new GuestClass();
innerClass nestClassObj = iNeedYou.new innerClass(); //it works
}
}
ok it's clear.
the innerClass object now points also to an GuestClass object (iNeedYou)
Now come my question:
an anonymous class is also a inner class right?
but with some difference:
A. I don't know the type of this object
B. it implements an interface.
but it is still an object by an inner class (anonymus but inner)
in fact if I do this:
public class GuestClass {
private int numb = 100;
class innerClass {
}
public void createAnAnonymusObject () {
myInterface myAnObj = new myInterface(){
int a, b;
#Override
public void print() {
System.out.println(numb); //it works
}};
myAnObj.print();
}
public static void main(String[] args) {
GuestClass iNeedYou = new GuestClass();
iNeedYou.createAnAnonymusObject();
}
}
works because the anonymous inner object points to the outer object... so i can see the variable numb.
but why this works?
public static void main(String[] args) {
myInterface myAnObj = new myInterface(){ //why does it work? in this case
//where is the outer object?
int a, b;
#Override
public void print() {
}};
}
if the anonymous class is an inner class why it doesn't need an outer object?

You're basically asking two questions here.
Why does a non-static nested class require an enclosing instance?
Because it's assumed to have access to all non-static members of the outer class. Even if you don't actually use any of those, the compiler can't infer that the non-static nested class can be used safely in static context. You have to explicitly mark it static to allow this.
Where and what is the enclosing object of the anonymous class created in this snippet?
public class OuterClass {
private int nonStaticMember;
private static int staticMember;
public static void main(String[] args) {
MyInterface myAnObj = new MyInterface(){ //why it works ?? in this case
//where is the outer object?
#Override
public void print() {
//nonStaticMember is not visible in this scope
//staticMember is visible in this scope
}};
}
}
In this case, your anonymous class has no enclosing instance. It's created in a static context, in the main method. You can instantiate MyInterface because all interfaces are implicitly static, even if defined inside another class. That's why the interface is visible at all. All of the non-static members of OuterClass, on the other hand, are not available in this scope so you're guaranteed not to use any of them. This is why there is no need to have a reference to an enclosing object. In fact, this is included in the language's specification.
Take a look at this Java Language Standard excerpt
Let C be the class being instantiated, and let i be the instance being
created. If C is an inner class then i may have an immediately
enclosing instance. The immediately enclosing instance of i (§8.1.3)
is determined as follows.
If C is an anonymous class, then:
If the class instance creation expression occurs in a static context
(§8.1.3), then i has no immediately enclosing instance.
Otherwise, the immediately enclosing instance of i is this.
(...)
I only quoted the most relevant part for this use case. Feel free to dive a little deeper into it.

public class Anonymous2 {
private int numb = 100;
public static void main(String[] args) {
MyInterface myAnObj = new MyInterface(){ //why it works ?? in this case
//where is the outer object?
int a, b;
#Override
public void print() {
System.out.println(numb);
}};
}
}
interface MyInterface {
public void print();
}
Compiling:
C:\JavaTools>javac Anonymous2.java
Anonymous2.java:11: error: non-static variable numb cannot be referenced from a static context
System.out.println(numb);
^
1 error
As can be seen, the code that the OP claimed would compile doesn't. So this entire question is irrelevant.

Related

Extending an inner class in java

I'm having trouble trying to implement this statement I read in Oracle's Docs about Inheritance when it comes to inner classes.
The statement :
A nested class has access to all the private members of its enclosing class—both fields and methods. Therefore, a public or protected nested class inherited by a subclass has indirect access to all of the private members of the superclass.
In order to test this out i.e. to see if I can achieve the above I created a top level class OC1 which had an inner class IC1 ,then I created another top level class OC2 which extended IC1.
Before I could even start writing a single method , the IDE stopped me at the OC2 class body itself saying
"No enclosing instance of type DataStructure is available due to some intermediate constructor invocation"
I read some other answers and most of them point to either
a) Changing the inner class to static Nested Class -- it resolves the error
b) The whole scenario is unnecessary and convoluted.
Here is the code:
public class DataStructure {
// Create an array
private final static int SIZE = 15;
private int[] arrayOfInts = new int[SIZE];
public DataStructure() {
// fill the array with ascending integer values
super();
for (int i = 0; i < SIZE; i++) {
arrayOfInts[i] = i;
}
}
//other methods
//IC1
protected class instanceArr{
private int a = 8;
private static final int B = 4;
protected instanceArr(){
}
protected void doSomething(){
System.out.println("arrayOfInts[] is accessible " + arrayOfInts[6]);
}
}
//main method
}
OC2
public class DataStructureChild extends DataStructure.instanceArr{
public DataStructureChild(){
}
}
I know that the scenario is not an ideal one but I don't want to change inner class to static nested class - it would defeat my purpose of basically trying to see whether arrayOfInts is accessible without OC1's instance in hand.
Am I misinterpreting this statement ? if not then kindly point me in the correct direction.
PS - this is my first question here - apologies in advance if some guidelines were flouted.
Yes, this is a Trap caused by Java's synthetic sugar. You think the inner-non-static-class have the default-no-arguments-constructor but that is wrong. Internally the constructor of IC1 have the OC1 as first argument in the constructor - even if you can not see it.
Thats why the OC2 constructor must use the OC1 as constructor-argument:
public DataStructureChild(DataStructure argument) {
}
Unfortunaltely this is not enougth, you need to get sure the argument is not-null:
public DataStructureChild(DataStructure argument) {
argument.super();
}
It looks very wierd but it works.
You can do this since you inherit access to the inner class of the parent.
class DataStructureChild extends DataStructure {
public DataStructureChild() {
}
public void foo() {
InstanceArr ins = new InstanceArr();
ins.doSomething();
System.out.println(ins.a);
}
}
But could you please give a link or explain where you read the following? A nested class has access to all the private members of its enclosing class—both fields and methods. Therefore, a public or protected nested class inherited by a subclass has indirect access to all of the private members of the superclass.
The first part I knew about. But I never considered a separate class extending another classes inner class. Especially since there is usually an implicit relationship between classes and their enclosed inner classes.
Edit:
I believe you misunderstood the statement.
It says that your subclass inherits the inner class. That is true.
It also says that once done you have access to the private values of the inherited inner class. That is also true as demonstrated above:
So it was just talking about access the inner class via inheritance, not extending it directly.
However, if you really want to do have that kind of inheritance relationship without passing references around, you can go this route.
public class Inheritance extends Outer.Inner {
public Inheritance() {
new Outer().super();
}
public static void main(String[] args) {
new Inheritance().start();
}
public void start() {
System.out.println(a);
method();
}
}
class Outer {
public Outer() {
}
protected class Inner {
protected int a = 10;
protected Inner() {
}
protected void method() {
System.out.println("This is a private message");
}
}
}

Can Anonymous inner class instantiated within a static method has access to instance members of containing class?

I want to understand better the visibility of instance fields of containing class to an Anonymous inner class (AIC).
There have been lots of talks that AIC has an implicit reference to the containing class' instance (When exactly is it leak safe to use (anonymous) inner classes?). With that logic, even when an AIC is instantiated within a static method, it should have access to the instance fields of the containing class. But I can't find a way to test this as the compiler gives errors.
For e.g., in the below code, I get: "Non-static field 's' can't be referred from a static context" by the compiler when I refer 's' within print() method of the AIC:
public interface TestInterface {
void print();
}
public class AICTest {
public String s = "something";
public static void main( String[] args ) {
new TestInterface() {
#Override
public void print() {
System.out.println( s ); **<-- compilation error**
}
}.print();
}
}
Could you suggest if it's possible for the AIC instance to access 's' in the above example?
Edit/Answer
I want to clarify that I am aware that static methods have access to class members and instance methods have access to instance & class members. The confusion was more about the general statement that AIC always have an implicit reference to containing class' object. This clearly is not the case for AIC initialised within a static method. #shmosel shared a link which answers my question (Is it possible to make anonymous inner classes in Java static?): "So an anonymous class in a static context is roughly equivalent to a static nested class in that it does not keep a reference to the enclosing class, even though it's technically not a static class.".
You have to have an instance of AICTest to read 's' out of, since 's' is an instance variable. Here's an example that will work, representing your example modified to access an existing AICTest object that could potentially come from anywhere:
class AICTest {
public String s = "something";
public static void main( String[] args ) {
AICTest aic = new AICTest();
new TestInterface() {
#Override
public void print() {
System.out.println(aic.s);
}
}.print();
}
}
To be clear, running 'main' does not create an instance of AICTest. You have to do a 'new' somewhere to create an instance of AICTest.
Another option is to make 's' static. Then it isn't associated with any particular AICTest object, and so it exists even if you haven't instantiated an AICTest object:
class AICTest {
public static String s = "something";
public static void main( String[] args ) {
new TestInterface() {
#Override
public void print() {
System.out.println(s);
}
}.print();
}
}
As you can see, I haven't added any visibility modifiers. So your idea about visibility was sound. If it otherwise makes sense to access 's', the visibility is there in your code. The problem here has nothing to do with visibility.
This may not be what you want, but you can:
interface TestInterface {
void print();
}
class AICTest {
public String s="something";
public static void main(String[] args) {
AICTest aicTest=new AICTest();
new TestInterface() {
#Override public void print() {
System.out.println(aicTest.s);
}
}.print();
}
}
The confusion was more about the general philosophy that AIC always have an implicit reference to containing class' object. This clearly is not the case for AIC initialised within a static method. #shmosel shared a link which answers my question (Is it possible to make anonymous inner classes in Java static?): "So an anonymous class in a static context is roughly equivalent to a static nested class in that it does not keep a reference to the enclosing class, even though it's technically not a static class.".

strange Cannot be referenced from a static context error in Java [duplicate]

This question already has answers here:
non-static variable this cannot be referenced from a static context when creating instance of class
(2 answers)
Closed 5 years ago.
Wondering - why there is such error message during compile:
ClassHierarchyTest1.this Cannot be referenced from a static context
Source code:
public class ClassHierarchyTest1 {
class Foo {
int a;
Foo(int b) {
this.a = b;
}
}
public static void main(String[] args) {
Foo f = new Foo(1); // this line has the error message
}
}
Foo is an inner class and therefore you can access it only through instance of ClassHierarchyTest1. Like that:
Foo f = new ClassHierarchyTest1().new Foo(1);
Another option is to define foo as static:
static class Foo{...}
Foo is a member of ClassHierarchyTest1 . Hence you have to use ClassHierarchyTest1 inorder to access it's members.
Docs of Inner Classes
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.
class OuterClass {
...
class InnerClass {
...
}
}
To instantiate an inner class, you must first instantiate the outer class. Then, create the inner object within the outer object with this syntax:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
Not at all strange.
Your inner class itself is not static. Thus it always needs an object of the outer enclosing class. Which you don't have in your static main.
So you have to change Foo to be static (of course you then can't use the "outer this"), or you have to create an instance of your outer class first,and call new on that object.
add static to your class
public class ClassHierarchyTest1 {
class static Foo {
int a;
Foo(int b) {
this.a = b;
}
}
public static void main(String[] args) {
Foo f = new Foo(1); // this line has the error message
}
}

Access methods within local inner classes in 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...

Inheriting InnerClass in java

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.

Categories

Resources