use super () in Java? - java

I'm trying to learn java oop and i find some problem understanding the use of super method when i make some exemple . Please chek the code below .
can you please tell me why the super(); method doesn't refer to the superClass ? i don't understand .
superClass :
package javaapplication;
public class A {
protected String val;
public A(){
this.val = " Class A ";
}
}
subClass
package javaapplication;
public class B extends A {
public B(){
this.val = " Class B";
System.out.println(super.val);
}
}
Main Class
package javaapplication;
public class JavaApplication {
public static void main(String[] args) {
B a = new B();
}
}
output : run : Class B
why i got "Class B" ?

Because there is only one val variable, and your B constructor is setting it to " Class B".
You can use super.something to refer to something (member variable or method) on the superclass instead of the current class, but those will only be different if both classes declare something. In this case, both A and B are sharing the val defined by A.

A constructor in Java (now focus on your constructor of class B) ALWAYS calls either another constructor of class B if you explicitly tell you to do so with this(arguments...) or a constructor of the super class A if you explicitly tell you to do so with super(arguments...) or if you don't specify any call to another constructor it calls super(). And this call is the first instruction of any constructor. Unless the class you are talking about is Object.
So first the A constructor is called, setting val to "Class A" but then the constructor of class B continuous erasing that value and replacing it with "Class B".
Albeit a good example on how constructors work but in essence bad programming as this is not what you would do. A good programmer would add a contstructor in class A accepting the value for val and in class B you would call it using super("Class B") and val would be a private variable defined in class A.
Note that because class B extends class A, any instance of class B has the attributes defined in class B and class A, so super.val or this.val is doing referencing exactly the same variable. One could add a new variable val in class B but again this would be bad programming, if the compiler would accept this, I am not sure.

when you doB a = new B(); constructor of B is executed which internally call base class constructor as the first operation.So this sets the value of variable val as Class A. But then you are manually doing this.val = Class B which sets the value again as Class B
Just comment out this.val = Class B from constructor B, it will print Class A

Related

Constructor in Child Class

Why is the constructor in B required?
IntelliJ suggests to remove =null as it is redundant presumably because it is initialized through the given constructor in A.
However, this removal (which is presumably also performed by the compiler) then (presumably) requires the constructor in B.
Any other explanation?
public abstract class A {
private Object foo = null;
public A(Object foo){this.foo=foo;}
}
public class B extends A {
public B(Object foo){super(foo);}
}
Java does not have "constructor inheritance". The only way to initialize A is to pass the foo parameter to its constructor, and the only way to do this is to create a constructor for B that does so.
Note, however, that they don't have to have the same signature (like you have in the question) - B's constructor only needs to pass some parameter to A. E.g.:
public class B extends A {
public B() {
super("Arbitrary default passed to A");
}
public B(Object passedToA, Obejct notPassedToA) {
super(passedToA);
System.out.println("This argument was not passed to A():" + notPassedToA);
}
}
Why is the constructor in B required?
If the class B extends A, the class B must be instantiated in all possible ways as the class A can be and the class B can have additional ways to be instantiated. It means that class B is forced to have a constructor.
The only exemption can be in case of a no-arg constructor because the compiler makes it up with a default constructor i.e. if you put a no-arg constructor in the class A the child classes are not forced to have this.

Why can't a local class that extends an inner class access the inner class enclosing instance?

