Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different char casting behaviour for method passing and inside method

Tags:

java

casting

char

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?

like image 414
gstackoverflow Avatar asked Feb 14 '14 08:02

gstackoverflow


People also ask

What is method and method passing?

What is Actually Passed to a Method? The data that is passed to a method is used inside the method to accomplish tasks. Definition clarification: What is passed "to" a method is referred to as an "argument". The "type" of data that a method can receive is referred to as a "parameter".

What is difference between pass by value and pass-by-reference in Java?

Pass by Value: The method parameter values are copied to another variable and then the copied object is passed, that's why it's called pass by value. Pass by Reference: An alias or reference to the actual parameter is passed to the method, that's why it's called pass by reference.

How do you pass a character to a method in Java?

Character ch = new Character('a'); The Java compiler will also create a Character object for you under some circumstances. For example, if you pass a primitive char into a method that expects an object, the compiler automatically converts the char to a Character for you.


1 Answers

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??@!?!?! 
like image 105
chm Avatar answered Sep 19 '22 19:09

chm