Java如何处理整数下溢和溢出?
在此之后,您将如何检查/测试这是否正在发生?
可能重复:
默认情况下,为什么语言不会引发整数溢出错误?
为什么C#默认不使用算术溢出检查?
我认为发生异常通常会更好,这样就不会模糊错误.我知道利用发生的"包装"行为偶尔会有用,但unchecked
在这些情况下可以使用关键字来明确意图.
我希望这个决定是故意做出的,也许是为了增加与其他基于C语言的兼容性.
Python比其他脚本语言更强类型.例如,在Perl中:
perl -E '$c=5; $d="6"; say $c+$d' #prints 11
Run Code Online (Sandbox Code Playgroud)
但是在Python中:
>>> c="6"
>>> d=5
>>> print c+d
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects
Run Code Online (Sandbox Code Playgroud)
Perl将检查字符串并转换为数字,并且+ - / * **
运算符按预期使用数字.PHP类似.
Python用于+
连接字符串,因此尝试的操作c+d
失败,因为c是一个字符串,d是一个int.Python 比Perl 具有更强的数字类型感.好的 - 我可以解决这个问题.
但考虑一下:
>>> from sys import maxint
>>> type(maxint)
<type 'int'>
>>> print maxint
9223372036854775807
>>> type(maxint+2)
<type 'long'>
>>> print maxint+2
9223372036854775809
>>> type((maxint+2)+maxint)
<type 'long'>
>>> …
Run Code Online (Sandbox Code Playgroud) 我甚至可以计算(expt 32768 32768
),我得到了:
476170470581645852036305042887575891541065808607552399123930385521914333389668342420684974786564569494856176035326322058077805659331026192708460314150258592864177116725943603718461857357598351152301645904403697613233287231227125684710820209725157101726931323469678542580656697935045997268352998638215525166389437335543602135433229604645318478604952148193555853611059596230656
在Java算术运算期间,JVM不会抛出下溢或溢出异常.很多时候,我们遇到了意想不到的结果,并想知道出了什么问题.
在.NET技术的情况下,我们有溢出和Undeflow异常.
所以我的问题是,为什么Java设计不会在算术运算期间抛出此异常
这个问题源于一个错误,我迭代了一个集合,Int64
并意外地做了foreach (int i in myCollection)
.我试图调试令人困惑的问题,当我做一个linq查询,i
不是一部分myCollection
.
这里有一些令我惊讶的代码:
Int64 a = 12345678912345;
Console.Write((int)a);
Run Code Online (Sandbox Code Playgroud)
我希望编译器给我一个错误.通常的一个是隐式演员表不存在.但不,它根本不介意这一点.甚至没有警告!
(int)a
偶然的输出值是1942903641
.
我很想知道为什么演员在没有任何警告的情况下被允许,以及它是如何产生这个价值的.有任何想法吗?
我已经学会了(至少在java中)整数/长值静默地溢出,它们的值从溢出时的最小值开始而不是抛出任何异常.
我正在使用外部api进行某些文件操作,其中从文件属性加载最大文件大小.在我当地的测试环境中一切都很好.代码进入实时环境后,最大文件大小限制根本不起作用.经过两天调试/分析代码后,根本没有成功.然后由于其他原因,我采用了live constants.properties文件并用它调试了代码.O_0
我只想问,是什么阻止他们在溢出时抛出异常?
List(Of T)
当我将内部_version
字段设置为Integer.MaxValue
并添加新项时,是什么阻止了抛出算术溢出异常?
TL; DR:
正如您在查看源代码时所看到的那样,没有针对潜在算术溢出的保护.但是,Integer.MinValue
如果值是最大值,那么某些事物就会将值设置为.
<__DynamicallyInvokable()> _
Public Sub Add(ByVal item As T)
If (Me._size = Me._items.Length) Then
Me.EnsureCapacity((Me._size + 1))
End If
Me._items(Me._size++) = item
Me._version += 1
End Sub
Run Code Online (Sandbox Code Playgroud)
详细
由于List(Of T)的内部项数组是私有的,我不会使用反射来访问它,我决定使用原始List(Of T)源代码创建自定义列表.
但是,我注意到,如果版本达到Integer.MaxValue,则无法防止潜在的算术溢出.
Me._version += 1
Run Code Online (Sandbox Code Playgroud)
所以我修改了代码:
Me._version = If((Me._version = Integer.MaxValue), Integer.MinValue, (Me._version + 1I))
Run Code Online (Sandbox Code Playgroud)
现在开始有趣的部分; 出于好奇,我设置了一个测试,我使用反射将内部_version
字段设置为最大值.
Dim flags As BindingFlags = (BindingFlags.Instance Or BindingFlags.NonPublic)
Dim list As New List(Of String) …
Run Code Online (Sandbox Code Playgroud) 由于性能原因,似乎默认情况下c#中的算术溢出检查已关闭(请参阅/sf/answers/7614351/等).
但是,如果我打开它,使用/ checked标志或checked关键字,运行时实际上如何执行检查?(我正在努力更好地理解这种"性能打击"的全部内容.)