Accessibility of members of top level class in inner class? - java

I have a query regarding accessibility of top level class from member inner class.
I have just read the reason why local or anonymous inner classes can access only final variables.The reason being JVM handles these two classes as entirely different classes and so, if value of variable in one class changes, it can't be reflected at run time in another class file.
Then, my question is that how an inner member class (non-static) can have access to members to members of top level class, as JVM is still treating these two classes as different class files? If value of a member variable of top level class changes, how will it possible to reflect in class file of inner class at runtime?

They're separate classes, but there's an implicit reference to the instance of the "outer" class in the "inner" class. It basically acts as a variable which you can get at either implicitly or via special syntax of ContainingClassname.this.
Note that if you don't want such an implicit reference, you should declare the nested class as static:
public class Outer
{
private class Inner
{
// There's an implicit reference to an instance of Outer in here.
// For example:
// Outer outer = Outer.this;
}
private static class Nested
{
// There's no implicit reference to an instance of Outer here.
}
}

this is implicitly final, you cannot change it. When you write some thing like
class Outer {
int a;
class Inner {
{ a = 1; }
}
}
you are actually writing the same as
class Outer {
int a;
class Inner {
{ Outer.this.a = 1; }
}
}
The a is not final but the Outer.this is, and that is the reference which is used.

Related

is this a java compiler bug?

Compiler gives a compilation error that does not make sense.
"Cannot make a static reference to the non-static field x"
I do not make a static reference. A static inner class should have access to the private members of the enclosing class. In fact it does allow me to access super.x
I tried this with java 1.8
class Bug
{
private int x = 0;
int y;
static class BugDerived extends Bug
{
BugDerived()
{
super();
super.y = 1; // no error
y = 1; // no error
super.x = 1; // no error !
x = 1; // ERROR
}
}
}
No, a static method can only reference static fields or other methods. By calling super().x you reference a non-static property from a non-static context, which is allowed.
The following quote is taken from Oracle website.
Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private. Static nested classes do not have access to other members of the enclosing class.
The inner static class do not have access to members (private methods/variables) of the enclosing class.
Also look here:
a static nested class cannot refer directly to instance variables or
methods defined in its enclosing class: it can use them only through
an object reference. They are accessed using the enclosing class name.
A static inner class is linked to the outer class at class level, not instance level.
As a result, it can only access static members of the outer class, working in that respect identical to static methods.
Hence, this is not a compiler bug, it's expected behaviour.
When you use super.x, you're accessing the x data member from the instance of the superclass that underlies the instance of the nested class for which the constructor is being run, thus it does have access.

inner class access of enclosing class members

I will be amazed if anyone can answer this question. I am a beginner struggling immensely with the syntax and logic of nested classes in Java. If you run the following program, 'a' will print instead of 'b'. Why?
class MainClass
{
public static void main(String[] args)
{
Outer OuterRefVar_a = new Outer('a');
Outer OuterRefVar_b = new Outer('b');
OuterRefVar_a.InnerTypeMember = OuterRefVar_a.new Inner();
OuterRefVar_b.InnerTypeMember = OuterRefVar_a.InnerTypeMember;
OuterRefVar_b.InnerTypeMember.set_innerChar_to_outerChar();
System.out.println(OuterRefVar_b.InnerTypeMember.innerChar);
}
}
class Outer
{
char outerChar;
Outer(char outerChar)
{
this.outerChar = outerChar;
}
class Inner
{
char innerChar;
void set_innerChar_to_outerChar()
{
innerChar = outerChar;
}
}
Inner InnerTypeMember;
}
That happens because while you have set the InnerTypeMember reference of object of A onto B..
OuterRefVar_b.InnerTypeMember = OuterRefVar_a.InnerTypeMember;
The inner object of A still has a reference to it's original Outer object A and will reference its member variables. Java implements inner classes by giving the object a secret reference to "Outer.this" which doesn't change simply by setting the InnerTypeMember on the other instance.
For example, if you had a InnerTypeMember variable within a completely different class, calling set_innerChar_to_outerChar() would still be expected to find Outer.outerChar on the object for which the inner class was original constructed.

What is the exact meaning of instantiate in JAVA

