【问题标题】:Final parameter in a method in javajava方法中的最终参数
【发布时间】:2013-08-11 10:05:20
【问题描述】:

我对此代码段有 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
}

【问题讨论】:

  • 不工作是什么意思?
  • 编译时显示 :: error: possible loss of precision
  • 可能是方法1中的静态优化?
  • 这个错误信息有什么不清楚的地方?你知道字符是 16 位长,而字节是 8 位长吗?

标签: java methods final


【解决方案1】:
Java 中的

char16 位无符号 值,而 byte8 位有符号 值。字节的允许范围是[-128, 127]。因此,并非所有字符都可以在byte 中分配。

在您的第一种方法中,您将返回一个带有 code point = 1 ('b' - 'a') 的 char。现在,由于您已将char 定义为final,并为其分配了一个常量表达式,因此它变成了一个编译时常量。因此,编译器不会给出任何编译器错误。

来自JLS Section 5.2

如果表达式是 byte、short、char 或 int 类型的常量表达式(第 15.28 节):
- 如果变量的类型是 byte、short 或 char,并且常量表达式的值在变量的类型中是可表示的,则可以使用窄化原语转换。

强调我的。

但是,如果你将c 设为非final,也会导致编译器错误:

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
}

【讨论】:

  • 哦!你在哪家公司?
  • 我在 iGATE...寻找 Ruby 工作...您能帮帮我吗? :)
【解决方案2】:

m1() 中,编译器看到char c 是常量,值为1,因此不会抱怨,因为它知道它可以放入字节中。如果您将其更改为 final char c = 128,其中 127 是 byte 的最大大小,您会收到投诉,就像您从 char c 中删除 finalvariable 描述符时一样。

【讨论】:

  • 能否解释一下为什么删除final关键字时会出错?
  • 当您删除 final 时,它不再是一个常量。所以编译器不能确定它将来不会改变(即使方法在下一行结束,编译器也不知道这一点)。当final char c 被赋值时,编译器只会将其视为数字 127,它可以安全地转换为任何整数类型。请记住,Java 中的 char 范围为 0 - 65 535,因为它有 16 位。 docs.oracle.com/javase/tutorial/java/nutsandbolts/…
【解决方案3】:

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

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

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

【讨论】:

    【解决方案4】:

    现在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
    

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

    【讨论】:

      猜你喜欢
      • 2011-04-14
      • 2013-07-17
      • 1970-01-01
      • 1970-01-01
      • 2015-02-18
      • 2014-07-10
      • 2019-04-14
      • 1970-01-01
      • 2017-08-30
      相关资源
      最近更新 更多