Reputation: 37106
I have simple code :
class A {
public static void main(String[] args){
char c = 65; // ok
new A().m(65); // compile error
}
void m(char c){}
}
I want to know why
char c = 65;
is possible, but
new A().m(65); // compile error
impossible!
Who can explain?
Who can specify common rule for similar issues?
Upvotes: 8
Views: 198
Reputation: 37106
Reading specification is right way but it is hard for me.
I offer less right but more simple answer:
when I write:
new A().m(65); // compile error
full analog:
int n =65;
char c = n;
It is ibviously(it is obviously for me) compile error
I hope it is hopes someone.
Upvotes: -3
Reputation: 1519
What you are looking at is the difference between method invocation conversion and assignment conversion.
In plain language, what has happened is that the conversion rules are different in the two cases.
Case #1: Assignment Conversion
char c = 5;
As you know, this is an assignment statement. When the object being assigned is not exactly the expected type, some conversion may happen to make the assignment work anyway.
Case #2: Method Invocation Conversion
def foo(char c){}
[...]
foo(5);
This (the last line) is a method invocation. This is another place where the type literal may not match the declaration, so conversion rules might apply.
So, why are they different?
The designers of Java have implemented different conversion rules for these two cases. In Case #1, the rules are (from the JLS):
...a narrowing primitive conversion may be used if all of the following conditions are satisfied:
- The expression is a constant expression of type byte, short, char or int.
- The type of the variable is byte, short, or char.
- The value of the expression (which is known at compile time, because it is a constant expression) is representable in the type of the variable.
So the int
-> char
conversion in Case #1 is being specifically checked for and automatically resolved by the Java compiler.
However, the rules in Case #2 are different. Here, Java's designers did not want to implement the automatic conversion that they used for assignment statements. From "A Programmer's Guide To Java Certification: A Comprehensive Primer":
Note that method invocation and assignment conversions differ in one respect: method invocation conversions do not include the implicit narrowing conversion performed for integer constant expressions.
So, why are there different rules for the two cases? Basically, Java's designers thought that the automatic conversion was useful and convenient, but it might make things too complicated by having too much typing flexibility. They thought Case #1 is a simple enough situation that we can have the conversion without losing clarity, but Case #2 is not. Here is the justification in the JLS:
Method invocation conversions specifically do not include the implicit narrowing of integer constants which is part of assignment conversion. The designers of the Java programming language felt that including these implicit narrowing conversions would add additional complexity to the overloaded method matching resolution process.
And this is, specifically, JLS 5.1, 5.2 and 5.3.
EDIT
With regards to the "additional complexity to the overloaded method matching resolution process", my assumption is that they were trying to avoid this kind of situation:
def foo(int i){}
def foo(char c){}
foo(5); // OH NO which of the above gets called??@!?!?!
Upvotes: 11