纹理和基元_Java的精妙之处,包括基元和变量参数数组

纹理和基元

在我最近的博客文章Arrays.hashCode()与 DZone联合版本的评论中提出了一个有趣的问题。 Objects.hash() “。 该评论的作者建立了一些示例,这些示例与我的博客文章中使用的示例相似,并且显示出与我看到的结果不同的结果。 感谢评论作者抽出宝贵的时间来发表这篇文章,因为它引起了Java的细微差别,我认为这很值得写博客。

评论作者显示了以下有效的Java语句:

int[] arr = new int[]{1,2,3,4};
System.out.println(Arrays.hashCode(arr));
System.out.println(Objects.hash(1,2,3,4));
System.out.println(Arrays.hashCode(new Integer[]{new Integer(1),new Integer(2),new Integer(3),new Integer(4)}));
System.out.println(Objects.hash(new Integer(1),new Integer(2),new Integer(3),new Integer(4)));

该评论的作者提到,对于所有四个语句,运行刚显示的代码的结果都完全相同。 这与我的示例不同,在示例中,在原始int值数组上调用Arrays.hashCode(int [])的结果与在同一原始int值数组上调用Objects.hash(Object…)的结果不同。

对原始反馈评论的一个答复准确地指出,不能保证在不同JVM上生成的哈希码是相同的。 实际上, Object.hashCode()方法的Javadoc注释指出(我强调了 ):

  • 只要在Java应用程序执行期间同一对象上多次调用它,hashCode方法就必须一致地返回相同的整数,前提是不修改该对象的equals比较中使用的信息。 从一个应用程序的执行到同一应用程序的另一执行,此整数不必保持一致。
  • 如果根据equals(Object)方法两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。

陈述了所有这些内容之后,为整数计算的哈希码通常在每次运行之间都是一致的。 原始评论者示例的输出都具有完全相同的值也很有趣。 尽管我可能不希望这些值与示例的值相匹配,但令人惊讶的是,评论者提供的所有示例都具有相同的答案。

反馈注释中提供的示例与我的示例之间的区别在于注释者的示例如何为原始int值数组调用Objects.hash(Object...)与我的示例如何调用Objects.hash(Object...)用于原始int值的数组。 在我的示例中,我将相同的本地数组传递给所有方法调用。 该注释者的示例将原始int值的显式数组传递给Arrays.hashCode(int[]) ,但将各个int元素传递给Objects.hash(Object...)而不是将数组传递给该后一种方法。 当我向注释者的示例集中添加另一个示例,该示例确实将原始int值数组传递给Objects.hash(Object...)方法时,我得到的生成的哈希码与所有其他哈希码不同。 接下来显示该增强的代码。

final int[] arr = new int[]{1,2,3,4};
out.println("Arrays.hashCode(int[]):              " + Arrays.hashCode(arr));
out.println("Objects.hash(int, int, int, int):    " + Objects.hash(1,2,3,4));
out.println("Objects.hash(int[]):                 " + Objects.hash(arr));
out.println("Objects.hashCode(Object):            " + Objects.hashCode(arr));
out.println("int[].hashCode():                    " + arr.hashCode());
out.println("Arrays.hashCode(Int, Int, Int, Int): " + Arrays.hashCode(new Integer[]{1,2,3,4}));
out.println("Objects.hash(Int, Int, Int, Int):    " + Objects.hash(1,2,3,4));

运行注释器提供的代码的经过修改和增强的版本会导致此输出(突出显示我添加的示例):

Arrays.hashCode(int[]):              955331
Objects.hash(int, int, int, int):    955331
Objects.hash(int[]):                 897913763
Objects.hashCode(Object):            897913732
int[].hashCode():                    897913732
Arrays.hashCode(Int, Int, Int, Int): 955331
Objects.hash(Int, Int, Int, Int):    955331

将输出与生成它的代码进行比较,可以看出,当将int值数组的元素传递给Arrays.hashCode(int[]) ,它与Objects.hash(Object...)生成相同的哈希码值Objects.hash(Object...)方法作为单个元素。 但是,我们还可以看到,当完整地传递原始int值的数组(作为单个数组而不是作为数组的单个元素)时, Objects.hash(Object...)方法生成了完全不同的哈希码。 我添加的其他两个示例(突出显示)是通过直接在数组上调用.hashCode()或通过Objects.hashCode获得等效的结果来显示原始int值数组上的“直接”哈希码。 (对象) 。 [这不是巧合, Objects.hash(Object...)为原始int值数组生成的哈希码比为原始int值数组生成的“直接”哈希码正好大31。 ]

