Reputation: 734
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.
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
Reputation: 43391
Your error is here:
Now, if "name" is indeed null,
this(name != null ? new File(name) : null);
evaluates tothis(null);
which in turn is equivalent to invocation ofFileInputStream(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
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