【问题标题】:In Java, is the result of the addition of two chars an int or a char?在Java中,两个字符相加的结果是int还是char?
【发布时间】:2012-01-31 02:23:35
【问题描述】:

当添加 'a' + 'b' 时,它会生成 195。输出数据类型是 char 还是 int

【问题讨论】:

  • 如果类型是char,那么'a' + 'b'的值就不是195而是'Ã'
  • 这里是 195 - ideone.com 但在 Eclipse 中没有。
  • 你从算法书里读到了,哈哈!我正是因为这个练习才来到这里的;)

标签: java char int primitive addition


【解决方案1】:

charbyte(和 short)上的二进制算术运算升级为 int -- JLS 5.6.2。

【讨论】:

  • 和一元算术运算。
【解决方案2】:

根据binary promotion rules,如果两个操作数都不是double、float 或long,则都提升为int。但是,我强烈建议不要将 char 类型视为数字,这会违背其目的。

【讨论】:

  • char 用作数值完全在其目的之内,这就是JLS 在这种用法上花费如此之多的原因。
【解决方案3】:

添加 Java 字符、短裤或字节的结果是 int

Java Language Specification on Binary Numeric Promotion:

  • 如果任何操作数属于引用类型,则取消装箱转换 (§5.1.8)执行。然后:
  • 如果任一操作数是双精度类型,则 其他转换为双精度。
  • 否则,如果任一操作数属于类型 浮动,另一个转换为浮动。
  • 否则,如果任一操作数 是 long 类型,另一个转换为 long。
  • 否则,两者都 操作数被转换为 int 类型。

But note what it says about compound assignment operators (like +=):

将二元运算的结果转换为左侧变量的类型……并将转换结果存入变量中。

例如:

char x = 1, y = 2;
x = x + y; // compile error: "possible loss of precision (found int, required char)"
x = (char)(x + y); // explicit cast back to char; OK
x += y; // compound operation-assignment; also OK

一般来说,找出结果类型的一种方法是将其转换为 Object 并询问它是什么类:

System.out.println(((Object)('a' + 'b')).getClass());
// outputs: class java.lang.Integer

如果您对性能感兴趣,请注意Java bytecode 甚至没有专门用于较小数据类型的算术指令。例如,对于加法,有指令iadd(用于整数)、ladd(用于长整数)、fadd(用于浮点数)、dadd(用于双精度数),仅此而已。为了用较小的类型模拟x += y,编译器将使用iadd,然后使用i2c(“int to char”)之类的指令将int的高字节归零。如果本机 CPU 具有针对 1 字节或 2 字节数据的专用指令,则由 Java 虚拟机在运行时对其进行优化。

