I have created an upcasting demo and i don't understand how this code is working or i can more specifically say why is constructor of base class also called while the dispatching is done with the Derived class.And there is even not a call to the constructor of the base class.I haven't even used super keyword anywhere than how is the constructor of the base class also called.
class Base{
int value =0;
Base(){
addValue();
}
void addValue(){
value+=10;
}
int getValue(){
return value;
}
}
class Derived extends Base{
Derived()
{
addValue();
}
void addValue(){
value+=20;
}
}
class Test{
public static void main(String args[]){
Base b=new Derived();
System.out.println(b.getValue());
}
}
When you create a new Derived object, its constructor will be called. Since Derived has a superclass Base, its construtor will be called first. In the constructor, the overridden method addValue will be called, which leads to the temporary value of 20. After that, addValue of Derived is called and adds another 20 to value. The final result is 40.
Since, you did not call the constructor of the superclass using super yourself, Java will do that automatically:
Derived() {
super();
addValue();
}
A Derived object is-a Base object, plus more. Java, like most languages, needs to construct the whole object, including the parts initialized by the Base constructor.
Look at is this way: What's doing the initial setting of value to 0? Isn't that part of the code for Base too?
Java lets you specify which base-class constructor to use with super if you want to, but if you don't specify one, it'll pick one. Those rules can be complicated, but in this case they're simple: The no-arguments Base constructor is called from the no-arguments Derived constructor.
As a test, set the Base() constructor private and see what the compiler tells you.
Related
Kindly excuse my question as I have tried to search the difference between using super keyword vs class name to call a method from super class but am unable to find an answer.
My question is I am trying to learn Java as a study course and am using an example from the link: http://www.javatpoint.com/super-keyword using Example # 3 and here is the code I have written:
I have created a super class named Vehicle
public class Vehicle {
Vehicle() {
System.out.println("Vehicle constructor created");
}
public void speed() {
int a = 20;
System.out.println(a);
}
}
and then created a sub class named Bike with the following code:
public class Bike extends Vehicle {
int speed;
Bike(int speed1) {
this.speed = speed1;
System.out.println(speed1);
super.speed();
}
public static void main(String args[]) {
Bike b = new Bike(10);
}
}
In the sub class under Bike constructor I am using super.speed() to call speed method from super (Vehicle) class. Now if I change this line to Vehicle.speed() I get an error stating that I need to make my speed method as static.
I do not want to make my method as static and want to know about the difference between both of them.
Cheers,
Calling a method using class name directly means that you want to call a static method, which is not related to any object of the class but the class it self.
That is why the compiler tells you that the method must be static.
As for your question, when you create an object of a child class (Bike class in this example) an object of its parent is always created, on the base of which the particular child object is created.
Its like, when ever you create a Bike, a backing Vehicle is always created, based on which the Bike is created. Otherwise the Bike wouldn't be a Vehicle.
So calling a method by super means, you're telling the compiler to call this method on the class which was used as base(parent) for making this Bike class, from which I'm calling this method.
when you're calling the method by class name, you're telling the compiler to call this method of Vehicle class which is not related to any Vehicle object/instance (and obviously not related to any child (e.g. Bike object or instance as well)
Methods that aren't static can only be called on a specific instance of an object. That is why calling Vehicle.speed() would only work if the speed method were static. The reason you can call super.speed() is because in the constructor, you have already constructed the vehicle object, and are basically calling the method on the object you are constructing.
For the above example, I would say that calling super.speed() is the best approach.
Also, as you haven't overriden the super implementation of the speed method, you can just as easily call this.speed() or speed(). That approach would mean that if you ever decided that the Bike needs different functionality in the speed method, your specific implementation would be called as opposed to the default.
The two constructs are not equivalent.
When calling Vehicle.speed() the compiler is looking for a static method named speed() in the class named Vehicle. A static method doesn't belong to any instance of the class. You cannot use any instance variable inside a static method. You haven't defined a static method named speed() in your Vehicle class and therefore there's no such thing as Vehicle.speed(). Hence, you get a compilation error.
When calling super.speed(), you don't look for a static method as in the previous case: The actual method that is going to be called when using the super syntax is an instance method (named speed() in your case) defined in the superclass of the current object. That is, super.speed() is the instance method defined in the super class of the current object (unlike this.speed() which is the instance method named speed() defined in the actual class of the current object). In other words, it is going to call the method speed() defined in the class Vehicle, but the this parameter is going to be the one referenced by b, the current object.
You need instance to calls instance(non-static) method.
super is parent class's instance. Simply put class name is not an instance(it' a static context for entire class).
[super is parent class's instance ?]
Jon skeet said no such thing as a "parent instance", but i doubt the term of instance.
super's variable is initialized first and then the turns of child to decide whether share the same variable/method(i.e. return this.i; in this kind of method will return super.i, not this.i, when call by child) or override it.
import java.util.Random;
class Love {
int i = 1;
int hole() {
return this.i;
}
}
class Main extends Love {
void wrapper() {
System.out.println(super.i); //1
System.out.println(this.i); //2
super.i = new Random().nextInt(50) + 2; //to avoid compiler pre-optimizing hard coded return value in hole(), so we set again.
System.out.println(super.i); //23
i = 3; //2nd attempt override
this.i = 3; //3rd attempt override
System.out.println(hole()); //23, super "instance" keep its own version of this.i
}
int i = 2; //1st attempt oveeride
public static void main(String[] args) {
new Main().wrapper();
}
}
So it's obvious when child override, super still keep its own version, so IMHO super can roughly treat like a parent instance, just the difference with normal instance are it's a keyword with some restriction of usage (e.g. super.super.i is not allow, direct print super not allow). One more difference is the variable value will sync in each instance due to child might share it as mentioned above.
You can try to print super.variable_name inside static method, it will output super is a non-static variable:
$ javac Bike.java
Bike.java:132: error: non-static variable super cannot be referenced from a static context
System.out.println(super.dummy);
^
Bike.java:132: error: cannot find symbol
System.out.println(super.dummy);
^
symbol: variable dummy
2 errors
$
So it's make sense super as a non-static variable can access non-static method speed() in your example.
If you want to use method directly with class name then you have to specify method as static
public static void speed() {
int a = 20;
System.out.println(a);
}
or
you can create an object of class Vehicle and access speed method in your subsclass like this
Bike(int speed1) {
this.speed = speed1;
System.out.println(speed1);
Vehicle vehicle = new Vehicle();
vehicle.speed();
}
hi super is a keyword which is used to access the super class methods in sub class.
This super keyword is used mainly when methods are overridden.
example
class A
{
method m()
}
class B extends A
{
method m()
method m1()
{
super.m()
}
}
class C
{
public static void main(String args[])
{
B b = new B();
b.m() // calls method m() in class B
b.m1() // calls method m() in class A because method m is pointing to super class method
}
}
We all Know that the JVM provides us a default constructor in the every java program.
But if we declare any other type of constructor then it does not provide the any type of default constructor.
So, my question is that is it compulsory to declare default constructor when we declare any other type of constructor in our program.
If YES then explain Why?
If NO then also explain Why?
Give the Solution with proper suitable example.
No, it's not compulsory at all. There are loads of classes with no default constructor, and there's nothing stopping you from writing your own. One that springs to mind is java.awt.Color.
Declaring the default constructor depends on the business requirement and technically its not compulsory.
If you want a class to be initialized only with a set of parameters, then you can skip the default constructor, which indeed forces you -- to give the required values to create the object
For instance,
public class ClassA {
String name;
ClassA(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
For the above class, if you want to do,
ClassA obj = new ClassA();
This is not possible as there is not default constructor.
ClassA obj = new ClassA("name");
The above is the only way to create object, as name is the parameter should be given.
If you want both to be created, add default constructor as
ClassA() {}
Which provides way to create the object with out name.
No, it's not cumpolsory.
class Dog {
Dog(String name)
{
system.out.println("Dog :" + name);
}
public static void main(String[] args)
{
Dog d = new Dog("dollar"); // works fine
Dog d2 = new Dog() // error , no default constructor defined for Dog
}
}
So, my question is that is it compulsory to declare default
constructor when we declare any other type of constructor in our
program.
No, It's not necessary to have a default constructor.
If NO then also explain Why ?
Default Constructor will be provided by Compiler, only if you don't defined any no argument Constructor. But, Keep in mind the following, Check mode from JLS
8.8.9. Default Constructor
If a class contains no constructor declarations, then a default
constructor with no formal parameters and no throws clause is
implicitly declared.
If the class being declared is the primordial class Object, then the
default constructor has an empty body. Otherwise, the default
constructor simply invokes the superclass constructor with no
arguments.
It is a compile-time error if a default constructor is implicitly
declared but the superclass does not have an accessible constructor
(§6.6) that takes no arguments and has no throws clause.
It is not necessary to create the default constructor, but it is good practice to create the default constructor.
If your class is to be reused then not creating the default constructor will limit the re-usability of your class.
Like if a class is extending that class, then the derived class must have an explicit super call.
consider the following example:-
class Base
{
public Base(int x){
//some statements
}
/*
some methods
*/
}
class Derived
{
// only one of the following will be used
public Derived(){ // This will cause a compile-time error
//some statements
}
public Derived(){ // This will work fine
//some statements
super(x);
}
/*
some methods
*/
}
The reason behind this is, if the base class do not have default constructor than derived class must call the appropriate super() in all its constructor declarations. But if we have a default constructor in base class then the call to super() is not mandatory.
No, it's not compulsory!
But then if you dont have a default constructor(No-argument constructor) and if you want the to create the object of your class in this form
A ref = new A();
then you might not be able to do it.
No this is not necessary.
let me explain why this is not necessary
The question which you've asked is seems like constructor overloading.
If you create an or many parameterized constructor in java then you do need need to be worried for the default constructor.
Basically constructor is used to initialize the instance variables or class members or for performing the preliminary tasks and if you have already done with this by using the another constructor then there is no need for another but you can do if you want.
public class base {
int a;
public base(int x)
{
this.a=x;
System.out.println(x);
}
public base()
{
System.out.println("abc");
}
public static void main(String []a)
{
base b=new base();
b=new base(4);
}
}
The output is :-
abc
4
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Use of ‘super’ keyword when accessing non-overridden superclass methods
I'm new to Java and have been reading a lot about it lately to get more knowledge and experience about the language. I have a question about inherited methods and extending classes when the compiler inserts automatic code.
I've been reading that if I create class A with some methods including lets say a method called checkDuePeriod(), and then create a class B which extends class A and its methods.
If I then call the method checkDuePeriod() within class B without using the super.checkDuePeriod() syntax, during compilation will the compiler include the super. before checkDuePeriod() or will the fact that the compiler includes the super() constructor automatically when compiling the class imply the super. call of the methods that class B calls from class A?
I'm a little confused about this. Thanks in advance.
The super class's implementation of regular methods is not automatically invoked in sub classes, but a form of the super class's constructor must be called in a sub class's constructor.
In some cases, the call to super() is implied, such as when the super class has a default (no-parameter) constructor. However, if no default constructor exists in the super class, the sub class's constructors must invoke a super class constructor directly or indirectly.
Default constructor example:
public class A {
public A() {
// default constructor for A
}
}
public class B extends A {
public B() {
super(); // this call is unnecessary; the compiler will add it implicitly
}
}
Super class without default constructor:
public class A {
public A(int i) {
// only constructor present has a single int parameter
}
}
public class B extends A {
public B() {
// will not compile without direct call to super(int)!
super(100);
}
}
If you call checkDuePeriod() in B without super., means you want to invoke the method that belongs to the this instance (represented by this within B) of B. So, it equivalent to saying this.checkDuePeriod(), so it just doesn't make sense for the compiler to add super. in the front.
super. is something that you must explicitly add to tell the compiler that you want to call the A's version of the method (it is required specially in case B has overridden the implementation provided by A for the method).
Call of super() as a default constructor (constructor with no args) can be direct or non direct but it garants that fields of extendable class are properly initialized.
for example:
public class A {
StringBuilder sb;
public A() {
sb = new StringBuilder();
}
}
public class B extends A {
public B() {
//the default constructor is called automatically
}
public void someMethod(){
//sb was not initialized in B class,
//but we can use it, because java garants that it was initialized
//and has non null value
sb.toString();
}
}
But in case of methods:
Methods implement some logic. And if we need to rewrite logic of super class we use
public class B extends A {
public B() {
}
public boolean checkDuePeriod(){
//new check goes here
}
}
and if we want just implement some extra check, using the value returned from checkDuePeriod() of superclass we should do something like this
public class B extends A {
public B() {
}
public boolean checkDuePeriod(){
if(super.checkDuePeriod()){
//extra check goes here
}else{
//do something else if need
}
return checkResult;
}
}
First about the Constructors:
- When ever an object of a class is created, its constructor is initialized and at that time immediately the constructor of its super-class is called till the Object class,
- In this process all the instance variables are declared and initialized.
- Consider this scenario.
Dog is a sub-class of Canine and Canine is a sub-class of Animal
Now when Dog object is initialized, before the object actually forms, the Canine class object must be form, and before Canine object can form the Animal class object is to be formed, and before that Object class object must be form,
So the sequence of object formed is:
Object ---> Animal ---> Canine ---> Dog
So the Constructor of the Super-Class is Called before the Sub-Class.
Now with the Method:
The most specific version of the method that class is called.
Eg:
public class A{
public void go(){
}
}
class B extends A{
public static void main(String[] args){
new B().go(); // As B has not overridden the go() method of its super class,
// so the super-class implementation of the go() will be working here
}
}
In Java, I can't create instances of abstract classes. So why doesn't eclipse scream about the following code?
public abstract class FooType {
private final int myvar;
public FooType() {
myvar = 1;
}
}
The code is fine, the final variable is initialized in the constructor of FooType.
You cannot instantiate FooType because of it being abstract. But if you create a non abstract subclass of FooType, the constructor will be called.
If you do not have an explicit call to super(...) in a constructor, the Java Compiler will add it automatically. Therefore it is ensured that a constructor of every class in the inheritance chain is called.
You can have constructors, methods, properties, everything in abstract classes that you can have in non-abstract classes as well. You just can't instantiate the class. So there is nothing wrong with this code.
In a deriving class you can call the constructor and set the final property:
public class Foo extends FooType
{
public Foo()
{
super(); // <-- Call constructor of FooType
}
}
if you don't specify a call to super(), it will be inserted anyway by the compiler.
You can create concrete sub-classes of FooType and they will all have a final field called myvar.
BTW: A public constructor in an abstract class is the same as a protected one as it can only be called from a sub-class.
What is your doubt?
Ok. See, an abstract class can have a constructor. It's always there-implicit or explicit. In fact when you create an object of a subclass of an abstract class, the first thing that the constructor of the subclass does is call the constructor of its abstract superclass by using super(). It is just understood, that's why you don't have to write super() explicitly unless you use parameterized constructors. Every class even if it is abstract, has an implicit constructor which you cannot see. It is called unless you create some constructor of your own. so long you created abstract classes without creating any custom constructor in it, so you didn't know about the existence of the implicit constructor.
You definitely can declare final variable in abstract class as long as you assign value to it either in the constructor or in declaration. The example that guy gave makes no sense.
No you can't declare final variables inside an Abstract class.
Check Below example.
public abstract class AbstractEx {
final int x=10;
public abstract void AbstractEx();
}
public class newClass extends AbstractEx{
public void AbstractEx(){
System.out.println("abc");
}
}
public class declareClass{
public static void main(String[] args) {
AbstractEx obj = new newClass ();
obj.AbstractEx();
// System.out.println(x);
}
}
This code runs correct and produce output as
abc
But if we remove comment symbol of
System.out.println(x);
it will produce error.
I know abstract fields do not exist in java. I also read this question but the solutions proposed won't solve my problem. Maybe there is no solution, but it's worth asking :)
Problem
I have an abstract class that does an operation in the constructor depending on the value of one of its fields.
The problem is that the value of this field will change depending on the subclass.
How can I do so that the operation is done on the value of the field redefined by the subclass ?
If I just "override" the field in the subclass the operation is done on the value of the field in the abstract class.
I'm open to any solution that would ensure that the operation will be done during the instantiation of the subclass (ie putting the operation in a method called by each subclass in the constructor is not a valid solution, because someone might extend the abstract class and forget to call the method).
Also, I don't want to give the value of the field as an argument of the constructor.
Is there any solution to do that, or should I just change my design ?
Edit:
My subclasses are actually some tools used by my main program, so the constructor has to be public and take exactly the arguments with which they will be called:
tools[0]=new Hand(this);
tools[1]=new Pencil(this);
tools[2]=new AddObject(this);
(the subclasses are Hand, Pencil and AddObject that all extend the abstract class Tool)
That's why I don't want to change the constructor.
The solution I'm about to use is to slightly change the above code to:
tools[0]=new Hand(this);
tools[0].init();
tools[1]=new Pencil(this);
tools[1].init();
tools[2]=new AddObject(this);
tools[2].init();
and use an abstract getter to acces the field.
How about abstract getter/setter for field?
abstract class AbstractSuper {
public AbstractSuper() {
if (getFldName().equals("abc")) {
//....
}
}
abstract public void setFldName();
abstract public String getFldName();
}
class Sub extends AbstractSuper {
#Override
public void setFldName() {
///....
}
#Override
public String getFldName() {
return "def";
}
}
Also, I don't want to give the value
of the field as an argument of the
constructor.
Why not? It's the perfect solution. Make the constructor protected and offer no default constructor, and subclass implementers are forced to supply a value in their constructors - which can be public and pass a constant value to the superclass, making the parameter invisible to users of the subclasses.
public abstract class Tool{
protected int id;
protected Main main;
protected Tool(int id, Main main)
{
this.id = id;
this.main = main;
}
}
public class Pencil{
public static final int PENCIL_ID = 2;
public Pencil(Main main)
{
super(PENCIL_ID, main);
}
}
How about using the Template pattern?
public abstract class Template {
private String field;
public void Template() {
field = init();
}
abstract String init();
}
In this way, you force all subclasses to implement the init() method, which, since it being called by the constructor, will assign the field for you.
You can't do this in the constructor since the super class is going to be initialized before anything in the subclass. So accessing values that are specific to your subclass will fail in your super constructor.
Consider using a factory method to create your object. For instance:
private MyClass() { super() }
private void init() {
// do something with the field
}
public static MyClass create() {
MyClass result = new MyClass();
result.init();
return result;
}
You have an issue in this particular sample where MyClass can't be subclassed, but you could make the constructor protected. Make sure your base class has a public / protected constructor also for this code. It's just meant to illustrate you probably need two step initialization for what you want to do.
Another potential solution you could use is using a Factory class that creates all variants of this abstract class and you could pass the field into the constructor. Your Factory would be the only one that knows about the field and users of the Factory could be oblivious to it.
EDIT: Even without the factory, you could make your abstract base class require the field in the the constructor so all subclasses have to pass in a value to it when instantiated.
Also, I don't want to give the value of the field as an argument of the constructor.
Is there any solution to do that, or should I just change my design ?
Yes, I think you should change your design so that the subclass passes the value to the constructor. Since the subclass portion of your object isn't initialized until after the superclass constructor has returned, there's really no other clean way of doing it. Sure, this'd work:
class Super {
protected abstract int abstractField();
protected Super() { System.out.println("Abstract field: " + abstractField); }
}
class Sub {
protected int abstractField(){ return 1337; }
}
... since the implementation of abstractField() doesn't operate on object state. However, you can't guarantee that subclasses won't think it's a great idea to be a little more dynamic, and let abstractField() returns a non-constant value:
class Sub2 {
private int value = 5;
protected int abstractField(){ return value; }
public void setValue(int v){ value = v; }
}
class Sub3 {
private final int value;
public Sub3(int v){ value = v; }
protected int abstractField(){ return value; }
}
This does not do what you'd expect it to, since the initializers and constructors of subclasses run after those of the superclass. Both new Sub2() and new Sub3(42) would print Abstract field: 0 since the value fields haven't been initialized when abstractField() is called.
Passing the value to the constructor also has the added benefit that the field you store the value in can be final.
If the value is determined by the type of subclass, why do you need a field at all? You can have a simple abstract method which is implemented to return a different value for each subclass.
I think you need a factory (aka "virtual constructor") that can act on that parameter.
If it's hard to do in a given language, you're probably thinking about it incorrectly.
If I understand you correctly: You want the abstract class's constructor to do something depending on a field in the abstract class but which is set (hopefully) by the subclass?
If I got this wrong you can stop reading ...
But if I got it right then you are trying to do something that is impossible. The fields of a class are instantiated in lexical order (and so if you declare fields "below", or "after", the constructor then those will not be instantiated before the constructor is called). Additionally, the JVM runs through the entire superclass before doing anything with the subclass (which is why the "super()" call in a subclass's constructor needs to be the first instruction in the constructor ... because this is merely "advice" to the JVM on how to run the superclass's constructor).
So a subclass starts to instantiate only after the superclass has been fully instantiated (and the superclass's is constructor has returned).
And this is why you can't have abstract fields: An abstract field would not exist in the abstract class (but only in the subclass) and so is seriously(!) "off limits" to the super (abstract) class ... because the JVM can't bind anything references to the field (cause it doesn't exist).
Hope this helps.