89

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

4

8 回答 8

141

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

关于二进制数字提升的 Java 语言规范

  • 如果任何操作数是引用类型,则执行拆箱转换(第 5.1.8 节)。然后:
  • 如果任一操作数是 double 类型,则另一个操作数将转换为 double。
  • 否则,如果任一操作数的类型为浮点型,则另一个将转换为浮点型。
  • 否则,如果任一操作数是 long 类型,则另一个将转换为 long。
  • 否则,两个操作数都转换为 int 类型。

但请注意它对复合赋值运算符(如 +=)的说明

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

例如:

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

如果您想将字符连接为字符串而不是将它们解释为数字类型,有很多方法可以做到这一点。最简单的方法是在表达式中添加一个空字符串,因为添加一个字符和一个字符串会产生一个字符串。所有这些表达式都会产生 String "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')
于 2011-12-31T14:43:28.370 回答
22

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

于 2011-12-31T14:40:28.753 回答
7

您可能希望学习以下有关 的表达式char

char c='A';
int i=c+1;

System.out.println("i = "+i);

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


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

这在 Java 中太有效了,String 类型变量会temp自动接受cchar 类型并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);

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

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

char是原始数字整数类型,因此受制于这些野兽的所有规则,包括转换和提升。您需要阅读此内容,而 JLS 是最好的来源之一:Conversions and Promotions。特别是,请阅读“5.1.2 Widening Primitive Conversion”上的简短说明。

于 2011-12-31T14:46:14.390 回答
3

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

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

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

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

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

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

诠释:195

字符:Ã

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

char result2 = 'a' + 'b'

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

于 2011-12-31T14:47:34.047 回答
1

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

于 2011-12-31T14:41:47.820 回答
1

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

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

于 2011-12-31T16:01:58.223 回答
0

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

char与提升到的值的任何算术运算一样int,因此 的结果'a' + 'b'计算为

1.)应用Unicode相应的值char使用Unicode Table

2.) 应用 十六进制到十进制的转换,然后对Decimal值执行操作。

    char        Unicode      Decimal
     a           0061          97
     b           0062          98  +
                              195

Unicode To Decimal Converter

例子

0061

(0*16 3 ) + (0*16 2 ) + (6*16 1 ) + (1*16 0 )

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

0 + 0 + 96 + 1 = 97

0062

(0*16 3 ) + (0*16 2 ) + (6*16 1 ) + (2*16 0 )

(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    %
于 2017-02-03T15:08:15.290 回答
0

虽然Boann 的回答是正确的,但是当常量表达式出现在赋值上下文中时,有一个复杂的情况适用于它们的情况。

考虑以下示例:

  char x = 'a' + 'b';   // OK

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

到底是怎么回事?他们的意思是一样的,不是吗?为什么在第一个示例中将a 分配int给 a是合法的?char

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

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

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

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

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

于 2020-05-24T03:20:58.230 回答