如果您想将字符连接为字符串而不是将它们解释为数字类型,有很多方法可以做到这一点。最简单的方法是在表达式中添加一个空字符串,因为添加一个字符和一个字符串会产生一个字符串。所有这些表达式都会产生字符串"ab"

  • 'a' + "" + 'b'
  • "" + 'a' + 'b'(这是因为"" + 'a'首先被评估;如果""在最后,你会得到"195"
  • new String(new char[] { 'a', 'b' })
  • new StringBuilder().append('a').append('b').toString()
  • String.format("%c%c", 'a', 'b')

【讨论】:

    【解决方案4】:

    你不妨学习以下关于char的表达方式。

    char c='A';
    int i=c+1;
    
    System.out.println("i = "+i);
    

    这在 Java 中完全有效,并返回 66,即 c+1 字符 (Unicode) 的对应值。


    String temp="";
    temp+=c;
    System.out.println("temp = "+temp);
    

    这在 Java 中太有效了,String 类型变量 temp 自动接受 char 类型的 c 并在控制台上生成 temp=A


    以下所有语句在 Java 中同样有效!

    Integer intType=new Integer(c);
    System.out.println("intType = "+intType);
    
    Double  doubleType=new Double(c);
    System.out.println("doubleType = "+doubleType);
    
    Float floatType=new Float(c);
    System.out.println("floatType = "+floatType);
    
    BigDecimal decimalType=new BigDecimal(c);
    System.out.println("decimalType = "+decimalType);
    
    Long longType=new Long(c);
    System.out.println("longType = "+longType);
    

    虽然cchar 的一种类型,但可以在各自的构造函数中正确地提供它,并且所有上述语句都被视为有效语句。它们分别产生以下输出。

    intType = 65
    doubleType = 65.0
    floatType = 65.0
    decimalType = 65
    longType =65
    

    char 是原始数字整数类型,因此受制于这些野兽的所有规则,包括转换和提升。你会想要阅读这个,JLS 是最好的来源之一:Conversions and Promotions。尤其是阅读“5.1.2 扩展原语转换”的简短部分。

    【讨论】:

      【解决方案5】:

      Java 编译器可以将其解释为任一。

      通过编写程序并查找编译器错误来检查它:

      public static void main(String[] args) {
          int result1 = 'a' + 'b';
          char result2 = 'a' + 'b';
      }
      

      如果它是一个字符,那么第一行会给我一个错误,而第二行不会。 如果是 int,则相反。

      我编译了它,我得到了.....没有错误。 所以 Java 两者都接受。

      但是,当我打印它们时,我得到了:

      整数:195

      字符:Ã

      当你这样做时会发生什么:

      char result2 = 'a' + 'b'
      

      执行隐式转换(从 intchar 的“原始缩小转换”)。

      【讨论】:

      • 我很惊讶您在第二种情况下没有收到编译器警告,因为缩小可能会导致精度损失。
      • @eboix: 你写了 "编译器自动转换为 char 或 int" [原文如此]...这是不正确的,因为 int 不是“强制转换”到 int 并且从 intchar 不是“强制转换”而是“缩小原始转换" ; )
      • 是的。我也是这么期待的。在制作程序之前,我实际上已经写了部分答案,但是当我看到我没有收到任何警告或错误时,我就删除了它。
      • @eboix: eh eh :) 我会编辑它,但我还没有 2000 个声望点,因此我的评论而不是编辑; )
      • 如果你愿意,@user988052,我可以把它改回原来的样子,你可以编辑它,获得积分。如果您的声望点少于 2000,您仍然可以对其进行编辑。唯一的问题是发帖的人必须接受编辑。我现在就把它改回来,这样你就可以得到本应属于你的两点。
      【解决方案6】:

      虽然您已经有了正确的答案(在 JLS 中引用),但这里有一些代码可以验证您在添加两个 chars 时是否获得了 int

      public class CharAdditionTest
      {
          public static void main(String args[])
          {
              char a = 'a';
              char b = 'b';
      
              Object obj = a + b;
              System.out.println(obj.getClass().getName());
          }
      }
      

      输出是

      java.lang.Integer

      【讨论】:

      • 这不是一个令人信服的验证,因为您已经将拳击转换加入其中。 intInteger 类型不是一回事。更有说服力的验证是尝试将a + b 分配给int 变量或char 变量。后者给出了一个编译错误,实际上是“你不能将int 分配给char”。
      【解决方案7】:

      char 表示为 Unicode 值,其中 Unicode 值由 \u 后跟 Hexadecimal 值表示。

      由于对 char 值的任何算术运算提升为 int ,所以 'a' + 'b' 的结果计算为

      1.) 使用Unicode TableUnicode 值应用于对应的char

      2.) 应用Hexadecimal to Decimal 转换,然后对Decimal 值执行操作。

          char        Unicode      Decimal
           a           0061          97
           b           0062          98  +
                                    195
      

      Unicode To Decimal Converter

      例子

      0061
      

      (0*163) + (0*162) + (6*161) + (1*160)

      (0*4096) + (0*256) + (6*16) + (1*1)

      0 + 0 + 96 + 1 = 97

      0062
      

      (0*163) + (0*162) + (6*161) + (2*160)

      (0*4096) + (0*256) + (6*16) + (2*1)

      0 + 0 + 96 + 2 = 98

      因此97 + 98 = 195


      示例 2

      char        Unicode      Decimal
       Ջ           054b         1355
       À           00c0          192 
                            --------
                                1547    +
                                1163    -
                                   7    /
                              260160    *
                                  11    %
      

      【讨论】:

      • 这不是问题要问的。
      • 仅供参考,我对上述评论的详细回复已被模组删除,这解释了我从已删除帖子中迁移答案的原因。如果我的回复已被删除以掩盖 SO 审核的缺陷,那么您至少可以删除上述评论或以某种方式指示观众,这样我就不必再写一条评论了? SO mods的问题
      • 我支持我的评论。正如我回复您...但随后删除...您在此处发布此问题的原因并没有改变这样一个事实,即该问题 95% 偏离主题,5% 重复先前的答案。如果你想保存你浪费的努力的结果,把它保存在你的硬盘上会更合适。或者找到其他相关的问题。
      • 如果您对版主有意见,请访问 meta.stackoverflow.com。并提供证据。我在这里要做的就是整理>>this
      • 我理解你的观点,但无法理解忽略 Unicode 转换细节的事实,作为一个附加值,它可能会帮助一些读者,所以我想保留这个答案(我知道它是对你没用,而且似乎离题了)。我避免使用元和类似的地方,因为在没有权力或支持的情况下做这些事情并不容易,这需要大量的时间和精力。我更喜欢保持内心的平静,陛下。
      【解决方案8】:

      虽然Boann's answer 是正确的,但是当常量表达式出现在赋值上下文中时,会出现复杂情况。

      考虑以下示例:

        char x = 'a' + 'b';   // OK
      
        char y = 'a';
        char z = y + 'b';     // Compilation error
      

      发生了什么事?他们的意思是一样的,不是吗?为什么在第一个示例中将int 分配给char 是合法的?

      当常量表达式出现在赋值上下文中时,Java 编译器会计算表达式的值并查看它是否在您要赋值的类型范围内。如果是,则应用隐式缩小原语转换

      • 在第一个例子中,'a' + 'b' 是一个常量表达式,它的 值将适合char,因此编译器允许将int 表达式结果隐式缩小为char

      • 在第二个示例中,y 是一个变量,因此 y + 'b' 不是 常量表达式。所以即使Blind Freddy 可以看到 值将适合,编译器不允许任何隐式缩小,并且您会收到一个编译错误,指出无法将 int 分配给 char

      关于在这种情况下何时允许隐式缩小原语转换,还有一些其他注意事项;有关详细信息,请参阅 JLS 5.2JLS 15.28

      后者详细解释了常量表达式的要求。可能不是你想的那样。 (例如,仅将 y 声明为 final 没有帮助。)

      【讨论】:

        猜你喜欢
        • 2013-08-27
        • 2012-05-18
        • 2015-02-22
        • 1970-01-01
        • 2011-06-16
        • 2018-09-25
        • 1970-01-01
        • 2013-04-29
        • 1970-01-01
        相关资源
        最近更新 更多