我对此代码段有2个问题
//方法1
static byte m1() {
final char c = 'b'-'a';
return c;
}
//方法2
static byte m3(final char c) {
return c; // 3
}
答案 0 :(得分:23)
char
是 16位无符号值,而byte
是 8位有符号值。允许的字节范围是[-128, 127]
。因此,并非所有字符都可以在byte
中分配。
在第一种方法中,您将返回char
代码点= 1 ('b' - 'a'
)。现在,由于您已将char
定义为final
,并为其分配常量表达式,因此它将成为编译时常量。因此,编译器不会给出任何编译器错误。
如果表达式是byte,short,char或int类型的常量表达式(第15.28节):
- 如果变量的类型是byte,short或char,并且变量类型中的常量表达式的值,则可以使用缩小的原始转换。
强调我的。
但是,如果你使c
成为非最终版,它也会导致编译错误:
static byte m1() { // This will be an error
char c = 'b'-'a';
return c;
}
原因是,c
不再是编译时常量,编译器不会进行隐式向下转换。
在第二种方法中,您将返回您传递的char
。参数c
没有编译时常量。在编译时不知道该方法可能得到什么值。
例如,如果您传递的char
代码点不在允许的byte
范围内,则无效。
要使第二种方法有效,您可以进行显式转换:
static byte m3(final char c) {
return (byte)c; // 3
}
答案 1 :(得分:2)
在m1()
中,编译器看到char c
与值1
保持不变,因此不会抱怨,因为它知道它可以适合字节。如果您将其更改为final char c = 128
,其中127是您将收到投诉的byte
的最大尺寸,就像您从final
删除char c
变量描述符时一样。
答案 2 :(得分:1)
在方法2中,编译器无法从聊天到字节进行缩小隐式转换,因为它可能导致精度损失(Java支持Unicode字符,并且其char原语类型定义为16位大小信息,与C语言不同,通常为8位)
在方法1中,编译器可以确定常数值''' a'实际上不会导致精度损失,因此允许您执行隐式转换。
看看:http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html
答案 3 :(得分:0)
现在m1()
起作用的原因和m3()
不起作用的原因是因为m1()
c中的compile-time constant
。
分析此代码:
byte b = 'x'; //compile-time constant
int i = 'x'; //compile-time constant
char c = 'x'; //compile-time constant
c = i; //compilation error
c = b; //compilation error
b = i; //compilation error
b = c; //compilation error
i = b; // Okay
i = c; // Okay
对于运行时变量,编译器不会进行隐式转换,这可能会导致数据丢失。