所有这些都指向这里的真正问题:通常最好不要将原语数组传递给接受可变参数 (通告省略号 )的方法。 SonarSource规则浏览器 ( Java )在RSPEC-3878中提供了有关此内容的更多详细信息。 与规则描述特别相关的是与歧义有关的问题:“数组应该是一个对象还是对象的集合?”

刚刚提出的问题的答案是,当将原始int值数组传递给接受方法Objects.hash(Object...)的变量参数时, 整个数组将被视为单个 Object 。 相反,当将引用对象的数组(例如Integer )传递给相同的方法时,它将其视为与传递给数组的元素相同数量的对象。 下一个代码清单和相关输出证明了这一点。

package dustin.examples.hashcodes;import static java.lang.System.out;/*** Demonstrates the difference in handling of arrays by methods that* accept variable arguments (ellipsis) when the arrays have primitive* elements and when arrays have reference object elements.*/
public class ArraysDemos
{private static void printEllipsisContents(final Object ... objects){out.println("==> Ellipsis Object... - Variable Arguments (" + objects.length + " elements): " + objects.getClass() + " - " + objects);}private static void printArrayContents(final Object[] objects){out.println("==> Array Object[] - Variable Arguments (" + objects.length + " elements): " + objects.getClass() + " - " + objects);}private static void printArrayContents(final int[] integers){out.println("==> Array int[] - Variable Arguments (" + integers.length + " elements): " + integers.getClass() + " - " + integers);}public static void main(final String[] arguments){final int[] primitiveIntegers = ArraysCreator.createArrayOfInts();final Integer[] referenceIntegers = ArraysCreator.createArrayOfIntegers();out.println("\nint[]");printEllipsisContents(primitiveIntegers);printArrayContents(primitiveIntegers);out.println("\nInteger[]");printEllipsisContents(referenceIntegers);printArrayContents(referenceIntegers);}
}
int[]
==> Ellipsis Object... - Variable Arguments (1 elements): class [Ljava.lang.Object; - [Ljava.lang.Object;@2752f6e2
==> Array int[] - Variable Arguments (10 elements): class [I - [I@1cd072a9Integer[]
==> Ellipsis Object... - Variable Arguments (10 elements): class [Ljava.lang.Integer; - [Ljava.lang.Integer;@7c75222b
==> Array Object[] - Variable Arguments (10 elements): class [Ljava.lang.Integer; - [Ljava.lang.Integer;@7c75222b

刚刚显示的示例代码和相关的输出说明,期望变量参数的方法将传递给它的原始值数组视为单个元素数组 。 另一方面,相同的方法将通过引用对象类型传递给它的数组视为具有相同元素数的数组。

考虑到这一点,请返回哈希码生成示例,由Objects.hash(Object...)为原始int值数组生成的哈希码与由Arrays.hashCode(int[])生成的哈希码不同。 类似地,我们现在可以解释为什么对象引用数组导致相同的哈希码,而不管调用了哪种方法。

我之前提到过,由Objects.hash(Object)生成的哈希码比整个数组的“直接”哈希码高31并非巧合。 这并不奇怪,因为Objects.hash(Object...)的OpenJDK实现将Arrays.hashCode(Object[]) Objects.hash(Object...)委托给Arrays.hashCode(Object[]) ,该数组使用素数乘以31 ,然后乘以计算出的哈希码中的每个元素。 考虑到上述观察,由Objects.hash(Object...)为原始int值数组提供的哈希码值似乎正是该方法的实现将导致我们期望的结果:整个数组的直接哈希值加上31个质数。 当该哈希码方法仅循环一个元素时(传递给需要可变参数的方法的基元数组就是这种情况),其计算本质上是31 * 1 + <directHashValueOfOverallArray>

值得注意的是,即使参考对象数组的哈希码计算得出的结果与将元素传递给接受变量参数的方法时的结果相同,还是最好避免将参考对象数组传递给这样的对象。方法。 当发生这种情况时, javac编译器会提供此警告:“警告:对最后一个参数使用不精确的参数类型的varargs方法的非varargs调用”,并添加了有关解决此问题的潜在方法的这些有用的细节:“为varargs调用广播到对象”或“广播到Object []以进行非可变参数调用并禁止显示此警告”。 当然,对于JDK 8和更高版本,在将数组提供给需要可变参数的方法之前,以多种其他方式处理数组是相当简单的。

我在原始帖子 (及其DZone联合版本 )中添加了最后一段,以尝试快速解决此问题,但是我已经使用此帖子来更详细地表达此信息。 此处总结的经验教训可以概括为“对原始数组使用适当的重载Arrays.hashCode方法,而不是使用Objects.hash(Object...) ”和“ Favor Arrays.hashCode(Object[])对于引用类型,而不是使用Objects.hash(Object...) 。” 如果调用的方法“看到”的元素数量无论如何都是重要的,则更通用的准则是要警惕将原始值数组传递给需要Object类型变量参数的方法,并且要警惕传递引用数组指向期望可变参数的方法的对象,以避免编译器警告和模棱两可的警告。

翻译自: https://www.javacodegeeks.com/2018/09/java-subtlety-with-arrays-of-primitives-and-variable-arguments.html

纹理和基元

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/332976.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ORACLE数据库常用命令总结

SELECT * FROM all_tables WHERE ownericore_prdtdb; --查询当前用户下所有的表名 SELECT table_name FROM user_tables; --查询当前用户下所有的表 SELECT * FROM user_tables; --查询当前用户下所有的索引 SELECT * FROM USER_indexes; --查询当前用户下所有的序列 SEL…

MacOS使用brew无法安装Python_无法安装gdbm_无法安装autojump

文章目录出现的问题解决无法安装gbdm的问题解决无法安装Python的问题GNU 程序国内下载源&#xff1a;https://mirrors.ustc.edu.cn/gnu/ brew 下载的软件安装包存放在下面的目录&#xff1a; liaowenxiongdeMacBook-Air:Homebrew liaowenxiong$ brew --cache /Users/liaowenx…

客户说发货慢怎么回复_?沐言恋爱学:当女生说“我累了”,怎么回复最合适?...

沐言恋爱学&#xff1a;当女生说“我累了”&#xff0c;怎么回复最合适&#xff1f;学员提问&#xff1a;沐言解答&#xff1a;01兄弟你在考虑该怎么回复她之前你需要做的不仅仅是直接读懂她的字面意思而是需要了解事情背景比如&#xff1a;时间她经历的事情是不是身体不太舒服…

react 线程_React式服务中的线程本地状态可用性

react 线程任何架构决策都需要权衡。 如果您决定采用React式&#xff0c;也没有什么不同&#xff0c;例如&#xff0c;一方面使用React式流实现几乎可以立即获得更好的资源利用率&#xff0c;但另一方面会使调试更加困难。 引入React式库也对您的域产生巨大影响&#xff0c;您的…

iTerm2的使用技巧及快捷键

文章目录查看剪贴板内容清屏切换全屏切屏/分屏切换标签栏移动标签栏编辑会话打开最近的目录复制粘贴查找移动光标搜索历史命令查看历史命令删除滚屏界面窗口缩放搜索会话/配置文件/快照展开&#xff08;Expose&#xff09;所有的标签窗口操作查看当前终端中光标的位置开启和关闭…

位运算和进制转换,反码补码

进制转换 package junit;public class Test {public static void main(String[] args) { // int aInteger.MIN_VALUE;int bInteger.MAX_VALUE;int cInteger.MIN_VALUE;System.out.println(b);System.out.println(c);print(b);// 最高位表示 符号位 最高位0 表示正数 …

python绘制pr曲线图_如何利用Python制作可以动的动态图表。

来源&#xff1a;机器之心原文链接&#xff1a;https://towardsdatascience.com/learn-how-to-create-animated-graphs-in-python-fce780421afe在读技术博客的过程中&#xff0c;我们会发现那些能够把知识、成果讲透的博主很多都会做动态图表。他们的图是怎么做的&#xff1f;难…

switch字符串jdk_JDK 12 Early Access Build 12中的原始字符串文字支持

switch字符串jdk本周Java世界上最大的新闻可能是JDK 11的通用性。 但是&#xff0c;另一个令人兴奋的发展是JDK 12 Early Access Build 12的发布 &#xff08; 2018年9月20日 &#xff09;。 JDK 12的这个早期访问生成12是显著&#xff0c;因为它包括与实施方式中JEP 326 [“原…

MacOS安装pip失败,提示:SyntaxError: invalid syntax

使用命令 easy_install 安装 pip 使用命令 sudo easy_install pip 安装 pip&#xff0c;结果失败了&#xff0c;执行命令的信息如下&#xff1a; ➜ ~ sudo easy_install pip Password: Searching for pip Reading https://pypi.org/simple/pip/ Downloading https://files.…

java压缩视频

引入依赖 <dependency><groupId>ws.schild</groupId><artifactId>jave-core</artifactId><version>3.0.0</version></dependency><dependency><groupId>ws.schild</groupId><artifactId>jave-all-dep…

经济学自身利益最大化_劳动经济学:研究劳动力市场运作的专业

多年以来同学们对劳动经济学认知上存在误区&#xff0c;很多同学一上来看到劳动两字会误以为这是让自己去当工人干活。事实并非如此&#xff0c;例如人力资源管理&#xff0c;大家都知道是一门很热门、实用的管理学&#xff0c;毕业后可以从事hr的工作&#xff0c;其实劳动经济…

corda_使用Spring WebFlux从Corda节点流式传输数据

corda自上次发布以来已经有一段时间了&#xff0c;但我终于回来了&#xff01; 由于我仍在我的项目中&#xff0c;因此我将再次撰写有关使用Corda的文章。 这次&#xff0c;我们将不再关注Corda&#xff0c;而是将Spring与Corda结合使用。 更具体地说&#xff0c;Spring WebFlu…

iTerm2 隐藏用户名和主机名

有时候我们的用户名和主机名太长&#xff0c;比如我的&#xff1a; 这么长的提示符前缀&#xff0c;在终端显示的时候会很不好看&#xff0c;我们可以手动去除。 编辑 ~/.zshrc 文件&#xff0c;增加 DEFAULT_USER"lwx" 配置&#xff0c;如下所示&#xff1a; 注…

投影串口测试程序_串口测试方法和步骤

信号测试与分析版号&#xff1a;xxx编写&#xff1a;xxx1、232串口信号&#xff1a;要点&#xff1a;RS232采用三线制传输分别为TXD\RXD\GND其中TXD为发送信号&#xff0c;RXD为接收信号。全双工&#xff0c;在RS232中任何一条信号线的电压均为负逻辑关系。即&#xff1a;—15v…

springBoot中自定义的yml文件引用的方式

一、yml配置文件 在yam文件中配置自定义的标签 1.在yml配置文件中加入 through:url: http://10.4.2.140:49003/IBSThrough2.测试类进行测试 import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; /…

MacOS安装zsh插件zsh-autosuggestion(自动命令补全和建议)

文章目录安装命令一安装命令二安装命令三使用插件 zsh-autosuggestion 用于命令建议和补全。 GitHub主页&#xff1a;https://github.com/zsh-users/zsh-autosuggestions 安装命令一 cd ~/.oh-my-zsh/custom/plugins/ git clone https://github.com/zsh-users/zsh-autosugg…

javafx 调用java_Java,JavaFX的流畅设计风格拨动开关

javafx 调用java嗨&#xff0c;这次我将在新版本的JMetro中讨论新的Toggle Switch样式。 拨动开关是一种近年来非常流行的控件。 我前一段时间在ControlsFX库中添加了JavaFX实现。 刚刚发布的JMetro版本4.1中提供了此新样式。 什么是拨动开关 在以前的文章中&#xff0c;我讨…

polkit 重新安装_不折腾,为U-NAS安装一个清爽的桌面,把小U打造成双面高手

本帖最后由 emaic 于 2012-2-2 03:41 编辑除了文件的存储和下载外&#xff0c;U-NAS还可以干嘛&#xff1f;其实&#xff0c;只要你-U-NAS的硬件性能足够强悍&#xff0c;U-NAS可以完成很多你意想不到的工作哦&#xff0c;也会有很多意想不到的玩法&#xff0c;希望看了emaic打…

用于zsh的插件incr(目录提示和补全)

文章目录使用命令 wget 下载插件直接下载插件脚本文件配置提示存在不安全目录incr 是一个目录提示和补全插件。 使用命令 wget 下载插件 mkdir ~/.oh-my-zsh/custom/plugins/incr cd ~/.oh-my-zsh/custom/plugins/incr wget -O incr.plugin.zsh http://mimosa-pudica.net/src…

普罗米修斯使用es数据库_用普罗米修斯和格拉法纳仪法来豪猪

普罗米修斯使用es数据库Adam Bien的Porcupine库使配置充当应用程序隔板的专用执行程序服务变得容易。 我创建了一个扩展&#xff0c;通过MicroProfile Metrics公开了豪猪统计信息。 我们还可以通过Prometheus和Grafana仪表板使仪器可见。 进行此扩展的原因是我们希望对Porcupi…