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,的,区别,本文,涉

《神之天平》强化流BD一览

《神之天平》的流派搭配比较自由,玩家可以搭配技能、天平、装备来进行BD。

今天小编就和大家分享《神之天平》强化流BD一览一起来看看吧。

《神之天平》强化流BD一览强化流核心技能:魔法扫帚(替换)、风精灵、再生(替换)、海龟盾防、狂战士,如图魔导力2700、攻击力5000、防御5500,攻速鬼畜(禁用升龙剑,向上攻击),光速回血。

天平核心效果:最大体力、最大精力、魔导力、体力回复量、精力提升量、效果时间、使用速度,星极强三个等级的效果全齐。

核心装备:攻击距离长的武器,其他随意。

加点主魔导力,敏捷点到重量0,超出衰减线的全点适应力和幸运。

核心嘉隆:自动连击、恶魔的右手、暗黑、恶魔的狂热、强化持续(替换)、道、爆发、召唤的秘诀。

综上,可以形成一套无脑平A站撸的无聊配装,秒回血比怪打的还多,攻速快到游戏卡成0.5倍速,唯一的弱点是启动比较慢。

打小怪一般只开魔法扫帚、风精灵、再生,节奏比较舒服;打boss5个buff拉满。

以上就是今天为大家带来的《神之天平》强化流BD一览的全部内容,喜欢的小伙伴们不要忘记关注一下绿色先锋,更多的和游戏攻略在这里等你探索 上一篇: 下一篇:

【限时特惠】超实用U盘之家工具包,助您解决各种存储问题!

想重装系统不会怎么办?菜科网一键重装系统轻松在线帮您搞定系统重装问题。

软件支持 在线重装、U盘制作、自定义重装 等多种模式。

【限时特惠】超实用U盘之家工具包,助您解决各种存储问题!现在购买超实用U盘之家工具包,即可享受限时特惠!通过使用这个工具包,您可以轻松解决各种存储问题,让您的工作更加高效方便。

接下来,让我们详细了解一下这个工具包的具体内容。

工具原料:系统版本:Windows 10品牌型号:联想ThinkPad X1 Carbon软件版本:U盘之家工具包v1.0一、快速备份文件通过U盘之家工具包,你可以快速备份你的重要文件。

不论是文档、照片还是视频,只需将文件拖拽至指定的文件夹,软件会自动帮你完成备份工作。

再也不用担心文件丢失或误删的问题了。

二、安全加密存储我们越来越依赖于U盘来存储重要的个人和工作文件,然而,一旦丢失或泄露,可能会引发严重的安全问题。

U盘之家工具包提供了强大的加密存储功能,您可以为您的文件设置密码,确保只有授权人员可以访问。

三、方便的文件同步如果您经常在多台电脑上工作,可能会遇到不同电脑之间文件的同步问题。

U盘之家工具包可以解决这个问题,您只需将文件拖拽至指定的同步文件夹,软件会自动将文件同步到各个设备上,让您的工作更加无缝衔接。

四、一键修复损坏文件有时候我们可能会遇到U盘中的文件损坏无法打开的情况,这可能会导致重要数据丢失。

U盘之家工具包提供了一键修复损坏文件的功能,只需点击修复按钮,软件会尽力恢复您的文件,最大程度减少数据损失。

总结:通过超实用U盘之家工具包,您可以轻松解决文件备份、安全加密存储、文件同步以及文件修复等各种存储问题。

无论您是个人用户还是企业用户,这个工具包都能为您提供便捷高效的存储解决方案。

标签: 注意:本站所刊载的文章均为学习交流之用,请勿用于商业用途。

对于商业使用,请联系各自版权所有者,否则法律问题自行承担。

Win7系统升级指南:全面解析升级步骤与要点 Win7系统损坏修复教程:详细步骤助你快速解决问题 【限时特惠】超实用U盘之家工具包,助您解决各种存储问题! 分类于: 回答于:2023-10-26 【限时特惠】超实用U盘之家工具包,助您解决各种存储问题!现在购买超实用U盘之家工具包,即可享受限时特惠!通过使用这个工具包,您可以轻松解决各种存储问题,让您的工作更加高效方便。

接下来,让我们详细了解一下这个工具包的具体内容。

工具原料:系统版本:Windows 10品牌型号:联想ThinkPad X1 Carbon软件版本:U盘之家工具包v1.0一、快速备份文件通过U盘之家工具包,你可以快速备份你的重要文件。

不论是文档、照片还是视频,只需将文件拖拽至指定的文件夹,软件会自动帮你完成备份工作。

再也不用担心文件丢失或误删的问题了。

二、安全加密存储我们越来越依赖于U盘来存储重要的个人和工作文件,然而,一旦丢失或泄露,可能会引发严重的安全问题。

U盘之家工具包提供了强大的加密存储功能,您可以为您的文件设置密码,确保只有授权人员可以访问。

三、方便的文件同步如果您经常在多台电脑上工作,可能会遇到不同电脑之间文件的同步问题。

U盘之家工具包可以解决这个问题,您只需将文件拖拽至指定的同步文件夹,软件会自动将文件同步到各个设备上,让您的工作更加无缝衔接。

四、一键修复损坏文件有时候我们可能会遇到U盘中的文件损坏无法打开的情况,这可能会导致重要数据丢失。

U盘之家工具包提供了一键修复损坏文件的功能,只需点击修复按钮,软件会尽力恢复您的文件,最大程度减少数据损失。

总结:通过超实用U盘之家工具包,您可以轻松解决文件备份、安全加密存储、文件同步以及文件修复等各种存储问题。

无论您是个人用户还是企业用户,这个工具包都能为您提供便捷高效的存储解决方案。

菜科网系统致力于解决 Windows 系统重装解决方案,提供高效、安全、免费的系统重装服务。

加入收藏
               

C#之int与Java之Integer的分别

点击下载文档

格式为doc格式

  • 账号登录
社交账号登录