16

我对此代码段有 2 个问题

  1. 方法 1 工作正常,方法 2 不行。这是什么原因?
  2. 在方法 1 中,返回值为字节(8 位)。但我们实际上返回了一个 char 值(16 位)。这里实际发生了什么?

//方法一

static byte m1() {
    final char c = 'b'-'a';
    return c; 
}

//方法二

static byte m3(final char c) {
    return c; // 3
}
4

4 回答 4

23

char在 Java 中是16 位无符号值,byte而是8 位有符号值。字节的允许范围是[-128, 127]。因此,并非所有字符都可以在byte.

在您的第一种方法中,您将返回一个char代码点 = 1 ( 'b' - 'a')。现在既然你已经定义了charasfinal并为其分配一个常量表达式,因此它成为编译时常量。因此,编译器不会给出任何编译器错误。

JLS 第 5.2 节

如果表达式是 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
}
于 2013-08-11T10:09:11.517 回答
2

m1()编译器中,char c它的值是常量,1因此不会抱怨,因为它知道它可以放入字节中。如果您将其更改为final char c = 128127 是byte您将收到投诉的最大大小,就像您finalchar c.

于 2013-08-11T10:14:27.353 回答
1

在方法 2 中,编译器不能进行从 chat 到 byte 的窄化隐式强制转换,因为它可能会导致精度损失(Java 支持 Unicode 字符,并且它的 char 原始类型定义为 16 位信息的大小,不同来自通常为 8 位的 C 语言)

但是在方法 1 中,编译器可以确定常量值 'b'-'a' 实际上不会导致精度损失,因此允许您执行隐式转换。

看看:http ://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html

于 2013-08-11T10:10:02.187 回答
0

现在原因m1()有效而m3()无效是因为在m1()c 中是 a 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

对于运行时变量,编译器不会执行可能导致数据丢失的隐式转换。

于 2013-08-11T10:25:29.480 回答