There was one MCQ ( Multiple Choice Question ) while I was reading my Java study book and that MCQ is:
Question : In case of inner and outer classes, _________
Options are :
(a) The members of outer class can not be accessed by inner class.
(b) The members of inner class can not be accessed by outer class.
(c) Members of both can be accessed by both of the classes.
(d) None of these.
The answer given on book answer key is (b) but I'm not feeling it as right answer because outer class can access members of its inner class I think. So please help me with what is right.
Thanks, have a good day :)
lets make it simple with some code
public class A {
public int a = 1;
public class B {
public int b = 2;
public int getAfromB() { return a; } // ACCESS OUTER CLASS MEMBER IMPLICITLY
public int getBfromB() { return b; }
}
public int getBfromA() {
B myB1 = new B();
B myB2 = new B();
return myB1.b + myB2.b;
}
}
An B instance is linked to a specific A instance, it belongs to the instance scope. In its scope, the members of the A class are defined.
The A class can handle several instances of the B class. It will be able to manipulate them but cannot implicitly access a specific instance members, simply because 'b' is not unique from its perspective.
Sorry for the confusion.
You can access inner and outer classes both ways. I do suggest trying a simple example though yourself as programming is one of those things you only learn through your own problems.
Refer to this as this may help: Can an outer class access the members of inner class?
Related
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 3 years ago.
Improve this question
I'm so confused that how could it be written like this... It creates an instance from another instance
st.new FirstLevel();
public class ShadowTest {
public int x = 0;
class FirstLevel {
public int x = 1;
void methodInFirstLevel(int x) {
System.out.println("x = " + x);
System.out.println("this.x = " + this.x);
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
}
}
public static void main(String... args) {
ShadowTest st = new ShadowTest();
ShadowTest.FirstLevel fl = st.new FirstLevel();
fl.methodInFirstLevel(23);
ShadowTest.FirstLevel mali = st.new FirstLevel();
}
}
Here, FirstLevel is a so-called inner class – that's because it is defined inside another class. Both relations (the 'outer' and the 'inner') are plain jane classes (and not interfaces, enums, or records). In this case, unless the inner class has the modifier static on it (and, in your code, it doesn't), then you get an instance inner class.
Such classes have a hidden field of the outer type associated with them. It is as if your FirstLevel class has this field:
private final ShadowTest outerInstance;
And each and every constructor of ShadowTest has a parameter for this field, but, it is hidden and a bit special.
Because this secret field exists, you can do things like invoke non-static methods from ShadowTest from within FirstLevel.
If you type new FirstLevel(), that just works... but only within non-static contexts inside ShadowTest. Anywhere else and the compiler will tell you that it doesn't know what instance of ShadowTest to pass along for that secret field. You can explicitly define which instance of ShadowTest. But not with new FirstLevel(shadowTestInstance), but with the somewhat weird-looking syntax shadowTestInstance.new FirstLevel(). But, it's the same thing: A parameter being passed to a constructor.
I generally advise that you do not use instance inner classes unless you really know they are the best fit for the case; this hidden field tends to cause confusion and surprises. I'd go so far as to say that you should never have instance inner classes; if you must hold a reference to an instance of the outer class, make it explicit (add an actual field, and make an actual parameter in your constructor). That way you avoid the surprises and confusion, at least. In other words, mark your FirstLevel class as static. By making your outer reference explicit, the shadowing thing also goes away; now you just have x or this.x referring to the x field in FirstLevel, and outerInstance.x for the outer field:
static class FirstLevel {
final ShadowTest shadow;
int x;
public FirstLevel(ShadowTest shadow) { this.shadow = shadow; }
}
As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.ref.javaOO_nested
As per java syntaxes, unless it's a private or static class you could initialize it in the following way
class OuterClass {
...
class InnerClass {
...
}
}
Then a sample initialisation can be done so:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
NOTE: I have referred the block to the oracle java docs. You can read more there
Hopefully this question hasn't already been asked. I've had a look around but haven't found a similar post.
Experimenting in Java I've noticed that there is no restriction on having duplicate method signatures in a nested class, which seems counter-intuitive.
For example, if I create class A containing a method with the signature int x() and later add a nested class B containing an identical method, the compiler seems to have no problem with it. My initial assumption was that it would complain that x is already defined. Perhaps I'm missing something obvious that explains why this is allowed?
class A {
int x() {
return 1;
}
class B {
int x() {
return 2;
}
}
}
Subsequently, is there any way to access class A's method x from within the scope of class B, or is it permanently hidden by the method x of the local scope?
Edit: I appreciate that the core of the question is the same as this post, however, I was more interested in understanding why this behaviour is allowed as it wasn't immediately clear to me.
Where a class is defined doesn't matter so much. Keep in mind, in the end you have
class A { int x()
and
class A.B { int x()
Two (almost) independent classes. The only relationship that we have here is that any instance of B needs an "enclosing" instance of A to which it belongs (because it is a non-static inner class).
And of course, you can access the "enclosing" A "stuff" from within B, for example using A.this.x().
This should be available somewhere in the JLS - but ultimately it boils down to scope. Each of them has a different scope - thus the compiler does not complain.
Why would the compiler complain? They are two different classes, they just happen to be nested.
Subsequently, is there any way to access class A's method x from within the scope of class B, or is it permanently hidden by the method x of the local scope?
A.this.x()
At first method signature is not the combination of return type and method name it is method name and parameters.
if you call x() it will run x() inside the B
A.this.x(); it will run x() in A
Its scope, it's similar to have an instance variable called foo and then a local one in the method called foo as well.
Its worth reading about scope in java
Inner class in java can access all the members (i.e variables and methods) including private one, but outer class can not access member of inner class directly.
To access x() method of class B inside class A you can either create B's instance and call it or call like this A.this.x();
To access x() method outside class A you can do something like this:
B b = a.new B();
b.x();
If you are using non-static nested class (inner class) then it wouldn't be able to access to x method of B class from other classes. But if you are using static nested class you will be able to access that method from other classes. Example:
public class A {
int x() {
new A.B().x();
return 1;
}
static class B {
int x() {
new A().x();
return 2;
}
}
}
public static void main(String[] args) {
A a = new A();
a.x();
B b = new A.B();
b.x();
}
I hope this example answering your question... ☺
B is nested inside A. According to scope rules we can do the following:
class A {
int x() {
return 1;
}
class B {
int x() {
return 2;
}
int xOfA(){
return A.this.x();
}
}
public static void main(String[] args) {
final A objA = new A();
final B objB = objA.new B();
System.out.println(objA.x());
System.out.println(objB.x());
System.out.println(objB.xOfA());
}
}
that is because B is visible from an instance of A.
Moreover B can reference methods in the containing class through their full paths.
For example, if I create class A containing a method with the signature int x() and later add a nested class B containing an identical method, the compiler seems to have no problem with it. My initial assumption was that it would complain that x is already defined. Perhaps I'm missing something obvious that explains why this is allowed?
When you define something in a nest scope which is otherwise in an outer scope, this is hiding.
What is important is that -: The version of a method that is executed will NOT be determined by the object that is used to invoke it. In fact it will be determined by the type of reference variable used to invoke the method
Subsequently, is there any way to access class A's method x from within the scope of class B, or is it permanently hidden by the method x of the local scope?
So as it is clear from above we can access it using class name, eg A.x
Hope this helps!!
So someone asked me to explain why the first scenario throws a compiler error and the 2nd scenario does not:
class Outer {
public Outer() {
Inner i = new Inner();
class Inner {
}
}
}
The other scenario is:
class Outer {
public Boss() {
Inner i = new Inner();
}
class Inner {
}
}
I was successful in explaining that the first scenario throws a compiler error because you can't create an object of the class Inner before the class Inner gets pushed onto the stack. Feel free to elaborate on this or correct my understanding.
My main problem was not being able to explain why we can create an Inner object even though the the code for the class Inner comes after the constructor in the 2nd scenario. I feel like the best answer to this question would be to know where exactly inner classes are stored in memory.
I'm hoping someone can provide a solid explanation. Thank you.
Nothing to do with stack, it's just the declaration order.
In this code:
class Outer {
public Outer() { // constructor "method" body BEGIN
Inner i = new Inner();
class Inner {
}
} // constructor "method" body END
}
As you are declaring Inner (a LOCAL class, not an inner class) in an ordinary block (that happens to be inside the constructor). This code is semantically equivalent to:
class Outer {
public Outer() {
String fullName = firstName + " Smith";
String firstName = "John";
}
}
Which clearly does not work.
Update:
I see where confusion may arise. Hopefully this will clarify:
There are four types of inner classes, and where they can be declared:
Static member classes: declared as fields;
Member classes: declared as fiels as well;
Local classes: declared in blocks, as a statement (just like a variable declaration);
Anonymous classes: also declared in blocks, but are expressions.
Bottom line is: Once again, as a local class is a statement, it's just like a variable declaration, you cannot access its "products" before that statement is executed.
This question already has answers here:
What causes error "No enclosing instance of type Foo is accessible" and how do I fix it?
(11 answers)
Closed 6 years ago.
I am trying to initialise the array C in the loop, but it gives error :
C is array of class ipdata and I have declared it and trying to initialise it inside the loop.
import java.io.*;
import java.util.*;
public class cluster_anlysis {
class ipdata{
float a,b;
int cluster;
ipdata()
{
a=0;
}
}
public float modc(float a){
if(a<0.0)
a=-a;
return a;
}
public static void main(String[] args) {
cluster_anlysis obj=new cluster_anlysis();
ipdata C[] = new ipdata[50];
float mean1,mean2,mean3;
int i,j,n1=0,n2=0,n3=0,flag=0;
float ina=0.0f;
float inb=0.0f;
//BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
Scanner scan =new Scanner(System.in);
System.out.println("pls enter no of data: ");
Integer no = scan.nextInt();
System.out.println("\nnow enter the x and y values");
for(i=0;i<no;i++)
{
ina=scan.nextFloat();
inb=scan.nextFloat();
System.out.println(ina);
C[i]= new ipdata(); // this line is giving error
C[i].a=ina;
C[i].b=inb;
C[i].cluster=0;
}
}
}
What could be the problem ?
it says :
No enclosing instance of type cluster_anlysis is accessible. Must qualify the allocation with an enclosing instance of type cluster_anlysis (e.g. x.new A() where x is an instance of cluster_anlysis).
you create an instance of inner class from static methods of your outer class using the outer class instance.
c[i]= new cluster_anlysis().new ipdata();
as you have alread created cluster_anlysis instance in your first line of main method.
cluster_anlysis obj = new Cluster_anlysis();
you could simple do.
c[i]= obj.new ipdata();
read about Inner classes in java
but if you want to create an inner class instance from the non-static methods of your outer class you dont need the instance of your Outer Class .
public class OuterClass {
public void method(){
InnerClass inner = new InnerClass();
}
class InnerClass{
}
}
and also follow class name convention as posted by #A.R.S and #JB Nizet in their solutions.
It seems you're starting with Java. I would advise to avoid messing with inner classes for the moment. Define each Java class in its own file, and everything will be simpler.
Also learn about Java naming conventions:
classes start with an upper-case letter, and are CamelCased: ClusterAnalysis, IpData. They should not contain underscores.
variables start with a lower-case letter, and are camelCased: c. They should not contain underscores.
Once you are more comfortable with the basics, learn about inner classes and static inner classes in the Java tutorial. But inner classes should not be abused. The basic rule is to have one class per file.
Use outer class Instance to call inner class constructor
like
c[i]=new cluster_analysis().new ipdata();
I think the best thing to do would be to declare ipdata as static; that would eliminate the error. There should be no need to instantiate cluster_analysis in order to instantiate ipdata in this case, and it makes sense that ipdata should in fact be static.
Oh, and by convention, you might want to consider using the names IpData and ClusterAnalysis instead - class names generally start with a capital letter and are "CamelCased", as another answer also pointed out.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why does Java prohibit static fields in inner classes?
I was going through the specification and got that it is not possible to have the static member in the inner class which is not final compile time constant .
class HasStatic {
static int j = 100;
}
class myInnerClassTest {
class Inner extends HasStatic {
static final int x = 3; // OK: compile-time constant
static int y = 4; // Compile-time error: an inner class
}
static class NestedButNotInner{
static int z = 5; // OK: not an inner class
}
interface NeverInner {} // Interfaces are never inner
}
Whereas I got from the Why can we have static final members but cant have static method in an inner class? that it can inherit the static member from its owner class. But why it shouldn't? What OOP's principal it hurts?
Your class myInnerClassTest isn't declared as static. So what would that exactly mean for it to have a static field ?
Would it be
the same for all instances whatever the enclosing instance ?
the same for all instances of this inner class having the same enclosing instance ?
At first sight most programmers would probably think it's the first case, while the encapsulation logic of the (non static) inner class should probably lead to the second choice. Either case (or both with different modifiers) would need a new definition of static which probably wasn't seen as necessary. And in either case programmers would be confused about the exact meaning.
From the specification :
An inner class is a nested class that is not explicitly or implicitly
declared static.
Inner classes include local (§14.3), anonymous (§15.9.5) and
non-static member classes (§8.5).
Inner classes may not declare static initializers (§8.7) or member
interfaces, or a compile-time error occurs.
Inner classes may not declare static members, unless they are constant
variables (§4.12.4), or a compile-time error occurs.
According to JLS: -
8.1.3 Inner Classes and Enclosing Instances
An inner class is a nested class that is not explicitly or implicitly
declared static. Inner classes may not declare static initializers
(§8.7) or member interfaces. Inner classes may not declare static
members, unless they are compile-time constant fields (§15.28).
Any local variable, formal method parameter or exception handler
parameter used but not declared in an inner class must be declared
final. Any local variable, used but not declared in an inner class
must be definitely assigned (§16) before the body of the inner class.
Apart from these two things, which I found important.. There are many more that you can get it from there.. There is a huge explanation about inner classes, anonymous inner classes, and nested classes..
UPDATED EXPLANATION : -
Just think about it. Static block is executed during class initialization, and you cannot initialize a non-static inner class without having an instance of the enclosing class, that's the reason.
Inner classes are associated with the instance of the enclosing class.. They are like other instance attributes of the enclosing class.. Now, it doesn't make sense to embed a static field in a non-static context.. However, if you declare them as Compile Time Constants they would be allowed.
NOTE: - static final Object = null is not compile time constants.. So, you can't have them inside your inner class
On the other hand, had your inner class been static, that is actually a nested class, then you can declare your field static, as they will still be associated with the class, so you can access them even before enclosing class in instantiated..
I hope that makes sense..
UPDATE 2 : -
public class A {
class B {
static int x = 0;
}
}
In the above code, static variable x will be common for every instance of class B..
Also, each instance of class A, will have it's own copy of class B (Since JVM will have to load class B every time an instance of A is created)..
So, static variable x could not have been shared between every instance of class A, unless it is a compile time constants.. (To make it more straight foreward: - You can do - B.x if you see B as outer class.. But class B is itself different for each instance of class A. So, B.x will be different for each instance of class A.. So, static variable x is not actually shared between different instances of class A.. Doesn't make sense for a static variable.)
I hope now, that makes sense..
All the restrictions are documented in
JLS #8.1.3. Inner Classes and Enclosing Instances
Because static declarations is associated with Class if you declare it inside inner class it will get associated with instance rather than class.
Non static inner classes are members of Object. And for members initialization only happens when instance of object is created. If static variables were allowed then initialization would have happened before creation of instance.
That is why there are separate non-static and static inner classes.
You always need outer class instance to access inner class Outer.Inner only exception is static inner class for which there are no constraints which are applicable to non-static inner classes.
static class Inner {
static final int x = 3; // OK: compile-time constant
static int y = 4;// OK
static class NestedButNotInner {// OK
}
interface NeverInner {// OK
};
}
However constants are permitted and it is documented in JLS
Because the inner class in intimately associated to the top level class you must have an instance of the outer class to create an inner via
Outer o = new Outer();
Inner i = o.new Inner();
This is therefore associated with an instance and not a class.
As you know, inner class can inherit static member from its owner class.
class HasStatic {
static int j = 100;
}
class myInnerClassTest {
class Inner extends HasStatic {
}
public static void main(String[] args){
System.out.println(Inner.j);
}
}
And it prints "100".