Every non-static nested class keeps a reference to its outer class for the purpose of accessing the outer class's methods and fields.
Given this class...
class Parent
{
// some fields
// some methods
protected class NestedParent
{
// some other fields
// some other methods
}
}
... and this class:
class Child extends Parent
{
// some fields
// some methods
protected class NestedChild extends NestedParent
{
// some other fields
// some other methods
}
}
The class NestedParent has a reference to its outer class Parent; because NestedChild inherits from NestedParent it will have that reference, too. However, will NestedChild also have a separate reference to Child or will it use the inherited reference and cast it to Child for accessing Child's members?
I ask this question because I am trying to figure out the final size of NestedChild. If it has one additional reference of 4 bytes this is a big waste of memory in the project I am working in since there will be millions of instances of NestedChild.
Your understanding is little wrong as every Child class instance is of type Parent class and so Child class instance is the outer enclosing class for NestedChild
The NestedChild class will have a reference to Child instance only,so no issue of memory here.Java works by reference and not by actual Object unlike C(there is no concept of pointers,only references).The Child instance holds reference to Parent Class members(see the Object graph).
Object references are part of the Object heap and class definition lies in method area.
EDITED FOR CLARITY:-
Try commenting out "extends Parent" from Child,you would see that compiler complains that no enclosing object of type Parent is present for NestedChild inner class.
Related
When we create a child object, single object is created of child class which uses parent class variables. this is my understanding. I have read on many places that super refer to parent class object but here only one single object is created which inherits its members from parent class.
Does a parent class object is implicitly created inside child one to which super refers to?.I dont exactly get how people have written and in which context that it refer to parent class object ? when only child class object is created singly.
Have a look there for super meaning and use.
https://docs.oracle.com/javase/tutorial/java/IandI/super.html
Basically, you can see any object as an onion with the inner peel being Object and the outer one your object's class, with all the super classes in between. Each peel comes with its own attributes, class (overloaded, overridden, or new) and constructors (same) but the whole thing is a single object, each peel only seeing toward the inner core (except for overriden methods that are called to their outmost overriding peel - i.e. a method implementation that does not exist yet at the the considered peel declaration : see https://pretagteam.com/question/calling-an-overridden-method-superclass-an-calls-overridden-method)
If your method overrides one of its superclass's methods, you can invoke the overridden method through the use of the keyword super.
You can also use super to refer to a hidden field (although hiding fields is discouraged).
You can also use super(...) to invoke a specific superclass constructor (whether it is not public or need to be called with specific parameters)
My interviewer asked me about inner classes.. After explaining him everything he stopped me on my one sentence- if inner classes can access private members of outer class then doesn't it violate privacy?
I was unable to answer it.
From a JVM perspective, yes, an inner class accessing a private member of the outer class violates privacy.
But, from a Java perspective, no, it does not violate privacy.
JVM perspective
The Java Virtual Machine Specification, section 5.4.4. Access Control says:
A field or method R is accessible to a class or interface D if and only if any of the following is true:
[...]
R is private and is declared in D.
So, the JVM will only allow private members to be accessed from code in the same class, i.e. a nested class cannot access private members of the outer class.
Java perspective
The Java Language Specification, section 6.6.1. Determining Accessibility says:
A member (class, interface, field, or method) of a reference type, or a constructor of a class type, is accessible only if the type is accessible and the member or constructor is declared to permit access:
[...]
Otherwise, the member or constructor is declared private, and access is permitted if and only if it occurs within the body of the top level class (ยง7.6) that encloses the declaration of the member or constructor.
So, a private member in a top-level class and/or nested class is accessible from code anywhere within that top-level class. Since nested classes by definition occur within the body of the enclosing top-level class, code in nested classes can access private members of the outer class.
Synthetic access
To solve the discrepancy, the Java compiler creates hidden (synthetic) methods for allowing "private" access between closely related classes, i.e. between a top-level class and all its nested classes.
This is an internal trick of the compiler and is not really documented in the specifications. JVMS, section 4.7.8. The Synthetic Attribute says:
[...] A class member that does not appear in the source code must be marked using a Synthetic attribute, or else it must have its ACC_SYNTHETIC flag set. [...]
The Synthetic attribute was introduced in JDK 1.1 to support nested classes and interfaces.
For more information, do a web search for java synthetic accessor.
See also: Synthetic accessor method warning
Answer is No as inner class is part of the outer class, just like other variable and methods are
All private variable/method of a class can be accessed inside all methods of the same class. An inner class is a special case where an instance of InnerClass can exist only within an instance of OuterClass. Hence it has direct access to the methods and fields of its enclosing instance.
The answer is NO, because inner class has internal link to the outer class and inner class does not exists without concrecte instance of outer class.
But if you add static to the inner class declaration, it means the it does not have link to the outer class and this is the same, when you declare class in it's own file.
That is all, clear and simple.
If you look closely at statement#1 and #2, you will find that the only difference between them is of one extra object (of inner class) that gets created in #1, rest everything access-wise is exactly same.
There is no violation because somewhere you're intentionally leaving the door open through some form of access specifier like public or protected. Inner class doesn't act (or is not capable to act) as a workaround in there, so no violation absolutely.
public class AccessPrivateMemberThruInnerClass {
private int getUniqueId() {
return 101;
}
private class AnInnerClass {
public int getParentID() {
return getUniqueId(); // invokes private method inside a public method.
}
}
public int getUniqueIdForce() {
return getUniqueId(); // invokes private method inside a public method.
}
public AnInnerClass getInnerClassObject(){
return new AnInnerClass();
}
public static void main(String[] args) {
AccessPrivateMemberThruInnerClass obj = new AccessPrivateMemberThruInnerClass();
System.out.println(obj.getInnerClassObject().getParentID()); // #1
System.out.println(obj.getUniqueIdForce()); // #2
}
}
Answer : No inner class does not voilate the privacy of outer class.
Explanation : All instance methods defined in a class are able to access the private or not private fields and methods defined in the class. This happens as all the instance methods and fields belong to the current object of the class.
Same is true for any inner (non static) class, it has an implicit reference of outerclass current object.
This is the reason as why you can only create the object of inner (non static) class with the help of an object of outer class. If you create the object of inner class inside any instance method of outer class then it is created with the help of implicit current object reference of the outer class.
If you have inner class which is static, then it does not has implicit reference to current object of outer class. Any instance field or method belong to an Object of the class. Hence static inner class can not access any private or non private instance field or method of outer class.
You can set reference of outer container class object explicitly and then it can acess. Now with the help of this explicitly set reference of outer class you can access the private Fields and methods.
So now lets modify the question as why inner static class with an explicit reference of outer class can acess and modify private methods and fields ?
Answer is related to our decision for having such design. The intention of defining any entity within the scope of a class is belongingness. If belongingness is missing then you should reconsider your decision lf making the class as inner (static or non static). Inner classes should be made when we wish to encapsulate a sub responsibility to an entity. This makes the related responsibility still cohesive.
Iterator is a part of any Collection and hence it is inner class. Custom AsyncTask class defined in custom Activity class in android is often made as private static (with weak reference of outer class activity) to prevwnt activity leak as the intention is to modify the fields which are private.
P.S : Afer compiler compiles the code it generates separate files for inner class and you can refer the link to understand as how the interaction of fields of one class being accessible to other class happens when other class is defined as inner class
https://stackoverflow.com/a/24312109/504133 . Actually synthetic getters and setters are injected in the code by compiler so as nested static class can access private fields using these. But still this is backend task done by langauge tools.
class One{
}
class Two extends One{
}
class Main{
public static void main(String[] args){
Two t = new One(); // invalid
}`
}
I am not able to understand the reason behind it, why child class reference could not hold the object of parent, while superclass reference can hold the object of subclass.
Because a dog has all the behaviours of an animal, but something that is only known to be an animal is not guaranteed to have all the behaviours of a dog.
Every Child is a Parent but not every Parent is a Child. Rule of Inheritance.
If we think in terms of set theory, compared to the parent class, the child class is a super set.
The child class has all possible properties and methods, compared to the parent class.
So, a parent class object can refer to its child class object, as the child class object includes the parent's methods and properties.
Thinking vice versa, since a parent class object does not have all the methods and properties needed by a child class, a child class object cannot refer to a parent class object.
The type of TWO cannot be an instance of ONE because there are members and methods that TWO has which ONE doesn't have. However, The type of ONE can reference TWO because TWO has everything that ONE has.
For example, if ONE can WALK and TWO can also RUN, then if you have an object from the type ONE then is needs to be able to WALK. So if ONE references TWO that works because TWO can walk.
But when you have an object of type TWO then it needs to be able to RUN so you cannot reference it to ONE which cannot RUN.
Consider class Two contain a method, let say demo().
class One{
}
class Two extends One {
void demo(){
System.out.println("in Two");
}
}
class Main{
public static void main(String[] args){
Two t = new One(); // Suppose this is valid at compilation time
t.demo();
}
}
Now suppose if compiler doesn't give us error when we create object of class One i.e. child reference holds object of parent. Further t is reference of class Two, hence t.demo() is valid.
Now when program runs, reference t contains object of class One. When program reaches t.demo() then t contains object of class One and class One does not have any method named demo().
So to prevent such type of errors compiler checks if object is type of reference i.e. object class is same as reference class or child of reference class.
In Java inheritance we can access parent class properties via the child class object, as there is a keyword extends for achieving inheritance. But my question is that we can access any class non-static Data Member or methods via that class object reference only, so in case of inheritance we make child class object and access parent property so as java rule we can access any DM(Data Member) via that class object only so in this case according to me two possibilities are there:
When inheritance is taking place all the Data Member or Member Function are first copied into child scope and then we use them because now they are properties of Child so easily accessible but in this case same DM and methods are in both, child memory as well as in parent memory. That is not a good approach because if I have 100 properties in parent than all 100 are first copied into child memory and then used.
As we make child object implicitly the parent class object is made by compiler and all parent class method are called via that parent class object implicitly, but according to me that is not done. There is no object creation of parent in case of inheritance in Java. You can also check this via printing ref in child class as well as on parent class both have same reference so no parent object is created.
So my question is, how properties of parent are access via child object implicitly means internally how they achieve or is there any third approach for achieving the same used in java.
Just like the word "extends" implies, the child object is an extension of the parent object. in other words, it has all the data members of the parent, plus what other data members the child adds. If the memory layout of parent object is
PPPPPP
then the child object looks like this:
PPPPPPCCCCC
When you consider your option (2), you say: "there is no object creation of parent". That is true and false at the same time. There is no separate instance of parent class, distinct from the instance of child class you're making. However, the parent instance does exist as a PART of child instance, and the parent CONSTRUCTOR is indeed called before the child constructor to initialize that part.
(Java question)
If I reference a field in an inner class, does this cause a circular dependency between the enclosing class and the inner class?
How can I avoid this?
Here is an example:
public class Outer {
private Other o;
private Inner i;
public Outer() {
o = new Other();
i = new Inner() {
public void doSomething() {
o.foo();
}
};
}
}
Static vs instance class: If you declare the inner class as static then the instances of the inner class doesn't have any reference to the outer class. If it's not satic then your inner object efectivelly points to the outer object that created it (it has an implicit reference, in fact, if you use reflection over its constructors you'll see an extra parameter for receiving the outer instance).
Inner instance points outer instance: Circular reference is in case each instance points the other one. A lot of times you use inner classes for elegantly implementing some interface and accessing private fields while not implementing the interface with the outer class. It does mean inner instance points outer instance but doesn't mean the opposite. Not necesary a circular reference.
Closing the circle: Anyway there's nothing wrong with circular referencing in Java. Objects work nicely and when they're not more referenced they're garbage collected. It doesn't matter if they point each other.
The syntax you're using in the example is a little off there is no declaration of the class or interface Inner. But there isn't anything wrong with the concept of the example. In Java it will work fine.
I'm not sure what you're doing here, but you may want to consider a more simple design for maintainability etc.
It's a common pattern for anonymous event handlers to reference elements of their parent class, so no reason to avoid it if that's the case, that's how Java was designed instead of having function pointers.
(Not sure if this is what you are asking...)
At runtime, the inner class has an implicit reference to the instance of the outer class it belongs to. So whenever you pass the inner class instance around, you are also passing the outer class instance around.
You can avoid that by declaring the inner class as "static", but that means that the inner class can't access member variables of the outer class. So in that case if you want to access a member of the outer class, you need to pass it explicitly to the inner class (using a setter or using the constructor of the inner class).