Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java constructor is not so intuitive. Or perhaps it's not Java, it's C# that is not intuitive

Given this Java code, this outputs 0 and 4:

class A{
   A() {  print();   }
   void print() { System.out.println("A"); }
}

class B extends A{
   int i =   Math.round(3.5f); 
    
   public static void main(String[] args){
      A a = new B();
      a.print();
   }
   void print() { System.out.println(i); }
}

And with this identical C# code, this outputs 4 and 4

using System;

class A{
   internal A() {  print();   }
   virtual internal void print() { Console.WriteLine("A"); }
}

class B : A{
   int i =  (int) Math.Round(3.5f); 
    
   public static void Main(string[] args){
      A a = new B();
      a.print();
   }
   override internal void print() { Console.WriteLine(i); }
}

Though I figure out that the output should be 4 and 4 on Java, but the answer is actually 0 and 4 on Java. Then I tried it in C#, the answer is 4 and 4

What gives? Java rationale is, during construction of B, A is still initializing(consequently I posit B is still initializing if Java said A is still initializing), so the default value should be 0. Hence the output is 0 and 4 in Java.

Why does C# constructor behavior differ from Java, or vice versa?

like image 731
Hao Avatar asked May 16 '12 03:05

Hao


People also ask

Which constructor is not possible in Java?

Java constructor can not be static One of the important property of java constructor is that it can not be static. We know static keyword belongs to a class rather than the object of a class. A constructor is called when an object of a class is created, so no use of the static constructor.

What is constructor in Java?

A constructor in Java is a special method that is used to initialize objects. The constructor is called when an object of a class is created.

Why we dont use constructor in Java?

It is a special type of method which is used to initialize the object. Every time an object is created using the new() keyword, at least one constructor is called. Note: It is not necessary to write a constructor for a class. It is because java compiler creates a default constructor if your class doesn't have any.

Can constructor be overriden?

Constructor looks like method but it is not. It does not have a return type and its name is same as the class name. But, a constructor cannot be overridden.


1 Answers

It's happening because of differences in the ordering of object initialisation in constructors.

What is happening in Java:

  • (empty, implicit) Constructor of B is called
  • Superclass Construtor of A is called (prints 0 since i is uninitialised)
  • i is initialised after the superclass constructor
  • print() is called (prints 4)

What is happening in C#:

  • (empty, implicit) Constructor of B is called
  • i is initialised before calling the superclass constructor
  • Superclass Construtor of A is called (prints 4 since i is already initialised)
  • print() is called (prints 4)

Neither is right or wrong - it's just a difference in how the compiler orders the construction operations. Personally I think the Java ordering is a marginally more logical, because it makes sense to me that the superclass is fully constructed before the subclass initialisation takes place.

Either way, because the logic can get quite complicated, I'd suggest that you avoid calling virtual methods during object construction in general.

like image 149
mikera Avatar answered Oct 30 '22 19:10

mikera