What's wrong with the following java code? - java

I am getting some argument errors while compilation. don't know what wrong this.
I was expecting the output would be bj. since Class a doesn't have default constructor so at compilation time default constructor would be created by JVM. and the remaining output would be bj. Am I missing something?
class a
{
a(String b)
{
System.out.println("this is a");
}
}
class b extends a
{
b()
{
System.out.println("b");
}
}
class c extends b
{
c(String j)
{
System.out.println(j);
}
public static void main(String...k)
{
new c("J");
}
}
The error is shown below:
javac construct.java
construct.java:12: error: constructor a in class a cannot be applied to given ty
pes;
{
^
required: String
found: no arguments
reason: actual and formal argument lists differ in length
1 error

since Class a doesn't have default constructor so at compilation time default constructor would be created by JVM
The default constructor is created only if you don't define a custom constructor.
Your IDE should have shown you the following message on b() declaration:
There is no default constructor available in 'package.a'
When you tried to instantiate b, it did an implicit call to super() but found only a(String b) instead of a(). As the error message says, a(String b) expected a String but got no arguments.
The solution is either to create the parameterless a() constructor or call the a(String b) constructor in class b constructor.
class b extends a
{
b()
{
super(""); // call to class a constructor passing some string as argument
System.out.println("b");
}
}

By convention you should name Java Classes in upper case letters
When new C("J"); is executed, it calls the constructor of class C. But as class C is extending class B, JVM will add
C(String j)
{
super(); //added by JVM - calls the constructor of super class
System.out.println("j");
}
So the constructor of class b is invoked and as it is also extending class A.
B()
{
super(); //added by JVM
System.out.println("b");
}
Now problem arises. As JVM will add default constructor in its implicit call. But there is no constructor defined with no-arguments. That's why you are getting an error. You can add super(""); in constructor B to resolve the error or create a constructor with no parameters.

Related

Confused with Constructors and Subclasses

I'm having trouble understanding the concept of using constructors with subclasses.
Here is the parent class:
public class A
{
public A()
{
System.out.println("The default constructor of A is invoked");
}
}
The child class:
public class B extends A
{
public B(String s)
{
System.out.println(s);
}
}
And my main method:
public class C
{
public static void main (String[] args)
{
B b = new B("The constructor of B is invoked");
}
}
When I run C, the output I get is
The default constructor of A is invoked
The constructor of B is invoked
What I don't understand is why the message from class A is getting output. Because you pass in a string argument to the constructor of the B class, shouldn't it just print out s? In other words, shouldn't the output simply be:
The constructor of B is invoked
Thanks in advance, I really appreciate any help you guys can give.
From the docs
If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem.
So even though you've not explicitly called the super class constructor, the compiler inserts a statement called super() in the constructor of class B.
This is how the class B constructor would look post compilation.
public B(String s){
super(); // this is inserted by the compiler, if you hadn't done it yourself.
System.out.println(s);
}
After compilation class B -
public class B extends A{
public B(String s){
super();
System.out.println(s);
}
}
And why! logical answer is child can not be existed without parent, so parent is initialized fast then child.
Technically - if you do not explicitly invoke super class constructor compiler will do it for you. what exactly happened in your case.
A good experiment would be if you invoke the super class contructor explicitly which help you understand this more closely-
public class B extends A{
public B(String s){
System.out.println(s);
super(); // invoking super later
}
}
you get an compilation error -
error: call to super must be first statement in constructor
So In case you are explicitly invoking the super class constructor, then you have to invoke at the start of constructor which should be first statement.
The reason it does this is that B needs to have all the fields in A if B is indeed a subclass of A. Therefore, when you call the constructor
B b = new B("The constructor of B is invoked");
It calls the default constructor of A to initialize A's fields, thus B is actually logically doing
public class B extends A
{
public B(String s)
{
super();
System.out.println(s);
}
}
where super just calls A's default constructor. If the compiler did not do this, you would have uninitialized fields in B since it inherits from A!

inheritance in java (compile error)

this is my program:
class A{
A(int a){
}
class B extends A{
B(){
}
}
}
when I compile I have an error:
C:\Users\Public\Documents\AB.java:6: error: constructor A in class A cannot be applied to given types;
B(){
^
required: int
found: no arguments
reason: actual and formal argument lists differ in length
and it fixed by this change in my code:
class A{
A(int a){
}
A(){
}
class B extends A{
B(){
}
}
}
but I don't understand why?
thanks for any help.
Since your A class declares a constructor
A(int a){
}
then any code that wants to instantiate A needs to do so with that constructor. Something like
A a = new A(42);
You also declare a child class, B. Since B is an A, in addition to its constructor, it must call the parent class' constructor. This is done implicitly by the compiler. Say you had
class A{
A(){
}
class B extends A{
B(){
// super(); injected by compiler
}
}
If you don't have a no-arg constructor, then the compiler doesn't know which constructor call to inject. You need to explicitly declare the super(...) call.
class A{
A(int a){
}
class B extends A{
B(){
super(42);
}
}
Think of it this way: you can't construct an A without the constructor call. When you construct a B, you are, through inheritance, also constructing an A, so you need that same constructor call.
You need to have a default constructor (no-argument) in A. The first implicit call of a constructor of any class is super(). But there is not super() method in the superclass. You can either explicitly call super(5) or some value, or create a default constructor in A:
A() {}
When instance of class B is created a default call to super() constructor with no parameters is made. Each class has a default constructor with no parameters, unless a different constructor is provided explicitly.
As you have explicitly provided class A with a constructor that takes one parameter, it no longer has default constructor with no params, so you need to define it.
Whenever we extend a class, by default it calls super() (it has no params). In your case , it dint get the matching A() , hence it resulted in compiler error.
Whenever u write this, what happens internally is :
class A
{
A(int a)
{
}
class B extends A
{
B()
{
//Internally compiler calls super()
super();//In your case, it dint get the matching constructor
}
}
}

calling hierarchy in constructors of super and base class

class a
{
a(){System.out.println("A");}
}
class b extends a
{
b()
{
super();
System.out.println("B");}
}
class c extends b
{
c(){System.out.println("c");}
}
class last
{
public static void main(String aaa[])
{
c obj = new c();
}
}
Output Comes as:
A
B
C
Shouldn't it be:
A
A
B
C
because of super keyword
super(); is always there if you don't specify explicitly. Java only adds automatic call if you don't specify it explicitly.
So your code
B() {
super();
System.out.println("B");
}
is same as
B() {
System.out.println("B");
}
No. If you have a call to super within the constructor, the automatic call doesn't get added. The compiler only adds the automatic call if you leave yours out. So the super(); line in b is unnecessary, as that's exactly what the compiler will add for you (a call to the default constructor). That is, these two bits of source result in identical bytecode:
// This
class b {
b() {
}
}
// Results in the same bytecode as this
class b {
b() {
super();
}
}
The reason for being able to call the superclass constructor directly is for passing arguments to it, since the compiler will only ever add calls to the default constructor (and will complain if there isn't one on the superclass).
super(); is called once within any constructor through inheritance tree, either you do it explicitly or it is done implicitly. So you shouldn't expect that "A" will be printed twice.
This won't compile:
b()
{
super();
super();
System.out.println("B");
}
Error message: Constructor must be the first statement in a constructor.
It means that you are not allowed to call super() multiple times in a constructor.
If you create sub class of some other class, with extends keyword, then java compiler puts super() call as first line of your constructor (in case you have not done that yourself).
In your example, the class a extends (by default) java.lang.Object() and after compilation the first line is call super() which calls Object default constructor.
SO before code in sub class constructor is ran, the code in its super class constructor is ran.
Why is A not printed multiple times? Because Java compiler adds super() in the beginning of constructor only if you have not done that yourself. (For example, you might want to call super class constructor that takes in some parameters)
Hopefully that clarifies things a little bit.
package threaddemo;
public class NewClass {
NewClass() {
System.out.println("hello");
}
}
class Child extends NewClass {
Child() {
System.out.println("child");
}
public static void main(String []ar) {
Child c1=new Child();
}
}

Does JVM call default Constructor of Anonymous Class to create instance?

Does JVM call default Constructor of Anonymous Class to create instance.
My understanding may be stupid for that. I think, even if Reflection API is used to create an instance, there will be at least Default Constructor. Anonymous Class have a Default Constructor? Otherwise, how JVM or whatever create instance?
Yes it does. You can even use other constructors through specifying parameters:
Given
public abstract class A {
String str;
public A(String str){
this.str=str;
}
public abstract void doSomething();
}
You can do
...
A a = new A("Hello World") {
public void doSomething() {
System.out.println(str);
}
};
a.doSomething();
When a class doesn't have an explicit constructor, it has an implicit default empty constructor. That is called, just as any other constructor would be called.
It appears to me that unlike normal classes, anonymous classes has different behaviour associated with implicit constructors.
When you define a normal class, compiler can implicitly insert only a no-arg constructor.
But with anonymous class you can get (implicitly by a compiler) all the constructors the superclass has.
Say we have a class:
class A {
A(int i) {}
A(String s) {}
}
If we subclass it as follows...
class B extends A {}
...we get a compilation error because compiler tries to do this:
class B extends A {
B() {
super(); // Error: there's no no-arg superclass constructor!
}
}
But when we create an anonymous class it implicitly creates constructors as defined for a superclass (A)
A a1 = new A(1) {}; // OK. Uses (int) constructor
A a2 = new A("") {}; // OK. Uses (String) constructor
A a3 = new A() {}; // Error. There's no no-arg constructor
As if our anonymous class has these constructors
X(int i) {
super(i);
}
X(String s) {
super(s);
}
Anonymous classes have a default no args constructor that is called once by the JVM. Since an anonymous class has no name, it is not possible to define a constructor for an anonymous class. If your class requires a constructor, you must use a local class instead.
In any case, a constructor is called to initialize newly created object. Anonymous class has default constructor, which initialize the fields of the class, if any, and calls constructor of the superclass.

Default constructor not getting called

Why default constructor(same class) is not getting called while calling the default constructor but the default constructor of parent class is getting called - Why?
class A{
A(){
System.out.println("A()");
}
}
class B extends A{
B(){
System.out.println("B()");
}
}
class C extends B{
C(){
System.out.println("C()");
}
C(int i){
System.out.println("<------>"+i);
}
}
public class sample {
public static void main(String[] args) {
C c = new C(8);
}
}
Output:
A()
B()
<------>8
This is how the language works: only one constructor is called per class, unless you specifically invoke one constructor from another (like so: How do I call one constructor from another in Java?).
It's Java's rule. If you want your behaviour you must use this() as first instruction in C(int).
as said before it's standard behavior of java if you want some code to be always called on construction of an object you can use an initializer
class A{
{
System.out.println("A()");
}
A(){
}
}
Based on your class declaration for class 'C', you are overloading the constructors and thus when you create a new 'C' object and pass in an integer with the following code:
C c = new C(8);
You are calling the constructor
C(int i){
System.out.println("<------>"+i);
}
instead of the constructor
C(){
System.out.println("C()");
}
therefore it doesn't print out "C()". Overloading constructors/functions depends on the type and number of parameters being passed in. On top of that, only 1 constructor gets called for each object being created.

Categories