(I keep re-reading that question title and thinking about how ridiculous it must look, but I assure you that is the best description of the problem, and I have an actual application where this is the best structure. I swear I'm not crazy.)
Consider the following. Each block is a separate file:
package myPackage;
public class A {
public int i;
public A(int i) {
this.i = i;
}
public class B {
}
}
package myPackage;
import myPackage.A.B;
public class Main {
public static void main(String[] args) {
class C extends B {
public C(A enclosingInstance) {
enclosingInstance.super();
}
public void show() {
System.out.println(A.this.i);
}
}
A myA = new A(2);
C myC = new C(myA);
myC.show();
}
}
Note that the enclosingInstance business is to solve a problem involving intermediate constructor invocations. See "Why can't outer classes extend inner classes?".
I would expect the output to be "2". But instead, I have a compile error on System.out.println(A.this.i);:
No enclosing instance of the type A is accessible in scope
I think the programmatic concept I'm trying to solve is sound: Create a new type of B inside main to give to A that uses things from A that types of B can access.
So what am I doing wrong, or why isn't this possible in java?
EDIT/UPDATE: Note that the same error appears when the code in main is moved to a non-static method. That is to say, I tried moving everything inside of static void main to a new, non-static method of class Main called go(). Then I changed static void main to the single line new Main().go();. The error is in the same spot. So it doesn't seem to be an issue of class C being defined in a static context.
You want A.this to refer to the enclosing instance of the B instance. But why should it? That's not what the syntax means. A.this would mean the enclosing A instance of the C instance, and this does not make sense because C is not an inner class of A.
To make this clearer, here is an example where C is an inner class of A.
public class A {
public int i;
public A(int i) {
this.i = i;
}
public class B {
void foo() {
System.out.println(A.this.i);
}
}
public class C extends B {
C(A a) {
a.super();
}
void bar() {
System.out.println(A.this.i);
}
}
public static void main(String[] args) {
A a1 = new A(1);
A a2 = new A(2);
C c = a1.new C(a2);
c.foo();
c.bar();
}
}
Here C extends B, and both C and B are inner classes of A. Therefore any C has an enclosing A instance, and it also has an enclosing A instance when considered as a B, and these enclosing instances are different (as proved by the fact that foo and bar print different numbers).
So, A.this could not possibly mean what you want it to mean, because it already means something else. I guess the reason why the language designers didn't come up with other syntax to mean the enclosing instance of a super class, is because such syntax would be very complicated, with little pay-off (simple workarounds already exist).
This is absurd code that you should never write for production.
It is, in part, explained in the documentation for Explicit Constructor Invocations
Qualified superclass constructor invocations begin with a Primary
expression or an ExpressionName. They allow a subclass constructor to
explicitly specify the newly created object's immediately enclosing
instance with respect to the direct superclass (§8.1.3). This may be
necessary when the superclass is an inner class.
All this to say that C is a local class (which is an inner class, which is kind of nonsense because if you declare it in a static method there is no enclosing instance) that is a subclass of B but not a nested class of A. As such, there is no enclosing instance. An instance of C does not have an enclosing instance. (Though it would if you declared it in an instance method, but that would be an instance of Main.)
The newly created object's immediately enclosing instance (from JLS) is specified indirectly through a constructor parameter.
You'd have to store it yourself
private A enclosingInstance;
public C(A enclosingInstance) throws CloneNotSupportedException {
enclosingInstance.super();
this.enclosingInstance = enclosingInstance;
}
and since A#i is public, you can access it normally
public void show() {
System.out.println(enclosingInstance.i);
}
With the provided information, I would do this :
public class B {
protected A getOuterInstance() {
return A.this;
}
}
and just let C inherit and use this method. I know you dislike this method but this is the simplest answer I can see. With more information, I would probably propose a design which would try not involving any inner class as this is not a normal use case for inner classes.

Inheritance and constructors in Java

In the following example:
class A {
private int a;
private int b;
private int c;
public A(int a, int b , int c) {
this.a = a;
this.b = b;
this.c = c;
}
}
class B extends A {
public B() {
super(1,2,3);
}
Does the statement super(1,2,3) in the class B create a private fields same as the private fields in the class A? Or is it illegal to use this statement because B cant inherit the private fields of A?
And we suppose that we didn't use the super constructor in the class B then normally the computer will call the default constructor of the class A. We know that private fields are not inherited in Java so what will the default constructor initialize in this state ?
You cannot call super() like this:
class B extends A {
super(1,2,3);
}
super() OR this() should be the first statement in a constructor. First correct this basic mistake of yours before going further. super() is used by default even if you don't explicitly use it.
class B extends A {
B (){
super(1,2,3);
}
}
This is the right way. Please Read about Constructors and Java language basics first before posting questions.
EDIT
I didn't notice that someone edited you question to add super(1,2,3) in a constructor, now answering your questions as follows:
Does the statement super(1,2,3) in the class B create a private fields same as the private fields in the class A? Or is it illegal to use this statement because B cant inherit the private fields of A?
No, by calling super(1,2,3) all you're doing is passing 3 integer values to the base class constructor public A(int a, int b , int c) After that you're assigning these values to the private instance variables of base class, you're not making a separate fields for class B, if thats what you asked, and No B class still can't access base class instance variables directly (by stating directly I mean by inheritance or making an instance, there are other ways like setters/getters etc)
And we suppose that we didn't use the super constructor in the class B then normally the computer will call the default constructor of the class A. We know that private fields are not inherited in Java so what will the default constructor initialize in this state ?
No, if you don't use a constructor in B class which uses super(int, int, int) to match the arguments of base class constructor (int a, int b , int c) then your code won't even compile. The default constructor will call the no-args constructor of Base class, but since Base class has no default constructor you'll get compilation error!
First of all, the code you posted is not valid Java. It is important that you post working code, otherwise we can't be sure about what you are asking.
Does the statement super(1,2,3) in the class B create a private fields same as the private fields in the class A? Or is it illegal to use this statement because B cant inherit the private fields of A?
Assuming you put the statement in a constructor instead of at class level, which is illegal, then no, that will not automatically create fields in class B. It just calls the constructor in the superclass A that takes three int arguments and initializes the fields in the superclass part of the object.
And we suppose that we didn't use the super constructor in the class B then normally the computer will call the default constructor of the class A. We know that private fields are not inherited in Java so what will the default constructor initialize in this state ?
Since there is no default (i.e. no-arguments) constructor in class A, you would get a compiler error - the compiler would complain that there is no appropriate constructor in class A.
Java only automatically adds a no-arguments constructor to a class if you do not specify a constructor at all in the class. Since class A already has a constructor, Java is not automatically going to add a no-arguments constructor.
First of all you need to understand one thing: private fields of a parent class ARE BEING INHERITED. The only thing is that if they are private in parent, then they cannot be accessed directly from the child class (the B class in your example). So in other words: not a single B class method can access those fields, but every A class method can access them. So for example its possible that there is a public/protected method inside A class that changes some of those fields and this method can be called from a child class (B).
Once you correct your class to the proper:
class B extends A {
public B() {
super(1,2,3);
}
}
...we can proceed to answer your actual questions.
The constructor of A does not create fields. The fields are created as part of creating of any A object, and are initialized by the constructor.
Those fields are created in B as well, but not because you called super(1,2,3) but because you extend A. As soon as an instance of B, which is an extended instance of A is created, those fields are there - but they are accessible only to methods that are declared in A itself and not in its descendents.
By calling super(1,2,3), you are initializing those private fields. They are still not accessible to B. The constructor of A is mediating between B and these private variables. If you had a method that prints those fields in A, and that method was not private, you could call it and it would print them with these values.
As for your second question, if you didn't call the super(1,2,3), Java would try to call the default constructor. However, for a class that has a constructor, there is no default constructor. The empty/nullary constructor only exists if you either declared it yourself, or if you didn't declare any constructor at all.
// The following two classes have a default constructor which will be called
// if any descendent doesn't call super(...)
class HasADefaultConstructor {
}
class AlsoHasADefaultConstructor {
AlsoHasADefaultConstructor() {
}
}
// But this one doesn't.
class DoesntHaveADefaultConstructor {
DoesntHaveADefaultConstructor( String a ) {
}
}
So you can't inherit private varibles, but you can access them if the parent class has the appropriate getters:
Run the example and you see the output is 'a is: 1'
Regarding the default constructor: In your example you have explicitly implemented
a constructor. So the implicit default constructor is not there any more
class B extends A {
public B() {
super(1, 2, 3);
}
public void foo() {
System.out.println("a is: " + super.getA());
}
public static void main(String[] args) {
B bb = new B();
bb.foo();
}
}
class B extends A {
public B() {
super(1, 2, 3);
}
public void foo() {
//access a
System.out.println("a is: " + super.getA());
}
public static void main(String[] args) {
B bb = new B();
bb.foo();
}
}

Multiple casting on inherited objects

interface I{
}
class A implements I{
}
class B extends A {
}
class C extends B{
public static void main(String args[])
{
A a = new A();
B b = new B();
b = (B)(I)a; //Line 1
}
}
I know this is not an actual code :)
I just need to know how the casting gets done at Line 1.
I know the reference variable 'a' gets cast to Class B/Interface I.
But I am not sure of the sequence in which the casting takes place..can someone tell me which cast gets executed first.
PS : I searched for similar posts but most of them were from C++.If a similar post is already there wrt to Java do point it..tx
a gets cast to type I first, and then to type B, as casting is right-associative.
Why would you cast it in the first place? This is multiple level inheritance but what happens here is all them methods in class I get inherited by class A, as class B inherits class A the methods in class A get passed onto class B. This means that all the methods class A inherits will also be in class B
That means class B is also a type of class I and therefore i believe there is no need to cast at all

Hierarchy of inner classes in Java

I am using a hierarchy of inner classes to represent some data in an application and I have run into an error message that I simply do not understand. My code can be boiled down to the following minimal example:
public class A {
public class B extends A {}
public class C extends B {}
}
Javac (and my IDE of course) fails to compile the code with the following error message:
A.java:3: cannot reference this before supertype constructor has been called
public class C extends B {}
^
1 error
I didn't write this anywhere. There is no more code than provided above, so I assume javac has generated something related to the inner class.
I have found another way to represent my data, so I am simply interested in a good explanation of why it doesn't compile.
You need an outer class instance to create an inner class instance i.e something like new Outer().new Inner();
To extend the inner class (Parent inner class) with another inner class (child inner class), you cannot call the constructor of 'parent inner class' because the instance of 'outer class' is not there.
Try like this,
public class A{
public class B extends A {
B() { }
}
public class C extends B {
C() {
new A().super();
}
}
public static void main(String args[]) {
}
}
Similar question : Odd situation for “cannot reference this before supertype constructor has been called”
The other poster is correct, but how to fix? Simply make your class static:
public class A {
public static class B extends A {}
public static class C extends B {}
}
Note that if your inner classes refer to fields of the outer class, you can't make them static, otherwise you can (and should - doing so reduces dependencies).
Your code compiles under Java 7.
The following workaround compiles under Java 6.
public class C extends B
{
public C()
{
A.this.super();
}
}
#saugok's link to the previous question quoted Joshua's explanation. Basically he argued that since C is subclass of A, C inherits A's members as C's members. Therefore B is also C's member. (For example a class literal C.B.class is valid.) Therefore he argues that C.this is the enclosing instance for B's super(), therefore C(){super();} is actually C(){C.this.super();}. Since C.this cannot be evaluated before super constructor, thus the error.
However this doesn't seem to be warranted by the language spec. See #8.1.3. Since B is not immediately lexically enclosed by C, B is not a direct inner class of C, there is no reason to say that B's direct enclosing instance must be an instance of C.
We need to pass B() an instance of A. It is true that C.this is an instance of A ( try this code: new C().new B().new C().new B();) therefore it could be a candidate. There is also another candidate, A.this. A.this is available and ready to use (it's passed in as the hidden parameter to C()).
According to javap, javac 7 compiles the code into
class B
private A this$0;
B( A a )
this$0 = a;
super(); // A()
class C extends B
private A this$0;
C( A a )
this$0 = a;
super( a ); // B(A)

Categories