Inner class construction in Java - java

I've read about class fromal parameters and the question then arises as to why the following code is ill-formed?
class A:
package org.gradle;
public class A extends B.Inner{
public A(B s){
s.super(new B()); //error
s.super(); //OK
}
}
class B:
package org.gradle;
public class B{
public class Inner{
}
}
The key part of what was said is:
The constructor of a non-private inner member class implicitly
declares, as the first formal parameter, a variable representing the
immediately enclosing instance of the class
So, I expect that besides the default constructor, we should have a constructor with the following signature:
Inner(B b);
Why not?

The "extra" parameter is effectively hidden from you - both when you declare it, and when you execute it. When you execute it, you provide a value in a different way - in your case, via s:
s.super();
That's passing s as the hidden extra argument to the B.Inner constructor. The syntax for all of this is a little weird - and I would personally try to avoid using inner classes in this sort of situation... they just get weird very quickly. I usually prefer static nested classes, and if I do need an inner class, it's almost always private. Subclassing an inner class declared in a different top-level class is an odd situation, IMO.

You are already passing the enclosing instance s (of class B) to the constructor of the inner class when you call s.super(), so there's no need to pass another instance of B.
The variable representing the immediately enclosing instance of the class is an implicit parameter, and it is passed to the constructor using a special syntax.

Related

Why exactly does the no-arg constructor of parent class get invoked while creating an instance of child class? [duplicate]

I have a question about inheritance in Java.
I have two classes A and B , and class B, inherits from A:
public class A {
public A() {
System.out.println("Hi!");
}
}
public class B extends A {
public B() {
System.out.println("Bye!");
}
public static void main(String[] args) {
B b = new B();
}
}
When I run program B, the output is:
Hi!
Bye!
Question : why the constructor of class A is invoked, when I create and object of class B ?
I know that B inherits everything from A - all instance or class variables, and all methods, and in this sense an object of B has all characteristics of A plus some other characteristics defined in B. However, I didn't know and didn't imagine that when I create an object of type B, the constructor of A is also invoked.
So, writing this:
B b = new B();
creates Two objects - one of type B, and one of type A.
This is getting interesting,
can somebody explain why exactly this happens?
It doesn't create two objects, only one: B.
When inheriting from another class, you must call super() in your constructor. If you don't, the compiler will insert that call for you as you can plainly see.
The superclass constructors are called because otherwise the object would be left in an uninitialized state, possibly unbeknownst to the developer of the subclass.
Your subclass actually looks like this after the compiler inserts the super call:
public class B extends A {
public B() {
super();
System.out.println("Bye!");
}
}
It doesn't create 2 objects, it only creates one instance of B. The reason the super class constructor is invoked is because, like you said, B has all of the fields of A, and these fields need to be initialized.
Remember inheritance is an "is a" relationship between the base class and the subclass, thus every time you have an instance of a subclass, by definition you will also have an instance of the base class (as part of the instance, not as two separate instances). To initialize the base class properly the constructor is called.
Additionally, think about what would happen if you subclass depended on some internal state of the base class. Wouldn't you want the instance of the base class to be initialized then?
This is done because the constructor is used to initialize the object. Since B is also an A, it calls the constructor for A first, then the constructor for B.
As a side note, you can use super(arg1, etc) to choose which constructor of A is called based on the parameter types you pass... but it must be the first line in the constructor.
The constructor contains all of the initialization for A. You are not creating two objects. You are creating one object, then running the initializer for the superclass to initialize its members, and then running the initializer for the deriving class to initialize its members.
It does not create two objects, it just creates one object b. b is of type B and of type A. A constructor is basically saying here is what you need to do to construct me. So when you are creating a new "B" instance, you are building an object that is both a B() and an A(). Imagine the following scenario:
class Q {
int i;
public Q() {
// set default value
i= 99;
}
}
class Z extends Q {
public Z() {
}
}
If the constructor for Q WAS NOT called, how would i get its default value?
The creation of B does not create an extra A.
But by creating B, you create a kind of A, because B is a A.
Java/C++ call the constructor of A for your implicitly. Why? Language design. But doing so is fine, because the constructor of A might contain some initializations. And as B uses all the features and bugs of A, these features better be initialized properly.
The constructor of a class is very important concept in most OOP
Classes, by providing state and the means to manipulate that state, allow the easier maintenance of invariants. The constructors role is to get the class into a state that conforms to those invariants (or throws thus forbidding usage of an invliad object).
this is somewhat looser than intended in many languages since the constructor is allowed to pass its own 'this' reference elsewhere but this is at least under the control of the class (as such it can know that it is in a sufficiently stable and valid state for it to be accessible to the rest of the world)
Inheritance makes this complex since B is-a A in a very real sense and thus can invoke any of the methods provided by A. The parts of B that are A should therefore get their chance to initialize themselves before B gets a look in, thus the constructor for A is called before the real work of the B constructor begins.
If A intializes members in it's constructor and you forget to call super in your derived class then the members of A could be in a bad state. Java is trying to stop you from shooting yourself in the foot.
Only one object is created, both contractors are running on the same object.
The reason is simple, as you know B has all the variables and methods of A, so if some variable of A needs initializing so methods of A can work someone has to initialize it - and that someone is A's constructor.
for example:
public class A {
public A() {
x = 1;
}
private int x;
public int getX() {
return x;
}
}
public class B extends A {
public B() {
}
public static void main(String[] args) {
B b = new B();
System.out.println(b.getX()); // should print 1
}
}
When new object is create(B), inside B A object is created(because of extends keywords) . In B class JVM search B class constructor, but due to extends keywords it goes to super class constructor. inside A class x value is initialized. But x is private so that we can access outside class throw getXxx() method and get the result.
When sub class object is created then internally it was not created for super class object.But the memory should be allocated for super class members.
In java when you create an object of child class the constructor of parent class is always called because Object class is the parent of every super class and when you call the constructor of Object class then only your object is created and java does not support multiple inheritance in case of class so if you extends any other class then the relationship between you child class and the Object class is through the Parent class so to call the constructor of the Object class the constructor of Parent class must be called.
Every superclass has a constructor and each constructor up the hierarchy runs at the time an object of a subclass is created.
if super class object is not created then how sub class is accessing super class non static methods and variables.
I studied that non-static methods and variables can be accessed only through objects..