I'am a newbie in JAVA and this came across this word called.
"A class i.e. created inside a method is called local inner class in java. If you want to invoke the methods of local inner class, you must instantiate this class inside the method".
The word in bold.
Can anyone please help me out with this one.I know it's embarrassing and i should've researched more but I just cannot understand.
Thanks.
First of all Declaring mean:
ClassName obj;
Simple meaning of instantiate is creating an object from class.
ClassName obj = new ClassName();
What is a object?
An instance of a class. From one class we can create many instances.
They are the basic runtime entities in in our program.
They may also represent user-defined data types such as lists and
vectors.
Any programming problem is analyzed in terms of objects and nature of
communication between them.
As a example:
//Define a reference(a variable) which can hold a `Person` obect.
Person p;
//Create a Person object(instantiate).
//new - use to allocate memory space for the new object
p = new Person();
What is a nested class?
A class that defined inside a class is called nested class. There 2 categories of nested classes.
inner classes
local classes
annonymous classes
Inner class:
Inner class can only be accessed by the outer class. Not by any other
class.
Inner class is a member of outer class.
Outer class can access inner class without importing.
Inner class can access any attribute or a method belong to outer
directly.
Outer class cannot access directly to a inner class.
Example for a inner class:
class Outer{
int i = 10;
void main(){
//instantiate inner class.
Inner in = new Inner();
in.show();
}
class Inner{
void show(){
System.out.print(i);
}
}
}
What is a local class?
Which are classes that are defined in a block.
Example:
public class{
int i = 10;
public main(){
class A{
void show(){
System.out.println(i);
}
}
//inside the method instantiate local class.
A obj = new obj();
obj.show();
}
//outside the main() -block(method)
//inside another method instantiate local class.
public test(){
A obj = new A();
obj.show();
}
}
To instantiate a class means to create an instance of the class. In other words, if you have a class like this:
public class Dog {
public void bark() {
System.out.println("woof");
}
}
You would instantiate it like this:
Dog myDog = new Dog();
Instantiating is when you use the new keyword to actually create an object of your class.
Instantiate == create an instance == create an object of a class.
Instantiate is creating an instance of a class. I reckon this is not helpful without knowing what an instance is.
Let's say you have a class definition like:
public class Person
{
private String name;
public Person(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}
You make an instance of this class my calling its constructor and using the keyword new:
Person p = new Person("Hugh Laurie");
An instance of a class is a place in memory that contains the state (e.g., Person::name) of a given object which used as a template a class definition.
I want to further expand upon:
If you want to invoke the methods of local inner class you must instantiate this class
What this means is that, you need to have instantiated that class in order to use the above's example getName() method. After all, it is trying to access the state (name) of a given object in memory; without that object, there is no state.
Instantiate in Java means to call a constructor of a Class which creates an an instance or object, of the type of that Class. Instantiation allocates the initial memory for the object and returns a reference. An instance is required by non-static methods as they may operate on the non-static fields created by the constructor.
Static methods don't need an instance and should not be stateful, i.e. should not rely on changing data. They are essentially free functions that are associated with the type and not a particular instance. When you want to work with changing data, encapsulating that data as member fields that are operated on by instance methods is the way to go.
For example, a Car class might have static numbeOfWheels() that always returns 4, but an instance numberOfFlatTires() that might return 0-4 depending on the state of that particular Car.
Inner classes are no different and the only difference between a static and non-static inner class is that the non-static can use the parent instance's members. This can be used to reduce complexity. You might have a looping operation that has a common parameter for the list and an individual parameter for the items. You could use a non-static inner class to encapsulate the operations on the item while referring to the common parameter in the parent class.
Enums are special in that each value is a single instance of a single type that all extend from a common abstract base class defined in the Enum class body. The Enum value is instantiated the first time it's used, but there will only ever be one instance per value.
when you create an instance of a class or simply called as an object
for ex: Bike abc = new Bike();
as soon as you create this object using the new keyword, a new block of memory is created and object "abc" will now be pointing to that new block of memory, this is called as instantiation in java.
create an instance of the class by using "new" word
for example Car car = new Car();

What does it mean if a variable has the name "this$0" in IntelliJ IDEA while debugging Java?

I am trying to understand this Functional Reactive Java library by running a test called testSendStream in debug mode and stepping through the code as the test executes.
The snapshot above shows that there is an oddly named variable called this$0.
Where does this name come from ?
What does this name mean ?
Why does this variable has this name ?
What is the reasoning behind giving it this name?
Surely this name does not come from the code itself, it is generated by IntelliJ or javac/java. But why ?
It is also interesting to see what happens if I mark this object by the label Mystery Object.
this$0 is "hidden field" in Inner class (the non-static nested class) which is used to hold reference to instance of Outer class which was used to create current instance of Inner class.
In short when you have
Outer outer = new Outer();
Outer.Inner inner = outer.new Outer.Inner();
Inner instance held by inner will store in its this$0 field reference to Outer instance used to create it (same reference as held by outer variable).
It is necessary because nested classes must have access to all members of outer classes (including private ones). If we want to be able to write something like methodFromOuterClass(); in inner class JVM needs to know on which Outer instance it should invoke this method. To make it possible compiler "changes" such code to this$0.methodFromOuterClass().
Little more details and example:
public class Outer {
private int id;
public Outer(int id) { this.id = id;}
public class Inner{
void printOuterID(){
System.out.println(id);
}
}
}
Now what will be printed here and why?
Outer o1 = new Outer(1);
Outer o2 = new Outer(2);
Outer.Inner in1 = o1.new Inner();
Outer.Inner in2 = o2.new Inner();
in1.printOuterID();
in2.printOuterID();
We will see
1
2
but how in1 knew that it should print value of id from o1 and not from o2?
It is because each instance of inner class knows on which instance of outer class was it created. And that is because of this$0 reference which stores reference to outer instance used to create inner instance.
This variable is added to all non-static inner classes by compiler and its value is set when you invoke
Outer.Inner in1 = o1.new Inner(); //`this$0` will be set to hold `o1` instance.
So code like
void printOuterID(){
System.out.println(id);
//OR
//System.out.println(Outer.this.id);
}
is compiled into
void printOuterID(){
System.out.println(this$0.id); //although we can't access this$0 explicitly
}
BTW if your inner class doesn't need to access non-static members of any of its outer classes you may change it to static class which will get rid of this$0 field.
The is a convention related to non static inner classes. The bytecode of the inner class will contain a reference to a package-scoped field named this$0 that allows you to refer to the this object of the enclosing class. Notice in your example this$0 is the same as the Mystery Object this variable defined above it.

What is wrong with an inner class not using an outer class in Java?

I'm using a static analyzer in Eclipse to examine my code. One class, foo, has an inner class, bar. I am getting the following error:
JAVA0043 Inner class 'bar' does not use outer class 'foo'
Why is this an error? As long as the outer class uses the inner class isn't that sufficient to make this information hiding useful and correct?
The inner class is not static.
Looks like an Enerjy Error:
// Incorrect
class Log {
// Position never uses the enclosing Log instance,
// so it should be static
class Position {
private int line;
private int column;
Position(int line, int column) {
this.line = line;
this.column = column;
}
}
}
A nested class that does not use any instance variables or methods from any of its outer classes can be declared static.
This reduces the dependency between the two classes, which enhances readability and maintenance.
// Correct
class Log {
static class Position {
private int line;
private int column;
Position(int line, int column) {
this.line = line;
this.column = column;
}
}
}
If the inner class can only ever be used by the outer class, yet the inner class needs no reference to the outer class, then you can make it private static.
If the inner class is known to someone other than the outer class, then it might as well be a top-level class in its own right.
If it's not making any reference to the outer class, it might as well be a full-on, regular class. Since it isn't dependent on the outer class, it can stand on its own. I suspect that's the reason for the "error".
A non-static inner class has an implicit reference to an instance of its outer class. This hidden reference can delay (or even prevent) garbage collection on the outer class and create serialization issues. So you should only use non-static inner classes when you need them. It is easy to forget to declare the class static, so the code analysis warns you when it isn't needed.
The whole point of the inner class is that it has access to the outer class. If you're not actually using the outer class, just make it a regular, full-blown class.

Categories

Resources