在Java中,两个字符相加的结果是int还是char?

Posted

技术标签:

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

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

【问题讨论】:

如果类型是char,那么'a' + 'b'的值就不是195而是'Ã' 这里是 195 - ideone.com 但在 Eclipse 中没有。 你从算法书里读到了,哈哈!我正是因为这个练习才来到这里的;) Java (OpenJDK 8) – Try It Online 【参考方案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.***.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.2 和 JLS 15.28。

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

【讨论】:

以上是关于在Java中,两个字符相加的结果是int还是char?的主要内容,如果未能解决你的问题,请参考以下文章

Java实现字符串形式大数相加

java求两个数组相加,所得值返回另一个数组。

java中的字符串相加

为什么两个short类型相加会自动提升为int?

为什么两个short类型相加会自动提升为int?

大数四则运算