I am having a hell of a time with an "extends" issue with a problem in a problem set I'm working on - I think I'm just having a block because it's written to be purposefully confusing. Here's the problem as I was given it:
class A {
int x;
A(int a) {System.out.println(" class A");}
}
class B extends A {
int x;
B() {System.out.println(" class B");}
public static void main (String [] args) {
A a = new B();
}
}
When I compile, I get the following error kicked out from the console:
cannot find symbol
symbol : constructor A()
location: class A
B() {System.out.println(" class B");}
^
and I'm supposed to be able to fix this error in class B without touching class A. I'm clearly missing something stupidly obvious, but I've tried permutations of everything I can think of for an hour and nothing's working.
So far, I've tried:
throwing a void in front of B() - same error.
making B() into A(int a) - the latter comes back with an invalid method declaration error (adding a void in front of it kicks me back to the original "cannot find symbol" error)
making B() B(int a) - same error, plus throws an additional "cannot find symbol" error since I've now trashed the B() declaration.
making class B extends A into class B extends A(int A) - throws nine errors. Clearly not the answer.
Changing the class name of A to Apple just to see if that would give me an answer - this wants me to add a void in front of A(int a) in the Apple class, which I can't do.
What the hell am I missing here? This is not exactly an advanced class so it can't be anything terribly complicated, but this is making me completely insane. Any help would be greatly appreciated.
In a derived class, you need to call the base class constructor. If you don't do this explicitly, the compiler will try and insert a call to the no-argument constructor - if none exists in the base class, you get that error.
The solution is to explicitly call the base class constructor with some value:
B() {
super(0);
System.out.println(" class B");
}
your first call in B's constructor needs to be super(a);
a being whatever you want to input into B's constructor.
1) When you extend a class, your subclass implicitly contains a chunk of data that consists of all the data used to make an instance of the superclass. You have to initialize that data, too. If you don't say how it will be initialized, it is assumed you want the default constructor, i.e. A.A(). But this constructor does not exist - you only have A.A(int).
To do this initialization, as the first line in the B constructor, you make a call to the A constructor, with special syntax as follows:
B() {
super(42);
// because we are calling the constructor that takes an int, we must supply
// one. It's up to you to figure out what values should be supplied. Maybe
// you wanted to take an int in the B constructor, and pass it along?
System.out.println(" class B");
}
2) You have an int x; declared in both class A and class B. This is probably not what you want. As noted, each B instance already contains an int x - the one that it automatically gets because B extends A.
Class A does not have a default constructor because you didn't write one (but you did write one that takes an int parameter).
Class B has a no-arg default constructor. It needs to call a superclass constructor, but it can't because there is no such thing in class A.
Related
Let's me explain my question by code example, I have this code:
class A {
public A() {
System.out.println("In class A constructor");
}
static {
System.out.println("In class A static initializer");
}
}
class B extends A {
static {
System.out.println("In class B static initializer");
}
public B() {
System.out.println("In class B constructor");
}
}
public class C extends B {
public C() {
System.out.println("In class C constructor");
}
static {
System.out.println("In class C static initializer");
}
public static void main(String[] args) {
new C();
}
}
If we run this code, we will have the console print out:
In class A static initializer
In class B static initializer
In class C static initializer
In class A constructor
In class B constructor
In class C constructor
As you can see, all the static field in the class is being called first from Class A down to Class B then Class C. And then I read about the Static Initializers
A static initializer declared in a class is executed when the class is
initialized
I know that if we just look into the constructor. When we call new C(), we will have a call stack:
"5" Object()
"4" A() calls super()
"3" B() calls super()
"2" C() calls super()
"1" main() calls new C()
So why do all static initializers in Class A, B, C finish first, then the constructors? Does that mean the classes in Java initialized in stack sequences if they have IS-A relationship?
I think my question can be answer through here Detailed Initialization Procedure but I am lost with all the details. Hope someone can explain it to me.
Constructors run after the instance has been created.
The static initializer for C has to finish before the instance of C is created because:
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
T is a class and an instance of T is created.
The static initializer for B has to run before C, and A before B, because:
Before a class is initialized, its direct superclass must be initialized,
I don't know exactly what you mean by "stack sequence"; let me see if I can explain how I expect this goes, which is how I think it has to go.
The Java runtime starts executing C.main; in order to do that, it must initialize the C class object (not an instance of C, but the class C).
It goes and gets the C Class and determines, from that, that it must have B before it does anything like execute the C static initializer (the static { ... } thing). It goes and gets the B class.
It determines that, before it executes the B static initializer, it needs A, and goes and gets it. Keep in mind that there are things about A that B does not know except that they're contained in A, so it cannot do anything at all with B before the A class is there and initialized.
Having gotten A, it might determine that it needs the Object class object (the language-twisting necessary to talk about the language you're implementing in language runtimes must drive those people NUTS) and to run its static initializer.
Once it has put the Object class in memory and run its static initializer, it is ready to run the static initializers of A, B, and C, in that order. This completes the portion of setting up the C class as far as the stuff we're talking about here. You could call that "stack order"; it's the same as if C had called B, which called A, which called Object, and in fact that may be how it's implemented (or how it might be implemented).
NOW it's ready for the C constructor to make an instance of C, and the same kind of logic applies. It cannot execute a bit of the C constructor until B is constructed, and not a bit of the B constructor until A is constructed, and not a bit of A until Object is constructed. That's why super() must be the first thing in a constructor if it's going to be there; if it isn't there, the runtime executes a no-arg constructor on the superclass.
You could say that the static initializers at each level are started, but their first step is to run the static initializers of their superclass, and similarly for constructors. Whether you say the one code is started and then the super code is run, or that the super code is run before the target code, doesn't seem to me to make much difference.
I'm not a Java runtime expert, but these sequences HAVE to be this way. If you alter the static initializer of A, the above sequence dictates when that code has to be run; I don't see any other way it could work.
class Time
{
public static void main (String args[])
{
Son obj = new Son();
}
}
class Father // Super Class
{
Father(int x, int y) // parameterized constructor
{
int a = x;
int b = y;
System.out.println("Super Class Constructor a = "+a);
System.out.println("Super Class Constructor b = "+b);
}
Father(int z) // parameterized constructor
{
int d = z;
System.out.println("Super Class Constructor d = "+d);
}
}
class Son extends Father // Sub Class
{
Son() // default constructor
{
super(100);
super(10, 20); // Problem is here
int c = 200;
System.out.println("Sub Class Constructor c = "+c);
}
}
My question is can we use multiple super ( ) in subclass constructor as i want to initialize two super class Parameterized constructor. If it is not possible then how can i do this?
Your code is simply wrong. A constructor in Java has to always call exactly one super class constructor. There is no such thing as writing down super() twice in the same constructor.
In other words: the very first statement in a constructor is a call to a super-class constructor. If you don't put such a call there, the compiler will insert a call to super() behind the covers.
In that sense: when you are a beginner, and the compiler gives you an error message; the thing to do: turn to a good book or online resource.
My polemic answer is you don’t want to do that (feel free to challenge me). You want to design you superclass (Father) in such a way that it only takes one super constructor call to construct and initialize it so that it is ready for use.
In your example you haven’t got any fields in Father, so any of your constructors should be good enough for that. if you’re happy with the constructors you have but still want the output from both, there are a couple of options. First, you may add a three-arg constructor Father(int x, int y, int z) as Nghia Do suggested in a comment. You don’t need to delete the other two constructors if you prefer to have all three. Second, you may put in a method call instead of the second super call, and write a method in Father to print the message and do what other work you require. For the sake of code reuse, you ought to have the two-arg constructor call the same method rather than having the code duplicated.
Think what would happen if you had a class with two constructors and you needed to call both — if that was allowed. This would be a tricky bug waiting to happen. There would always be a risk that someone forgot to call both. You’d end up with some half-constructed object, and no one would know when something would go wrong when you used it.And when that happened, it would be far from obvious that it was due to the forgotten second constructor call. As I said, you don’t want that. The rule that Java always calls exactly one super constructor is a good one.
There is two classes Super1 and Sub1
Super1.class
public class Super1 {
Super1 (){
this.printThree();
}
public void printThree(){
System.out.println("Print Three");
}
}
Sub1.class
public class Sub1 extends Super1 {
Sub1 (){
super.printThree();
}
int three=(int) Math.PI;
public void printThree(){
System.out.println(three);
}
public static void main(String ...a){
new Sub1().printThree();
}
}
When I invoke the method printThree of class Sub1 I expected the output to be:
Print Three
3
Because Sub1 constructor calling the super.printThree();.
But I actually get
0
Print Three
3
I know 0 is default value of int but how it is happening ?
You're seeing the effects of three things:
Default super-constructor calls, and
Instance initializers relative to super calls, and
How overridden methods work
Your Sub1 constructor is really this:
Sub1(){
super(); // <== Default super() call, inserted by the compiler
three=(int) Math.PI; // <== Instance initializers are really inserted
// into constructors by the compiler
super.printThree();
}
(Surprising, I know, but it's true. Use javap -c YourClass to look. :-) )
The reason it looks like that is that the superclass must have a chance to initialize its part of the object before the subclass can initialize its part of the object. So you get this kind of interwoven effect.
And given that that's what Sub1 really looks like, let's walk through it:
The JVM creates the instance and sets all instance fields to their defaults (all bits off). So at this point, the three field exists, and has the value 0.
The JVM calls Sub1.
Sub1 immediately calls super() (Super1), which...
...calls printThree. Since printThree is overridden, even though the call to it is in the code for Super1, it's the overridden method (the one in Sub1) that gets called. This is part of how Java implements polymorphism. Since three's instance initializer hasn't been run yet, three contains 0, and that's what gets output.
Super1 returns.
Back in Sub1, the instance initializer code for three that the compiler inserted (relocated, really) runs and gives three a new value.
Sub1 calls printThree. Since three's instance initializer code has now run, printThree prints 3.
With regard to this instance initializer code getting moved into the constructor, you might be wondering: What if I have more than one constructor? Which one does the code get moved into? The answer is that the compiler duplicates the code into each constructor. (You can see that in javap -c, too.) (If you have a really complicated instance initializer, I wouldn't be surprised if the compiler effectively turned it into a method, but I haven't looked.)
It's a bit clearer if you do something really naughty and call a method during your instance init: (live copy)
class Super
{
public static void main (String[] args) {
new Sub();
}
Super() {
System.out.println("Super constructor");
this.printThree();
}
protected void printThree() {
System.out.println("Super's printThree");
}
}
class Sub extends Super
{
int three = this.initThree();
Sub() {
this.printThree();
}
private int initThree() {
System.out.println("Sub's initThree");
return 3;
}
protected void printThree() {
System.out.println("Sub's printThree: " + this.three);
}
}
Output:
Super constructor
Sub's printThree: 0
Sub's initThree
Sub's printThree: 3
Note where "Sub's initThree" came in that sequence.
When the instance is created, the Sub1 constructor is called.
The first instruction in any constructor is a call to the superclass constructor. If you don't have an explicit call, there will be an implicit call to the no-args constructor of Super1.
The no-args constructor is calling this.printThree(). This method is overridden in Sub1. Now, this part may be confusing, but even if the code is in the superclass, this.method() still refers to the overriding method.
So it's calling the printThree() in Sub1, which prints the uninitialized value of the variable three - 0.
Now that the superclass's constructor is done, it completes Sub1 constructor, which uses super.printThree(). Since it specifically says super, the method from Super1 is used rather than the overriding one. This prints the Print Three.
Now the Sub1 constructor is also done, and main calls the new instance's printThree(). Now three is already initialized, so you get the output 3.
While previous answers gave you clear answer to what is happening, they did not gave you any pointers on how to avoid your problems in the future, so I would also like to add my input on this.
If you are going to inherit, then you should make the super class constructor as "dumb" as possible. For example
public class Super{
private int a,b;
public Super(int a, int b) {
this.a = a;
this.b = b;
}
//all the methods operating on the data provided by constructor
}
and then having sub constructor like this
private int c,d;
public Sub(int a, int b) {
super(a,b);
c = a;
d = b;
}
Is perfectly fine and is going to give you minimal side-effects, while keeping the functionality of the parent class.
But having
public Super(){
method1();
method2();
}
and then having sub do this
public Sub(){
super.method1();
super.method2();
}
Is really asking for trouble and possible hard to track bugs. The less the object does during initialization, the better, because it gives the childs flexibility.
Managing inheritance is like being dumb manager vs clever manager. Dumb manager calls Tim and Tracy employee, because they are both employees, and their jobs as Accountant and HR manager are just tags. Clever manager knows Tim and Tracy are Accountant and Manager and does not care that much that they are basically just employees.
This is my simple java code. When I compile/run the program, Eclipse IDE shows a syntax error. The syntax error does not make any sense to me
class A {
int x;
int z;
int s;
A(int a,int b) {
x=a;
z=b;
}
void display() {
System.out.println("x+y :"+(x+z));
}
}
class B extends A
{
B(int a, int b, int c) {
x=a;
z=b;
s=c;
}
void display() {
System.out.print("In B class...");
System.out.println("x+y+s :"+(x+z+s));
}
}
public class Simple {
public static void main(String[] args) {
A ob=new A(10, 20);
B ob2=new B(20, 30, 40);
ob.display();
ob2.display();
}
}
In your class A, you've provided a constructor that accepts two parameters and you've not defined a parameter-less constructor for A. As such, when you try to instantiate B, which extends A, it fails since it cannot call A()
There're two ways to resolve this:
Provide a parameter-less constructor for A
Something like:
class A{
int x;
int z;
int s;
public A(){
}
public A(int a,int b){
x=a;
z=b;
}
void display(){
System.out.println("x+y :"+(x+z));
}
}
Call super(a, b) as the first statement in the constructor of B.
For example:
class B extends A
{
B(int a, int b, int c){
super(a,b);
x=a;
z=b;
s=c;
}
void display(){
System.out.print("In B class...");
System.out.println("x+y+s :"+(x+z+s));
}
}
If you're new to Java, you might want to read about Inheritance and Creating Objects in Java
There are a few things that needs to be considered here: -
When you declare a class without any constructor, the compiler does that for you by inserting a default constructor, that is an empty zero-arg constructor..
If you have explicitly declared your one-arg constructor(or any other constructor), compiler doesn't add any default constructor.
Every time you make an instance of a class, constructors are invoked from top-down in inheritance hierarchy. So, if you are not using inheritance, then instantiating a class first invokes the Object class's constructor (which is the top-level class of any inheritance or non-inheritance hierarchy)
We invoke super class constructor, using super(), but if we haven't done it explicitly, compiler will add this for us.. If you are adding it by yourself, make sure it should be the first statement of a constructor.. You can pass argument to super, to call super class's non-zero arg constructor, but compiler adds only zero-arg super().
Now, Having said all that, lets move to your code..
In your class A, you have declared a three-arg constructor, so compiler won't add any.. So, precisely you don't have any zero-arg constructor there.
Now, your class B extends A and hence instantiating that class will invoke super-class constructor which is A here.
Now, since you have not added any super() call in your B class, compiler will add there automatically.
But, what compiler adds is: super(), which will call A's zero-arg constructor, which we saw that you don't have.
So, how you can solve that??
Either add a default constructor to your class A: -
class A {
public A() {
}
}
Or add an explicit super() call as your first statement in B's constructor to invoke your 3-arg A's constructor : -
class B extends A {
public B(int a, int b) {
super(a, b, 19);
/* More Code */
}
}
Similar, to super(), you can also use this() in your constructor, to invoke the same class's constructor. Same rule applies to this().. It should be the first statement in your constructor..
So, we can see that we can either have super() or this() in our constructor.
I hope this much information will solve at least your current problem.
The (lack of) formatting makes it hard to read. The start of the definition of class A is outside the code block.
It looks like you didn't define the int field s in class B. Should be:
class B extends A
{
int s;
...
}
EDIT: looks like you reformatted and changed it while I was posting my answer...
Where is the class a definition " class A"? Where are the data fields definitions (x, z, s for class B and x,z for class A)? Please edit your post
After the post was edited, I've tried to compile it and the error should be as follows:
Simple.java:17: cannot find symbol
symbol : constructor A()
location: class A
B(int a, int b, int c){
^
1 error
This means that you should call some constructor of class A when you create a class B because B extends A. You don't have default constructors because you created your own.
Rewrite the constructor of B like this and you'll be fine:
B(int a, int b, int c){
super(a,b);
s=c;
}
Good luck!
You have explictly declare constructor of Class A, so the class B should explict call his parent's - class A - constructor.
Add below code into the class B's constructor:
super(a, b);
Then your constructor of class B will be looks like:
B(int a, int b, int c) {
super(a, b);
x = a;
z = b;
s = c;
}
PS, pls take care of the formatting of the code that your pasted. It's hard to read.
your super class has an two args constructor, when you extend class A in class B's constructor you have call your superclasses's two args constructor.
change your sub class constructor code to this.
B(int a, int b, intc) {
super(a,b); //this has to be in the first line inside the constructor.
//do your things
}
this link explains it
If you want to set the values to the properties that are defined in the super class, call super() method in the sub class constructor.
So, Your sub class constructor should look like as follows
public B(int a, int b, int c){
// The following statement will automatically sets the values to the base class properties (which are already derived into derived class).
super(a, b);
// No Need of setting the values to the super class properties... The above statement will automatically sets the values...
s=c;
}
First off, posting the error given by eclipse would be helpful.
But in any case, your syntax errors are stemming from the fact that you aren't defining the datatype of your variables, such as x, z, s, etc.
For example,
int x = a;
int z = b;
etc.
Clarification: this question is not about access modifier
Confirmed that B.m() and b.m() statements both works in the following code:
class A {
static void m() { //some code }
}
class B extends A {
}
class Example {
public static void main (String [] args) {
B.m(); // running A's m() static method
}
public void try() {
B b = new B();
b.m(); // running A's m() static method
}
}
My question is can we said "static method is inherited"?
if "inherited" is the correct term, if we add a method to B class we same signature of the static class:
class A {
static void m() { //some code }
}
class B extends A {
static void m() { //some code }
}
class Example {
public static void main (String [] args) {
B.m(); // running B's m() static method
}
public void try() {
B b = new B();
b.m(); // running B's m() static method
A a = new B();
a.m(); // running A's m() static method, no polymorphism
}
}
In this case, notice that we have no polymorphism, is it the correct term to said that "static method is inherited but not overridden, subclass static method hide superclass static method"?
Last doubt, for these 2 terms, "inherited" and "overriden", which one is directly tied to the term "polymorphism" ?
Yes, I think "inherit" is the correct term here, even if it's not as descriptive as it might be. From section 8.4.8 of the Java Language Specification:
A class C inherits from its direct superclass and direct superinterfaces all non-private methods (whether abstract or not) of the superclass and superinterfaces that are public, protected or declared with default access in the same package as C and are neither overridden (§8.4.8.1) nor hidden (§8.4.8.2) by a declaration in the class.
That doesn't specify instance methods, but there are specific restrictions on what is allowed to hide or override what, which wouldn't make sense if static methods were not inherited.
Really though, I would simply view static methods as "accessible without qualification" rather than anything else, given that they don't take part in polymorphism etc. I think it's worth being very clear about that - for example, one static method can hide an inherited one, but it can't override it.
In other words, while I think "inherit" is technically correct, I would try to avoid using it without any further explanation.
For your second question, I'd say that based on the above, overriding is tied to polymorphism, but inheriting isn't necessarily.
(I would also strongly advise you to avoid calling static methods "via" variables, and also to use the name of the class which declares the static method wherever you specify the name at all. I know that's not part of the question, but I thought I'd just add it anyway...)
I think trying to apply words like 'inherited' and 'overridden' to this sort of thing is not productive. It's misleading because it gives the impression there is something comparable of what goes on with virtual instance methods, and you point out there isn't.
(But as Jon Skeet points out, the Java language spec doesn't agree with me, it groups these together in the same section.)
Guys I would like to share my knowledge in java with all java lovers out there!
First of all let me tell you that static members are those members which can be accessed directly without creating an object of that particular class, when static members of a class is used in some other class then it should be used by specifying the class name .(dot) static member's name(e.g. A.i in the following example), and also if any subclass class is getting inherited from a super class which has static members and if both subclass and super class are in the same package then that static members can be accessed from the base class without even using the class name of the super class. Please go through the
Example:
package myProg;
class A
{
static int i = 10;
A()
{
System.out.println("Inside A()");
}
}
class B extends A
{
public static void main(String[] args)
{
System.out.println("i = " + i); //accessing 'i' form superclass without specifying class name
System.out.println("A.i = " + A.i); //again accessing 'i' with the class name .(dot) static member 'i'
/*
we can also use the super class' object in order to access the static member compiler
will not show any error but it is not the exact way of using static members. static members are created
so that it could be used without creating the class object. see below the usage of object to use the
static member i.
*/
A obj = new A(); //creating class A object and A() also gets called
obj.i = 20;
System.out.println("obj.i = " + obj.i);
}
}
/*
This program was to show the usage of static member. Now, lets discuss on the topic of static member inheritance.
SO GUYS I WOULD LIKE TO TELL YOU THAT STATIC MEMBERS ARE NOT INHERITED. This undermentioned program is
to show the inheritance of static members.
*/
class A
{
static int i = 10; //initially the value of i is 10
static int j = 20; //lets use one more static member int j, just to see the value of it through class A, and B
static
{
/*
This is static initialization block(SIB) of class A,
SIB gets executed first in the order of top to bottom only one time
when the class is loaded.
*/
System.out.println("A-SIB");
}
}
class B extends A
{
static
{
i = 12;//trying to modify the i's value to 12
System.out.println("B-SIB");
}
}
class D extends A
{
static int k = 15;
static
{
System.out.println("D-SIB");
}
}
class C
{
public static void main(String [] arhs)
{
System.out.println("D.k: " + D.k);
/*here we are trying to access the static member k from class D,
it will try to search this class and then that class
will be loaded first i.e. SIB of class D will be loaded and SOP
statement of class D will be printed first. When the class loading
is done then the compiler will search for the static int k in class
D and if found SOP statement will be executed with the value of k.
*/
/*
ONE GROUND RULE: as soon as the compiler see this statement the compiler will load
class D into the memory, loading of class into memory is nothing but
storing all the static members (i.e. static constant & SIBs) into the
memory.
*/
System.out.println("B.i: " + B.i);
/*Now, this is what we are talking about... we think that static int i's
value is there in class B and when we write B.i it compiles and executes
successfully BUT... there compiler is playing a major role at this statement...
Try to understand now... we know that class B is the subclass of class A
BUT when the compiler sees this statement it will first try to search
the static int i inside class B and it is not found there, then since it is
the subclass of A, the compiler will search in class A and it is found
there. NOW, WHEN STATIC INT I IS FOUND IN CLASS A THE COMPILER WILL CHANGE
THIS STATEMENT B.i TO A.i and the class B WILL NOT AT ALL BE LOADED INTO
THE MEMORY BECAUSE STATIC I IS ONLY PRESENT IN CLASS A. But in the previous
statement static int k is present inside class D so when we try to access k's value
the class D will be loaded into memory i.e. SIB will be executed and then
the SOP statement of the value of k. USING B.i IS NOT WRONG BUT COMPILER
ASSUMES THAT THE PROGRAMMER HAS MADE A MISTAKE AND IT REPLACES THE CLASS NAME
B.i TO A.i. Thus this show that static members are not inherited to the subclass.And
therefore the vaue of i will NOT BE CHANGE TO 12 AS YOU CAN SEE IN THE SIB OF
CLASS B, it will be 10 only..
*/
System.out.println("A.j: " + A.j);//this statement will be executed as it is, compiler will not make
System.out.println("A.i: " + A.i);//any modifications to these statements.
System.out.println("B.j: " + B.j);//again compiler will modify this statement from B.j to A.j
}
}
Guys if you still have any confusion mail me at this email-id:
pradeep_y2k#yahoo.co.in
Regards
Pradeep Kumar Tiwari
Ok static methods cannot be overridden but can be redefined in other words its called hiding
check this http://www.coderanch.com/how-to/java/OverridingVsHiding they explain pretty well