This week's book giveaway is in the OCAJP 8 forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide and have Edward Finegan & Robert Liguori on-line! See this thread for details.
Have you tried to compile it? Check out the error message: ------- C:\blah>javac Hide.java Hide.java:29: Reference to test is ambiguous. It is defined in float test(float) and char test(char). b.test('m'); //why compile error this line ------- because the value of the character 'm' is 109 -- and that value can be interpretted as char or as a float. So the compiler doesn't know which version of the method test it should run. [ May 20, 2002: Message edited by: Jessica Sant ]
Notice, however, that the fact that the method invocation is ambiguous is dependent upon the fact that the test method is overridden in class Sub. Try commenting out that overriding method and see what happens. Corey
Originally posted by Corey McGlone: Notice, however, that the fact that the method invocation is ambiguous is dependent upon the fact that the test method is overridden in class Sub. Try commenting out that overriding method and see what happens. Corey
Yup, Corey is absolutely right. But could you please tell me the reason? I've just done the following test, and it works without inheritence.
because the value of the character 'm' is 109 -- and that value can be interpretted as char or as a float. So the compiler doesn't know which version of the method test it should run.
But this is the case also with b.test(1); 1 is char/int and can be widend to float also. then why that is able to compile? is it litral thats why ? Now second question : passing 'm' as parameter for method which is suppose to take *char* is not good indication for compilar to not get confuse? (true internally char are unsigned int) CMIW TIA
"Thanks to Indian media who has over the period of time swiped out intellectual taste from mass Indian population." - Chetan Parekh
Joined: Dec 20, 2001
Hmmm...This one is a tough one (it is for me, anyway). I've read through the first three sections of the JLS on Method Invocation Expressions. Those sections deal with compile time selection of the method to be invoked. Unfortunately, in no place (at least that I've seen) does the JLS come out and say why this doesn't work. However, I'll explain why I think it doesn't work and you can tell me I'm wrong however you'd like. Step 1 of the process is to determine which class or interface to search for the method. From the JLS:
If the form is Primary . Identifier, then the name of the method is the Identifier and the class or interface to be searched is the type of the Primary expression.
So, from that, we know that we'll search for the method within the class Sub. Next, we need to search for all methods that are applicable and accessible. This is where the problem occurs, I believe. From the JLS:
The class or interface determined by the process described in �15.12.1 is searched for all method declarations applicable to this method invocation; method definitions inherited from superclasses and superinterfaces are included in this search.
I don't think the problem occurs in this step, but I think it originates here. In the next step, we need to locate the "most specific method." I believe the compiler gets confused as to which class to look in to find the most specific method. That's why it complains of ambiguity. Let's look at the following code and see what happens when we make small changes to it:
Compiled as it is, this code generates a compiler error. However, if you comment out the test method in the class Sub, you'll get the following output:
Notice that, even though there are two applicable and accessible methods within Super, the compiler chooses the method that takes a char because it is the "most specific." From this, I thought it was an issue dealing with method overriding but, I tried leaving the test method in Sub and commenting out the test method in Super. This leaves the code looking like this:
However, compiling this code also leads to a compiler error (due to ambiguity) even though there is no overriding taking place. My best guess is that, because the compiler finds two applicable and accessible methods in two separate classes, it can not choose the most specific, even though it has no problem doing so when the methods are contained within the same class. That's my best explanation of what is occuring. Sorry I can't be of more help. If anyone can explain, definitively, what is occuring, I'd love to hear it. Corey
Applying JLS 15.12.1 we agree that Sub is the class to search for the method declaration.
because the value of the character 'm' is 109 -- and that value can be interpretted as char or as a float. So the compiler doesn't know which version of the method test it should run. But this is the case also with b.test(1); 1 is char/int and can be widend to float also.
The words of Jessica must be interpreted in the context of JLS. Anyway, "1" is an "int" and as such it can not be widdenning converted to a char. Thus compiler has no problem about this call.
The key to understand this is JLS 188.8.131.52
The precise definition is as follows. Let m be a name and suppose that there are two declarations of methods named m, each having n parameters. Suppose that one declaration appears within a class or interface T and that the types of the parameters are T1, . . . , Tn; suppose moreover that the other declaration appears within a class or interface U and that the types of the parameters are U1, . . . , Un. Then the method m declared in T is more specific than the method m declared in U if and only if both of the following are true: * T can be converted to U by method invocation conversion. * Tj can be converted to Uj by method invocation conversion, for all j from 1 to n.
Consider the first list where we have two method declarations be chosen as the most specific: Super.test(char) //inherited in Sub Sub.test(float) // declared in Sub None of them are most specific than the other. Because considering the types of the parameters, char is widdening convertible to float, BUT super is not to Sub. This is so even if test(float) is not overriden as Corey's code showed. Now the situation where the two methods are declared in Super, but not overriden in Sub: Super.test(char) Super.test(float) char can be converted to float by widdening, AND Super can be concerted to Super by method invocation conversion (the same type or a widdening conversion). Thus there is a most specific declaration, and compiler doesn't complain.
SCJP2. Please Indent your code using UBB Code
Joined: Dec 20, 2001
Originally posted by Jose Botella: None of them are most specific than the other. Because considering the types of the parameters, char is widdening convertible to float, BUT super is not to Sub.
What did you mean by that? I lost you along the way. Corey
Joined: Jul 03, 2001
char is widdening covertible to float, but we cannot say that the declaration of Super.test(char) is more specific than Sub.test(float) because Super is not the same type or widdening covertible to Sub. Follow the quote of JLS 184.108.40.206 . It speaks not only about the types of the parametes, but also about the types in which were placed the methods declarations we are considering. Just post again if not clear enough.