Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Something interesting about two overloaded constructors of FileInputStream in Java 7 API

Tags:

Before talking about FileInputStream, I am starting with a scenario where there are two perfectly valid, overloaded methods but where the compiler will get confused and then report a compile-time error in response to certain inputs.

Here are the methods.

double calcAverage(double marks1, int marks2) {      return (marks1 + marks2)/2.0;   }    double calcAverage(int marks1, double marks2) {      return (marks1 + marks2)/2.0;   }  

Here is the complete code showing the use of the methods:

class MyClass {     double calcAverage(double marks1, int marks2) {               return (marks1 + marks2)/2.0;     }     double calcAverage(int marks1, double marks2) {              return (marks1 + marks2)/2.0;     }     public static void main(String args[]) {             MyClass myClass = new MyClass();             myClass.calcAverage(2, 3);     }   }   

Because an int literal value can be passed to a variable of type double, both methods are acceptable candidates for literal values 2 and 3, and therefore the compiler fails to decide which method to pick.

This is where I get confused when I take the above concept with me, dive further into the Java 7 API to the FileInputStream class, and study about two overloaded constructors of that class.

  1. public FileInputStream(String name) throws FileNotFoundException {.....}
  2. public FileInputStream(File file) throws FileNotFoundException {.....}

According to the Java 7 API source code, the definition of the version that takes a String object as the argument is:

public FileInputStream(String name) throws FileNotFoundException {          this(name != null ? new File(name) : null);   }  

Now, if "name" is indeed null, this(name != null ? new File(name) : null); evaluates to this(null); which in turn is equivalent to invocation of FileInputStream(null); but then both FileInputStream(String) and FileInputStream(File) become possible choices to be invoked with a null value. Does it not give rise to ambiguity? So, isn't there a compile-time error for that?

I do understand that eventually a FileNotFoundException is raised, but it is a separate issue which comes later. How is the ambiguity resolved before that?

like image 395
Mohammad Ali Asgar Avatar asked Jun 26 '14 06:06

Mohammad Ali Asgar


People also ask

Why do we need to use overloaded constructors?

The constructor overloading enables the accomplishment of static polymorphism. The class instances can be initialized in several ways with the use of constructor overloading. It facilitates the process of defining multiple constructors in a class with unique signatures.

Which are reasons to overload a constructor in Java?

If we want to have different ways of initializing an object using different number of parameters, then we must do constructor overloading as we do method overloading when we want different definitions of a method based on different parameters.

What does an overloaded constructor do?

The constructor overloading can be defined as the concept of having more than one constructor with different parameters so that every constructor can perform a different task. Consider the following Java program, in which we have used different constructors in the class.

Can we overload the constructors if yes then which type of polymorphism is it?

It is compile-time polymorphism because the constructor overload to be executed is chosen at compile time.


1 Answers

Your error is here:

Now, if "name" is indeed null, this(name != null ? new File(name) : null); evaluates to this(null); which in turn is equivalent to invocation of FileInputStream(null);

It actually evaluates to this((File) null) -- that is, a null value explicitly typed as File. This is because the expression name != null ? new File(name) : null has to have a type, and that type is the most specific type of the two alternatives. In this case, one alternative is typed as File and the other is typed as null, so the most specific common type is File.

That's why it's able to unambiguously resolve it to the FileInputStream(File) constructor. It's analogous to:

File file = null; new FileInputStream(file); 
like image 183
yshavit Avatar answered Nov 27 '22 08:11

yshavit