Why can't we get access from the inner's class constructor to another inner class?

class Main
{
public static void main (String[] args) throws java.lang.Exception
{
}
public class SuperInner{
int a;
}
public class Inner{
public class MegaInner{
public MegaInner(){
Main.SuperInner.this.a = 6; //error: not an enclosing class: Main.SuperInner
}
}
}
}
IDEON
What JLS says is:
Let C be the class denoted by ClassName. Let n be an integer such that
C is the n'th lexically enclosing class of the class in which the
qualified this expression appears.
[...]
It is a compile-time error if the current class is not an inner class
of class C or C itself.
In the case C:=Main, the set of inner classes S := {SuperInner, MegaInner, Inner}. Which means the code above should work fine. What's wrong?
One could have multiple instances of SuperInner, as well as of Inner or MegaInner.
Calling Main.SupperInner.this.a from within MegaInner, it wouldn't be clear which instance (if there is an instance at all) should have the a variable set to 6.
The inner classes behave much like normal classes: one always needs an instance to set a variable in them. Main.SuperInner.this does not denote an instance from MegaInner's view, as this only refers to the class-hierarchy of MegaInner, which SuperInner is not a part of.
The "Qualified this" expression Main.SuperInner.this.a appers inside MegaInner.
The enclosing classes of MegaInner are Inner and Main. So this is the 0th qualified this, Inner.this is the 1st qualified this, and Main.this is the 2nd qualified this.
The part you were missing is that it has to be an enclosing class of the class where the expression with the this appears. SuperInner is not an enclosing class of MegaInner and therefore the Qualified this does not apply to it.
Think about it in reality. A this expression refers to an instance of the class. It does not refer to the class itself. You cannot refer to this from a static method, for example.
Now, when you create an instance of MegaInner, it has to be part of an actual instance of Inner and an actual instance of Main. But there is no guarantee that there is an actual instance of SuperInner. The code of the enclosing classes may create objects of type SuperInner at any time and independently of instances of Inner.
Thus, you can't access a this of it at compile time. But if you are given an instance of it through a reference variable, you are allowed to access the variable a, as they are all members of the same outer class.

Eclipse showing two THIS$0 fields for a nested class (Java)

