您的位置:首页 > 编程语言 > Java开发

java中"+"与”+=“的本质区别

2014-08-07 11:02 351 查看
今天看书时,突然发现了一个很有趣的问题:

short s = 1;

(1)s=s+1;

(2)s+=1;

编译时s=s+1提示出错,不能隐式转换,必须强制转换;而s+=1却能顺利编译。

通过在网上查找原因,得出结论:s=s+1中"+"操作符自动向较高精度提升了字符类型,s+1为int 类型,与左边的short类型不匹配,必须强制转换;

s+=1中"+="操作符在返回结果之前不仅提升了字符类型,而且自动进行了类型转换。

下面是摘自网上一篇详细的介绍

s=s+1与s+=1在官方网站上据说是等效的,可是在实际的应用中,它们之间还是有一点小小的区别,这些区别造成了一些困惑,现在就对这些区别做一些解释。

前几天一个很牛的朋友问我:“s=s+1与s+=1有什么区别?”,我认为他在开玩笑,因为以这个朋友的实力,不会不知道这个的,我认为这是一个陷阱,赶快到MSDN上 进行查询,得到的结果是:

使用 += 赋值运算符的表达式,
x += y

等效于

x = x + y。既然MSDN上都说了“等效”,当然它们应该是一样的。我的朋友立即给我发过来一段代码,

short s = 1;

s = s + 1;

short n = 1;

n += 1;

Console.ReadKey();

其中s=s+1编译错误:无法将类型“int”隐式转换为“short”。存在一个显式转换(是否缺少强制转换?),并且定位在s=s+1这一行,从

这里看两个还真的不等效。

于是将代码改写为

short s = 1;

s = (short)(s + 1);

   short n = 1;

   n += 1;

   Console.ReadKey();

编译通过,于是推测s=s+1这个表达式中,1被默认的看为整型int,根据运算规则,s+1中的s也会隐式的转换成int,于是结果就变成

了int类型,由于int类型比short类型的精度高,所以将int赋值给short时,需要进行强制类型转换,于是,我又编写了下面的代码


short s = 1;

short k = 2;

s = s+k;

short n = 1;

n += 1;

Console.ReadKey();

编译仍然不能通过,提示信息错误无法将类型“int”隐式转换为“short”。存在一个显式转换(是否缺少强制转换?),晕倒,short+short得出的结果仍然是int类型,为了测试这个想法,于是编写代码如下:

short s = 1;

short k = 2;

Console.WriteLine((s + k).GetType().FullName);

short n = 1;

n += 1;

Console.ReadKey();

得到的结果是System.Int32(在c#中,short对应System.Int16,int对应System.Int32),在C#中,为数值类型和字符串类型预定义了二元 + 运算符。其实+运算符应该也是一个函数调用,只是这个函数的名字比较特殊罢了。

当一个函数的名称相同,而要根据参数的类型或者参数的个数的不同而有不同的实现的时候,需要进行函数的重载,问题可能就是出现在这个+运算符的重载了。

推测在系统的内部,系统只重载了 int operator+(int,int)这样的函数,在进行short+short运算时,系统寻找精确的匹配,但是没有找到,可是将short升级为int是一个自动的过程,于是系统调用了int operator(int,int)这个函数,得到的结果也就被转化为int类型,就出现了上面的错误。

而+=这个运算符与+运算符一样,但是系统重载了short operator +=(short,short)或者short operator +=(int,int),这个函数的具体实现没办法看到,可是据推测应该是这样

short operator+=(int b)

{

return (short)(this+b);

}

也就是在返回数据的结果前,系统自己做了强制类型转换。为了验证这个思想,我又做了两件事情。

第一:对short类型扩展一个方法(vs2008的扩展方法),该方法实现的是两个short类型的变量的加和,但是在返回结果前,对结果进行强制类型转换。代码如下:

namespace ConsoleApplication1

{

static class Myshort

{

public static short add(this short a,short b)

{

return (short)(a+b);

}

}

}

重新编写代码

short s = 1;

short k = 2;

s=s.add(k);

没有任何问题,编译通过。

第二:对源代码进行反编译,看看反编译的代码

源代码如下:

static void Main(string[] args)

{

short s = 1;

short k = 2;

s=s.add(k);

short n = 1;

n += 1;

Console.ReadKey();

}

生成的反编译的代码:

private static void Main(string[]
args)

{

short s = 1;

short k = 2;

s = s.add(k);

short n = 1;

n = (short) (n + 1);

Console.ReadKey();

}

对比可以知道,+=运算符果然在返回结果之前系统进行了强制类型转换。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: