views:

84

answers:

4

I just wondering why this works (in Java):

byte b = 27;

but being method declared like this:

public void method(byte b){
    System.out.println(b);
}

This doesn't work:

a.method(27);

Gives a Compiler error as follows:

`The method method(byte) in the type App is not applicable for the arguments (int)`

Reading this doesn't give me any clue (probably i am missunderstanding something).

Thanks in advance.

+1  A: 

Simple answer - a byte is 1 byte of memory, and an integer is typically 4 bytes.

Without explicitly trying to cast the int to a byte, there is no implied coercion because an integer of size say 10790 would lose information if truncated down to one byte.

ghills
Yep, but my first example works, right?
David Santamaria
+9  A: 

The reason the assignment

byte b = 27;

works is due to section 5.2 of the Java Language Specification (assignment conversion), which includes:

In addition, if the expression is a constant expression (§15.28) of type byte, short, char or int :

A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.

In other words, the language has special provision for this case with assignments. Normally, there's no implicit conversion from int to byte.

Interestingly, C# works differently in this respect (despite being like Java in so many other aspects of core functionality) - the method call is valid in C#.

Jon Skeet
As usual great answer Jon, but why there is not a narrowing in the method invocation? but there is in the assignation?
David Santamaria
Wild guess, but perhaps because it would significantly complicate method lookup mechanism - it would have to look for all possible demotions, which generally sounds problematic.
Yardena
@David: I really don't know, given that C# manages it. I guess it may have been *considered* too complicated, but I don't find it makes C# unbearably complicated. (Admittedly there are some other fun implicit conversions around constant zero values, but that's a different matter - and one involving C# compiler bugs.)
Jon Skeet
A: 

The process of taking one numeric value and converting it to another without your help is called a promotion - You are taking for example a 1 byte number, and making it into a 4 byte number by filling in zeroes. This is (generally) safe since the range of possible values in the target type is greater than in the source type.

When the opposite occurs, such as taking an int and converting to a byte, it is a "demotion" ad it is not automatic, you have to force it since there's a loss of value.

What happens here is that 27 is interpreted as an int. The expression itself is an int, and then it gets sent to a method that expects a byte. In other words, the fact that you are putting it inside a call to a method that takes a byte doesn't change the fact that Java considers it to be a bit to begin with.

I don't remember exactly how to define byte constants in Java, but generally speaking, a number like 27 is a magic number. You may want to write a

final byte MY_CONSTANT_THAT_MEANS_27_BUT_WITH_MEANINGFUL_NAME = 27;

And then call your function with that constant instead of the 27.

Uri
Yes, I understand that. But the JVM makes the first expresion work (only if the int that you specify in the assignation fit in the byte var, if is bigger you should to put an explicit cast). And my question is still there, why with a method call doesn't work? (Am I missing something in your answer?)
David Santamaria
@David: The difference is not in the JVM but in the compiler. Because you initialize the byte in that place, the compiler figures it from the context. In the case of a function call, you first evaluate an expression, and then adapt to the type of parameter the function receives.
Uri
A: 

By default, Java will look at a numeric value such as 27 as an integer type. Think of this in a similar aspect, if you say 123.45, it will see it as a float, and "hello" is a string. These are static values, and not variables, so you need to cast it to a byte, like so:

a.method((byte)27);
gabehabe
123.45 is a double, 123.45f is a float, they are called literals not static values.
Nash0
My bad, good call. Bad thing about being totally self taught is I get keywords mixed up from time to time. :)
gabehabe