I have been facing an odd phenomena that I don't quite understand. I have an abstract class that is extended by several other classes. the abstract class is a type of special collection and it has a nested abstract iterator class that fits it. Every class that extends the abstract collection class, also has a nester iterator class that extends the orginal abstract iterator.
The abstract class is something like this:
public abstract class AbstractMultiCollection<T> {
public AbstractMultiCollection() {
...
}
MultiIterator<T> iterator();
public abstract class AbstractMultiIterator {
public AbstractMultiIterator() {
...
}
The extending classes are something like this:
public class MajorityMultiCollection<T> extends AbstractMultiCollection<T> {
...
public MultiIterator<T> iterator() {
return new MajorityIterator();
}
...
public class MajorityIterator extends AbstractMultiIterator {
public MajorityIterator() {
super();
...
}
public T next() {
...
}
Simply put, the collections extend the abstract collection and their nested iterators extend the nested abstract iterator.
I have two problems that I don't understand and would appreciate clarification on:
When I debug my code, the "return new MajorityIterator();" lines raise a "Source Not Found" error and "ClassNotFound" exception in the eclipse debugger and a bunch of "ClassLoaderExt" exceptions that I don't understand.
I noticed that every "MajorityIterator" has two "This$0" fields, containing the collection he belongs to. one is null at first, but receives the collection once I invoke the "super();" builder.
I failed to find the reason for this, can anyone clarify? Thanks in advance!
Actually having two this references makes sense. One thing most people do not realize is how the Java compiler implements non-static nested classes:
It implicitly adds a new field with the type of the outer class, lets call it outer$object.
It implicitly adds a new argument for the outer class object to all constructors to fill in that field. Incidentally, that means that the default constructor of the inner class actually has a parameter, which makes using it via reflection significantly more complex.
It implicitly creates constructors and methods with wider visibility to get around any accessibility issues if e.g. the inner class is declared private.
Since the outer$object field needs to have the same type as the outer class, one will be added each time a nested class inherits from a class that is not nested within the same outer class.
Personally, I tend to avoid non-static non-anonymous inner classes, in order to keep everything explicitly on the surface, rather than let the compiler make a mess out of things...
A MajorityIterator object will indeed have two this$0 fields:
One (implicitly declared in MajorityIterator) for the reference to the enclosing instance of MajorityMultiCollection
One (implicitly declared in AbstractMultiIterator) for the reference to the enclosing instance of AbstractMultiCollection. This will be null until the super() call, as it'll be set in the constructor.
You might find it clearer to make these static nested classes, and explicitly pass in the reference to the enclosing instance instead - I suspect you only want one reference, and it'll be simpler to reason about.

A call to a static method within the parameter list of super() is valid in Java. Why?

Let's look at the following code snippet in Java.
package trickyjava;
class A
{
public A(String s)
{
System.out.println(s);
}
}
final class B extends A
{
public B()
{
super(method()); // Calling the following method first.
}
private static String method()
{
return "method invoked";
}
}
final public class Main
{
public static void main(String[] args)
{
B b = new B();
}
}
By convention, the super() constructor in Java must be the first statement in the relevant constructor body. In the above code, we are calling the static method in the super() constructor parameter list itself super(method());.
It means that in the call to super in the constructor B(), a method is being
called BEFORE the call to super is made! This should be forbidden by the compiler but it works nice. This is somewhat equivalent to the following statements.
String s = method();
super(s);
However, it's illegal causing a compile-time error indicating that "call to super must be first statement in constructor". Why? and why it's equivalent super(method()); is valid and the compiler doesn't complain any more?
The key thing here is the static modifier. Static methods are tied to the class, instance methods (normal methods) are tied to an object (class instance). The constructor initializes an object from a class, therefore the class must already have been fully loaded. It is therefore no problem to call a static method as part of the constructor.
The sequence of events to load a class and create an object is like this:
load class
initialize static variables
create object
initialize object <-- with constructor
object is now ready for use
(simplified*)
By the time the object constructor is called, the static methods and variables are available.
Think of the class and its static members as a blueprint for the objects of that class. You can only create the objects when the blueprint is already there.
The constructor is also called the initializer. If you throw an exception from a constructor and print the stack trace, you'll notice it's called <init> in the stack frame. Instance methods can only be called after an object has been constructed. It is not possible to use an instance method as the parameter for the super(...) call in your constructor.
If you create multiple objects of the same class, steps 1 and 2 happen only once.
(*static initializers and instance initializers left out for clarity)
Yep, checking the JVM spec (though admittedly an old one):
In the instance init method, no reference to "this" (including the implicit reference of a return) may occur before a call to either another init method in the same class or an init method in the superclass has occurred.
This is really the only real restriction, so far as I can see.
The aim of requiring the super constructor to be invoked first is to ensure that the "super object" is fully initialized before it is used (It falls short of actually enforcing this because the super constructor can leak this, but that's another matter).
Calling a non-static method on this would allow the method to see uninitialized fields and is therefore forbidden. A static method can only see these fields if it is passed this as argument. Since accessing this and super is illegal in super constructor invocation expressions, and the call to super happens before the declaration of any variables that might point to this, allowing calls to static methods in super constructor invocation expressions is safe.
It is also useful, because it allows to compute the arguments to the super constructor in an arbitrarily complex manner. If calls to static methods weren't allowed, it would be impossible to use control flow statements in such a computation. Something as simple as:
class Sub extends Super {
Sub(Integer... ints) {
super(Arrays.asList(ints));
}
}
would be impossible.
This is one situation where the java syntax hides what's really going on, and C# makes it a bit clearer.
In C# your B would look like
class B : A {
public B() : base(method()) {
}
private static String method() {
return "method invoker";
}
}
Although the java syntax places super(method) within the constructor it's not really called there: All the parent initialization is run before your subclass constructor. The C# code shows this a little more clearly; by placing super(method()) at the first line of the java constructor you're simply telling java to use the parameterized constructor of the super class rather than the parameterless version; this way you can pass variables to the parent constructor and they'll be used in the initialization of the parent level fields before your child's constructor code runs.
The reason that super(method()) is valid (as the first line in a java constructor) is because method() is being loaded with the static elements--before the non-static ones, including the constructors--which allows it to be called not only before B(), but before A(String) as well. By saying
public B() {
String s = method();
super(s);
}
you're telling the java compiler to initialize the super object with the default constructor (because the call to super() isn't the first line) and you're ready to initialize the subclass, but the compiler then becomes confused when it sees that you're trying to initialize with super(String) after super() has already run.
A call to super is a must in java to allow the parent to get initalized before anything with child class starts.
In the case above, if java allows String s= method(); before the call to super, it opens up flood gate of things that can be done before a call to super. that would risk so many things, essentially that allows a half baked class to be used. Which is rightly not allowed. It would allow things like object state (some of which may belong to the parent) being modified before it was properly created.
In case of super(method()); call, we still adhere to the policy of completing parent initialization before child. and we can use a static member only, and static member of child classes are available before any child objects are created anyways. so the method is avilable and can be called.
OK..i think, this one could be relevant that, if we are calling some member with Super, then it first try to invoke in super class and if it doesn't find same one then it'll try to invoke the same in subclass.
PS: correct me if i'm wrong

How does this object get created?

Many articles say objects get created only after the class's constructor gets called. But I found this snippet and it works fine.
public class A {
public A(){
this.foo();//line #1
}
private void foo() {
System.out.print("without an instance..!!!!");
}
}
class B extends A
{
public static void main(String[] args){
A a = new A(); //line #2
}
}
Here you see, I'm trying to create an object of its super class in line #2 and in its constructor how come its method got called without an instance. What's going on here, is Constructer of instance of A is getting called here.?
The constructor is always called when an object is created. Even if you don't explicitly define a constructor, the compiler will generate one for you with an empty body.
You may call other methods of the class from the constructor. All non-static methods get an implicit (compiler generated) parameter to this, the actual class instance. However, it is important to know that while executing the constructor, the object is not yet fully created, although all data members of the class in question (if there are such) have already been initialized, at least to some default value. Because of this, you
should not publish this (i.e. pass it to other objects / threads) before exiting the constructor call, and
you should not call non-final, non-private methods from the constructor.
Doing either of these (in a non-final class) means that you give access to an object not yet fully constructed, which may result in subtle, hard to find bugs later. E.g. if the virtual method in question is overridden in a subclass and the implementation depends on some member defined and initialized only in the subclass constructor, the method gets called before the subclass member is correctly initialized, thus it won't have the value you would expect.
Because public static void main is the entry point of the programm. So you do not require to create instance of the class B.
The method signature for the main() method contains three modifiers:
* public indicates that the main() method can be called by any object.
* static indicates that the main() method is a class method.
* void indicates that the main() method has no return value.
Read more : Understanding public static void main function
So that Constructor of A is get called when the programm get executed and that it calls the foo method of the super class A.
It's not called without an instance.
You call it on this - that's an instance.
The constructor of A is getting called because you called it directly. However, if you wished to call A through B, within Main [which is called without a current instance of the containing class B (1 because its static, and 2. its reserved for the beginning of the application)] you would just change the "new A()" to "new B()"
Since you're using a constructor with no parameters, a default constructor in automatically generated at compile time.
Whether main() is the entry point or not is not the explanation. The reason is that main() is static, therefore doesn't require an instance of its class.
No instance of B is ever created by this program.
class A is public, and its inherited by class B. class B can instantiate class A, with
A object=new A()
and the object initialization is done by Constructor method defined automatically. Constructor of A in turn calls method foo(), which is private to class A. As far as i know, to call a method from a class which is in the same class scope, no instance is needed.

Categories

Resources