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


80

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


2
如果类型是char那么的值'a' + 'b'不会是195,但'Ã'
净莲

1
此处为195,位于ideone.com,但不在Eclipse中。
橙色

2
您是从《算法》一书中读到的!我正是因为这个练习才来到这里的;)
杰克·吐温

Answers:


132

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

Java语言规范对二进制数值的促进

  • 如果任何一个操作数是引用类型,则执行装箱转换(第5.1.8节)。然后:
  • 如果一个操作数的类型为double,则另一个将转换为double。
  • 否则,如果其中一个操作数的类型为float,则另一个将转换为float。
  • 否则,如果其中一个操作数的类型为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较小的类型,编译器将使用iadd诸如i2cint char的指令,然后将int的高字节清零。如果本机CPU具有用于1字节或2字节数据的专用指令,则取决于Java虚拟机在运行时对其进行优化。

如果要将字符串连接为字符串而不是将它们解释为数字类型,则有很多方法可以做到这一点。最简单的方法是在表达式中添加一个空String,因为添加char和String会生成String。所有这些表达式都产生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')


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就是其中的最佳来源之一:转化和促销。特别是,请阅读“ 5.1.2扩展基元转换”的简短内容。


3

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字符不叫“转换”但“缩小的原始转换”;)
TacticalCoder

是的 我也期望如此。在编写程序之前,我实际上已经写了有关此问题的部分答案,但是一旦发现没有警告或错误,便将其删除。
eboix 2011年

@eboix:eh eh:)我本来可以编辑它,但是我还没有2000信誉点,因此我的评论代替了编辑;)
TacticalCoder

如果需要,@ user988052,我可以将其更改回原来的状态,并且可以编辑它,获得积分。如果信誉点少于2000,您仍然可以对其进行编辑。唯一的事情是发帖的人必须接受编辑。我现在将其更改回原来的位置,以便您可以正确地获得两点。
eboix 2011年


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


这不是令人信服的验证,因为您已将拳击转换投入混合。类型intInteger不是同一件事。更具说服力的验证是尝试分配a + b给一个int或多个char变量。后者给出了一个编译错误,实际上是“您不能将an分配intchar”。
Stephen C

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    %

这不是问题要问的。
Stephen C

仅供参考,我对上述评论的详细回复已被mods删除,这些解释了从删除的帖子中迁移我的答案的原因。如果我的回答已被删除以掩盖SO审核的缺陷,那么您是否可以至少删除上述评论或以某种方式指示听众,这样我就不必再写评论了?SO mods的问题
Pavneet_Singh,

我支持我的评论。正如我对您的答复……但后来删除了……您在此处发布此问题的原因并未改变这样的事实,即该问题的题外率是95%,而先前答案的重复率是5%。如果您希望保存浪费的结果,那么将其保存在硬盘上会更合适。或者找到其他与之相关的问题。
Stephen C

如果您对主持人不满意,请访问meta.stackoverflow.com。并提供证据。我在这里要做的只是整理>> this <<问答。
Stephen C

我理解您的观点,但无法理解忽略带有示例的Unicode转换细节的事实,这是一个可能对某些读者有所帮助的附加值,因此我想保留这个答案(我得到的答案是,它对您没有用,而且看起来不对。话题)。我避免使用元数据和类似的地方,因为在没有权力或支持的情况下进行此类事情并不容易,这需要大量的时间和精力。我宁愿保持内心的和平S下。
Pavneet_Singh,

0

尽管Boann的答案是正确的,但当常量表达式出现在赋值上下文中时,有一种复杂情况适用于常量表达式

请考虑以下示例:

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

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

到底是怎么回事?他们是说同一件事不是吗?为什么在第一个示例中将分配int给a合法char

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

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

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

关于在这种情况下何时允许隐式变窄原语转换,还有其他一些警告。有关完整的详细信息,请参见JLS 5.2JLS 15.28

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.