Mohammad Ali Asgar
Mohammad Ali Asgar

Reputation: 734

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

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?

Upvotes: 22

Views: 897

Answers (2)

yshavit
yshavit

Reputation: 43391

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);

Upvotes: 18

mth
mth

Reputation: 677

The type of the result of the conditional operator is File. The JLS defines:

If one of the second and third operands is of the null type and the type of the other is a reference type, then the type of the conditional expression is that reference type.

So there is no ambiguity about which constructor should be called

Upvotes: 15

Related Questions