C#之int与Java之Integer的分别

作者:小菜 更新时间:2025-03-16 点击数:
简介:本文涉及到一些JVM原理和Java的字节码指令,推荐感兴趣的读者阅读一本有关JVM的经典书籍《深入Java虚拟机(第2版)》,将它与我在《.NET 4.0面向对

【菜科解读】

本文涉及到一些JVM原理和Java的字节码指令,推荐感兴趣的读者阅读一本有关JVM的经典书籍《深入Java虚拟机(第2版)》,将它与我在《.NET 4.0面向对象编程漫谈》中介绍的CLR原理与IL汇编指令作个对比,相信读者会有一定的启发。

而仔细对比两个类似事物的异同,是很有效的学习方法之一。

1 奇特的程序输出

前段时间,一个学生给我看了一段“非常诡异”的Java代码:publicclassTestInteger{publicstaticvoidmain(String[]args){Integerv1=100;Integerv2=100;System.out.println(v1==v2);//输出:trueIntegerw1=200;Integerw2=200;System.out.println(w1==w2);//输出:false}}

让这个学生最困惑的是,为什么这些如此相似的代码会有这样令人意外的输出?

我平时多使用C#,Java用得不多,初看到这段代码的输出,我也同样非常奇怪:怎么会这样呢?100和200这两个整型数值对Integer这个类有本质上的差别吗?

为了弄明白出现上述现象的底层原因,我使用javap工具反汇编了Java编译器生成的.class文件:

通过仔细阅读Java编译器生的字节码,我发现以下给Integer变量赋值的语句:

Integer v1=100;

实际上调用的是Integer.valueOf方法。

而完成两个Integer变量比较的以下语句:

System.Console.WriteLine(v1 == v2);

实际生成的是if_acmpne指令。

其中的a代表“address”,cmp代表“Compare”,ne代表“not equal”。

这条指令的含义是:比较Java方法栈中的两个操作数(即v1与v2),看看它们是不是指向堆中的同一个对象。

当给v1和v2赋值100时,它们将引用同一个Integer对象。

那为什么当值改为200时,w1和w2就“翻脸了”,分别引用不同的Integer对象?

秘密就在于Integer.valueOf方法。

幸运的是,Java的类库是开源的,所以我们可以毫不费力地看到相关的源代码:

publicstaticIntegervalueOf(inti){if(i>=-128&&i128的整数值的应用程序而言,这个缓存一点用处也没有,是个累赘。

就算真要缓存,那也最好由应用程序开发者自己来实现,因为他可以依据自己开发的实际情况缓存真正用到的对象,而不需背着这个包容着256个Integer对象的大包袱。

而且前面也看到了,基于Integer对象的加减乘除会增加许多不必要的类型转换指令,远不如直接使用原始数据类型更快捷更可靠。

其实上用得最多的不是Integer对象而是它所封装的一堆静态方法(这些方法提供了诸如类型转换等常用功能),我很怀疑在实际开发中有多少场合需要去创建大量的Integer对象,而且还假设它们封装的数值还位于[-128,127]区间之内?

缓存Integer对象还对多线程应用程序带来了一定的风险,因为可能会有多个线程同时存取同一个缓存了的Integer对象。

不过JDK设计者已经考虑到了这个问题,我看到Integer类的字段都是final的,不可改,是一个不可变类,所以可以在多线程环境下安全地访问。

尽管在使用上没问题,但这一切是不是有点弯弯绕?去掉这个对象缓存,Integer类型是不是“更轻爽”“更好用”?

4 C# int挑战Java Integer

将Java的设计与.NET(以C#为例)的设计作个比较是有趣的。

Java将数据类型分为“原始数据类型”和“引用数据类型”两大类,int是原始数据类型,为了向开发者提供一些常用的功能(比如将String转换为int),所以JDK提供了一个引用类型Integer,封装这些功能。

.NET则不一样,它的数据类型分为“值类型”和“引用数据类型”两大类,int属于值类型,本身就拥有丰富的方法,请看以下C#代码:

inti=100;stringstr=i.ToString();//int变量本身就拥有“一堆”的方法

使用.NET的反汇编器ildasm查看一下上述代码生成的IL指令,不难发现C#编译器会将int类型映射为System.Int32结构:

注意System.Int32是一个值类型,生存于线程堆栈中,一般来说,在多线程环境下,使用值类型的变量往往比引用类型的变量更安全,因为它减少了多线程访问同一对象所带来的问题。

=================================

简要解释一下:请对比以下两个方法:

void DoSomethingWithValueType(int value);

void DoSomethingWithReferenceType(MyClass obj);

当多个线程同时执行上述两个方法时,线程函数使用值类型的参数value是比较安全的,不用担心多个线程互相影响,但引用类型的obj参数就要小心了,如果多个线程接收到的obj参数有可能引用同一个MyClass对象,为保证运行结果的正确,有可能需要给此对象加锁。

====================================

与JVM一样,.NET的CLR也提供了add等专用指令完成加减乘除功能。

从开发者使用角度而言,C#的int既具有与Java的原始数据类型int一样的在虚拟机级别的专用指令,又具有Java包装类Integer所拥有的一些功能,还同时避免了Java中Integer的那种比较古怪的特性,个人认为,C#中的int比Java中的int/Integer更好用,更易用。

但从探索技术内幕而言则大不一样,Java使用Integer一个类就“搞定”了所有常用的整数处理功能,而对于.NET的System.In32结构,好奇的朋友不妨用Reflector去查看一下相关的源码,会发现System.Int32在内部许多地方使用了Number类所封装的功能,还用到了NumberFormatInfo(提供数字的格式化信息)、CultureInfo(提供当前文化信息)等相关类型,如果再算加上一堆的接口,那真是“相当地”复杂。

比对一下Java平台与.NET平台,往往会发现在许多地方Java封装得较少。

从应用程序开发角度来看,不少地方Java在使用上不如.NET方便。

就拿本文所涉及的非常常见的整数类型及其运算而言,相信大家都看到了,使用Java编程需要留心这个“Intege对象缓存”的陷阱,而.NET则很贴心地把这些已发现的陷阱(.NET设计者说:当然肯定会有没发现的陷阱,但那就不关我事了)都盖上了“厚厚”的井盖,让开发者很省心,因而带来了较高的开发效率和较好的开发体验。

但另一方面,Java的JDK代码一览无余,是开放的,你要探索其技术内幕,总是很方便,这点还是比较让人放心。

.NET则相对比较封闭,总是遮遮掩掩,想一览其庐山真相还真不容易,而且我感觉它为开发者考虑得太周到了,服务得太好了,这不见得是一件好事。

因为人性的弱点之一就是“好逸恶劳”,生活太舒服了,进取精神就会少掉不少,.NET开发者很容易于不知不觉中养成了对技术不求甚解的“恶习”,因为既然代码能够正常工作,那又何必费心地去追根问底?但话又说回来,如果仅满足于知其然,又怎会在技术上有所进步和提高?等到年纪一大,就被年轻人给淘汰了。

而这种现象的出现,到底应该怪微软,怪周遭的环境,还是自己呢?

之,int,与,Java,Integer,的,区别,本文,涉

风流皇帝乾隆举办过两次“千叟宴”,为什么之后的帝王不办了?

“千叟宴”其实并不是的首创,最早举办“千叟宴”的是。

他不光成功地通过“千叟宴”向世人展示了他文韬武略,有治国大才,还成功地向人传递了他以“孝”治天下的仁爱之心。

乾隆视康熙为偶像,因此也效仿康熙举行过“千叟宴”,甚至比康熙举行的“千叟宴”更隆重,更盛大。

那么,的“千叟宴”举办得怎样?为什么乾隆举办后,此后的皇帝都不再举办了? 我们先说说康熙举办的“千叟宴”。

康熙第一次举办“千叟宴”是在他60大寿时。

此时康熙在位已经52年。

论文治他兴修水利、奖励农耕、减轻赋税和徭役,治理黄河水患;论武功他除、平三藩、收台湾、征蒙古及南沙俄。

再加上他重视汉儒文化,对西方算术等也很喜欢。

因此,在他的治理下,呈现出经济繁荣,国泰民安的盛世局面。

所以,在他60大寿时,他看到国家欣欣向荣的气象,颇为自得,决定举办万寿庆典,并“布告天下耆老,年65岁以上者,官民不论,均可按时赶到京城参加畅春园的聚宴”。

据《康熙实录》记载,为了庆典活动,搭置的彩棚绵延20多里,从西直门一直搭到畅春园。

此次“千叟宴”由于不论官民,因此参与者多达上万余人,其中90岁以上的老人有33人,80岁以上的有538人,65岁以上者3000多人。

这已经不只是“千叟宴”,而是“万叟宴”了。

康熙不仅亲自赐酒给80岁以上老人,还命皇子皇孙们负责给老人们执爵敬酒,分发食物。

对于外省老人,还赏赐路费等。

这些老人也因能参加皇帝的寿宴,倍觉荣耀。

民间更是对康熙的行径大为赞赏,称他为“威服海内,恩浃华夷”的千古一帝。

康熙六十一年,康熙为了庆祝70大寿,再次在乾清宫举办了“千叟宴”,时年12岁的乾隆有幸参加了这次“千叟宴”,并且还留下了深刻的印象。

乾隆继位后,处处以康熙为榜样,他编修典籍、蠲免钱粮、维护民族统一,巩固边疆版图,可以说也的确做出了不少政绩。

当然,乾隆也学康熙举办过两次“千叟宴”。

一次是在他75岁时,正好又喜添五世孙。

于是为了彰显皇恩浩荡,乾隆在乾清宫举行了第一次“千叟宴”。

由于年龄限定在60岁以上,举国上下能达到这个要求的人数不少,乾隆精选了3000多人参加宴会。

乾隆是个讲排场的人,宴会上制作的都是山珍海味,满汉全席,酒水亦是取之不尽的贡酒。

因此与会者都兴高采烈。

其中90岁以上的老人,更是在一品大员的带领下参拜乾隆。

除得到乾隆亲赐的御酒外,还得到玉如意、朝珠、文玩等贵重物品。

老人们一生也就参加了这一次宫廷盛宴,不光荣耀,还知道吃的喝的都是民间尝不到的,所以他们一边夸赞着“圣上英明”,一边大快朵颐,一时醉倒撑倒无数。

再加上当时又是正月天气,虽说御厨制作的满汉全席既华丽又好吃,但由于天气冷,菜凉得快。

又加上舟车劳顿,好不容易才赶到京城。

因此老人们在食用了这些凉菜以后,不少人就病倒了。

再摊代医疗条件不好,一些老人没能撑住,就病逝了。

事情发生后,人们经过了解,发现其中一部分老人是被地方官员强制送到北京的。

原来地方官员都知道乾隆是个喜好排场,讲究大场面的人。

他们为了取悦乾隆,于是将登记在册的老年人征集起来,并派驴车拉着他们去了北京城。

跋山涉水,一路上吃了不少苦头的老人们,还没有缓过劲来,再加上居然能看到皇帝,本就兴奋不已。

又看到皇帝给他们准备了好吃好喝的,一时不免放开口腹之欲,大吃大喝起来。

的原因,最终把老人们折磨致病,甚至去世。

虽然第一次“千叟宴”因为没有经验,导致老人死亡,乾隆也遭到士人指责。

但乾隆为了与康熙同步,毅然又举办了第二次“千叟宴”。

乾隆60年,乾隆遵从他继位时不超过康熙执政的承诺,把帝位传给了。

不过军政大事,还是要经过他来把控。

所以,他是个特别忙的太上皇。

乾隆在传位第一年,也就是嘉庆元年,他又举办了第二次“千叟宴”。

由于此时乾隆已是85岁高龄的老人,他便把参与年龄提到70岁以上。

为了避免发生第一次“千叟宴”的问题,他这次不仅把菜肴改为火锅,还把宴会地点改到皇极殿内。

至于人数嘛,他也压缩了不少,这样一来,再没发生过死人的事情。

只是,乾隆两次举办的“千叟宴”,都没能带来康熙举办时的轰动效应,还害死了不少老人,没死的老人,生活也没什么变化。

再加上乾隆在世时,耗费了不少财力国力,制造了不少矛盾。

以至于乾隆去世后,清王朝开始麻烦不断,盗贼四起,起义频发,朝廷与民间尖锐对立。

因此,后世皇帝们继位后,便摒弃了“千寿宴”这一宫廷宴会了。

随机文章博物馆是南部邦联纪念碑的理想之家吗?蓝宝石般的伯利兹大蓝洞天坑,潜水员与鲨鱼共舞(深123米)最严重香港启德机场事故,美陆战队飞机坠海致56人死亡乌兹别克斯坦地狱之门,1000度的地狱门户燃烧54年网红区块链的应用领域有哪些,几乎能被运用到各行各业(未来可期)

吃石榴的好处与功效吃石榴的季节是几月份

石榴是一种营养价值很高的水果,吃石榴对我们的身体是有非常多的好处的,但是很少有人了解过石榴的功效作用,那么我们便来了解一下吃石榴的好处与功效?吃石榴的季节是几月份?吃石榴的好处与功效石榴具有止血,收敛,解酒,有抗菌杀虫的功效,石榴富含矿物质、碳水化合物、维生素、膳食纤维、蛋白质、脂肪等营养成分,并且它含有生物碱,对于黄金葡萄球菌,溶血性链球菌有明显的抑制作用,对于身体的寄生虫有麻醉,驱虫,杀虫的作用,中医认为石榴具有收敛、收敛、止痢的功效,经常食用石榴汁,能够有助于降低婴儿大脑发育受损的概率。

还可以有效缓解腹泻、痢疾,辅助治疗腹泻、便血、痢疾、脱肛。

还有抗衰老,保护神经系统稳定情绪的作用。

此外,石榴还能抑制皮肤真菌和流感病毒,对金黄色葡萄球菌、霍乱弧菌和痢疾杆菌有明显的抑制作用。

吃石榴会上火还是降火上火。

石榴虽然好,但是它不能多吃。

石榴的糖分多,吃多了会上火。

所以要注意适量吃。

石榴当中含微量元素和多种氨基酸,可以帮助消化、抗胃溃疡。

中医上讲,石榴性温、味甘酸涩,具有生津止渴、止泻止血的功效;可治疗口燥咽干、烦渴等病症。

对于饮酒过量的人,石榴还有解酒的功效。

石榴皮中含有多种生物碱,抑菌试验证实,石榴的醇浸出物及果皮水煎剂,具有广谱抗菌作用,其对金黄色葡萄球菌、溶血性链球菌、霍乱弧菌、痢疾杆菌等有明显的抑制作用,其中对志贺氏痢疾杆菌作用最强,石榴皮水浸剂在试管内对各种皮肤真菌也有不同程度的抑制作用,石榴皮煎剂还能抑制流感病毒。

石榴味道酸,当中含有生物碱、熊果酸等,有收敛作用,可以涩肠止血。

此外,石榴还有抑菌作用。

因此可以帮助治疗痢疾、泄泻等病症。

加入收藏
               

C#之int与Java之Integer的分别

点击下载文档

格式为doc格式

  • 账号登录
社交账号登录