• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Something interesting about two overloaded constructors of FileInputStream

 
Mohammad Ali Asgar
Ranch Hand
Posts: 39
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,

As I was reading Mala Gupta's book, I came to a page where there is an interesting discussion on a scenario where there are two 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.



I quote from the book: "... but an issue arises when you try to execute this method using values that can be passed to both versions of the overloaded methods. In this case, the code will fail to compile ..."

Here is the code showing the use of the methods:



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 and dive further into the book to the final chapter, the chapter of exceptions. There, the writer introduces from Java 7 API two overloaded constructors of FileInputStream.

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


The writer also says that, according to the Java 7 API source code, here is the definition of the version that takes a String object as the argument:



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?
 
Paweł Baczyński
Bartender
Posts: 1876
35
Firefox Browser IntelliJ IDE Java Linux Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you pass null like below, the compiler will indeed complain about ambiguosity.But if you have your null in appropriate varialbe, the compiler will not complain. The type of the variable determines which constructor is chosen.If you cast a null to appropriate type (yes, you can do this) you can help the compiler to choose a version of constructor (or method).
 
Mohammad Ali Asgar
Ranch Hand
Posts: 39
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Pawet,

Yes, I have realized that. In fact, as I have come to know, if "name" is null, then

this(name != null ? new File(name) : null); evaluates to this((File)null); not this(null);

As per JLS: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.25-300-C

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.

That is why null is type-cast into (File)null. So, there is no ambiguity and FileInputStream(File) is chosen by the compiler.

And, lastly, this((File)null) is analogous to
File file = null;
new FileInputStream(file);
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As you already discovered, it's all about using the conditional operator. The conditional operator evaluates to a certain type based on 2nd and 3rd operands (the 1st one always have to be a boolean). So the call to the constructor this(name != null ? new File(name) : null); is equivalent to File file = (name != null ? new File(name) : null); this(file); and that's why you don't have the compiler error.

Can we use the equivalent in the constructor? Why (not)?


And what happens when the types of the 2nd and 3rd operands are different, like in this example. What type will the method need to have to make the code compile (if possible)?


PS. That was an excellent question (and analysis), have a cow for that!
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic