自动装箱,拆箱和NoSuchMethodError

J2SE 5为Java编程语言引入了许多功能。 这些功能之一是自动装箱和拆箱 ,这是我几乎每天都没有考虑过的功能。 它通常很方便(尤其是与收藏夹一起使用时),但有时会导致一些令人讨厌的惊喜 ,即“ 怪异 ”和“ 疯狂” 。 在此博客文章中,我介绍了一种罕见的NoSuchMethodError案例(但对我来说很有趣),该案例是由于在自动装箱/拆箱之前将使用Java版本编译的类与包含自动装箱/取消装箱的Java版本编译的类混合在一起而造成的。

下一个代码清单显示了一个简单的Sum类,该类可以在J2SE 5之前编写。它已重载了“ add”方法,这些方法接受不同的原始数值数据类型,并且Sum>每个实例Sum>简单地添加了通过以下任何一种方式提供给它的所有数字类型其重载的“添加”方法。

Sum.java(J2SE 5之前的版本)

import java.util.ArrayList;public class Sum
{private double sum = 0;public void add(short newShort){sum += newShort;}public void add(int newInteger){sum += newInteger;}public void add(long newLong){sum += newLong;}public void add(float newFloat){sum += newFloat;}public void add(double newDouble){sum += newDouble;}public String toString(){return String.valueOf(sum);}
}

在无法进行拆箱之前,上述Sum类的所有客户端都需要向这些“添加”方法提供原语,或者,如果它们具有与原语相同的引用,则需要在将其中一个引用称为“添加”方法。 在调用这些方法之前,在客户端代码上有责任从引用类型转换为相应的原始类型。 下一个代码清单中显示了如何完成此操作的示例。

不取消装箱:客户端将引用转换为基元

private static String sumReferences(final Long longValue, final Integer intValue, final Short shortValue)
{final Sum sum = new Sum();if (longValue != null){sum.add(longValue.longValue());}if (intValue != null){sum.add(intValue.intValue());}if (shortValue != null){sum.add(shortValue.shortValue());}return sum.toString();
}

J2SE 5的自动装箱和拆箱功能旨在解决这种情况下所需的额外工作 。 通过取消装箱,客户端代码可以使用与预期的基本类型相对应的引用类型来调用上述“添加”方法,并且这些引用将自动“取消装箱”为原始形式,以便可以调用适当的“添加”方法。 Java语言规范的 第5.1.8节 (“取消装箱转换”)说明了提供的数字引用类型在取消装箱中将转换为哪些原语,该规范的 第5.1.7节 (“装箱转换”)列出了自动装箱的引用类型。从自动装箱中的每个原语。

boxingAndUnboxing_transparentbg

在此示例中,在调用Sum的“ add”方法之前,将引用类型转换为对应的原始对等类型,从而使客户方面的拆箱工作减少了,但并没有使客户完全不必在提供它们之前处理数字值。 因为引用类型可以为null ,所以客户端可以为Sum的“ add”方法之一提供null引用,并且当Java尝试自动将null取消装箱到其对应的原语时,将引发NullPointerException 。 下一个代码清单从上面进行了改编,以指示在客户端不再需要将引用转换为原语,但是仍然需要检查null以避免NullPointerException 。

自动取消装箱秘密对原始的引用:仍然必须检查是否为空

private static String sumReferences(final Long longValue, final Integer intValue, final Short shortValue)
{final Sum sum = new Sum();if (longValue != null){sum.add(longValue);}if (intValue != null){sum.add(intValue);}if (shortValue != null){sum.add(shortValue);}return sum.toString();
}

在设计API时,可能需要避免客户端代码在Sum上调用“ add”方法之前检查其引用是否为null。 消除需求的一种方法是更改​​“添加”方法以显式接受引用类型,而不是原始类型。 然后, Sum类可以在显式或隐式(取消装箱)对它进行解引用之前检查null。 接下来显示了经过修改的Sum类,其中包含已更改的,更易于客户端使用的API。

用“ add”方法求和的类期望引用而不是基元

import java.util.ArrayList;public class Sum
{private double sum = 0;public void add(Short newShort){if (newShort != null){sum += newShort;}}public void add(Integer newInteger){if (newInteger != null){sum += newInteger;}}public void add(Long newLong){if (newLong != null){sum += newLong;}}public void add(Float newFloat){if (newFloat != null){sum += newFloat;}}public void add(Double newDouble){if (newDouble != null){sum += newDouble;}}public String toString(){return String.valueOf(sum);}
}

修改后的Sum类对客户端更友好,因为它允许客户端将引用传递给它的任何“ add”方法,而不必担心传入的引用是否为null。 但是,如果涉及的任何一个类(客户端类或Sum类的一个版本)都使用不同版本的Java编译,则像这样对Sum类的API进行更改可能会导致NoSuchMethodError 。 特别是,如果客户端代码使用原语并且使用JDK 1.4或更早版本进行编译,并且Sum类是所示的最新版本(期望使用引用代替原语)并且使用J2SE 5或更高版本进行了编译,则将遇到类似以下内容的NoSuchMethodError (“ S”表示它是“ add”方法,它期望原始short ,而“ V”表示该方法返回void )。

Exception in thread "main" java.lang.NoSuchMethodError: Sum.add(S)Vat Main.main(Main.java:9)

另一方面,如果客户端使用J2SE 5或更高版本进行编译,并且如第一个示例中那样将原始值提供给Sum (预拆箱),并且Sum类在JDK 1.4或更早版本中使用“ add”方法进行编译原语,会遇到不同版本的NoSuchMethodError 。 请注意,此处引用了Short参考。

Exception in thread "main" java.lang.NoSuchMethodError: Sum.add(Ljava/lang/Short;)Vat Main.main(Main.java:9)

由此可见对Java开发人员的一些观察和提醒。

  • 类路径很重要:
    • 使用相同版本的Java(相同的-source-target )编译的Java .class文件可以避免本文中的特定问题。
  • 自动装箱和取消装箱的目的是很好的,并且通常非常方便,但是如果在一定程度上不牢记,可能会导致令人惊讶的问题。 在这篇文章中,仍然需要检查空值(或知道对象不是空值),这是由于拆箱而导致隐式解引用的情况。
  • 是否允许客户端传递null并让服务类代表它们检查null是API风格的问题。 在工业应用程序中,我将用每个方法的Javadoc注释中的@param声明每个“添加”方法参数是否允许为null。 在其他情况下,可能要让调用者负责确保任何传入的引用都不为空,并且如果调用者不遵守该约定,则抛出NullPointerException内容将是满意的(也应在方法的Javadoc)。
  • 尽管通常会在完全删除某个方法或在该方法可用之前访问旧类或方法的API在类型或类型数方面发生更改时看到NoSuchMethodError 。 在Java自动装箱和拆箱在很大程度上被视为理所当然的日子里,很容易想到将方法从采用原语转换为采用相应的引用类型不会产生任何影响,但是即使这种更改也会导致异常,如果并非所有涉及的类都基于支持自动装箱和拆箱的Java版本构建。
  • 确定要针对其编译特定.class文件的Java版本的一种方法是使用javap -verbose并在javap输出中查找“主要版本:”。 在本文示例中使用的类(针对JDK 1.4和Java SE 8编译)中,“ 主要版本 ”条目分别为48和52( Java类文件上Wikipedia条目的“ 常规布局”部分列出了主要版本) )。

幸运的是,由于构建通常会清理所有工件并在相对连续的基础上重建代码,因此本文中使用示例和文本演示的问题并不常见。 但是,在某些情况下可能会发生这种情况,最可能的情况之一是意外使用旧的JAR文件时,因为它位于运行时类路径上的等待中。

翻译自: https://www.javacodegeeks.com/2014/08/autoboxing-unboxing-and-nosuchmethoderror.html

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

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

相关文章

vue 动态显示三级路由

无需 vuex、本地存储实现动态显示三级路由。 目录 一、需求描述: 二、代码 2.1 路由配置 1. 我的一级菜单和二级菜单的路由配置的: 2. 三级菜单的路由配置: 3. 上面有几个变量和要注意的细节: 2.2 封装导航栏 2.3 封装面…

第二章 Vue快速入门-- 18 v-for中key的使用注意事项

注意:如果属性和方法还没定义直接使用的话&#xff0c;就会报 xxx is not defined 导致界面不能正常显示。我看视频教程里老师的可以直接使用&#xff0c;而且界面正常显示&#xff0c;可能是vue版本不同吗&#xff1f;还不清楚 1 <!DOCTYPE html>2 <html lang"…

vue 后端返回二进制流文件,前端如何实现下载?

目录 1. axios 请求二进制流文件导出文件 1.1 后台返回的二进制流&#xff1a; 1.2 使用&#xff1a; 1.3 需要注意以下几点&#xff1a; 2. 关于 arraybuffer 和 blob 2.1 ArrayBuffer 和 blob 2.2 区别 2.3 相互转换 3. 主要参考&#xff1a; 1. axios 请求二进制…

python量化之路:获取历史某一时刻沪深上市公司股票代码及上市时间

python量化之路&#xff1a;获取历史某一时刻沪深上市公司股票代码及上市时间 最近开始玩股票量化&#xff0c;由于想要做完整的股票回测&#xff0c;因此股票的上市和退市信息就必不可少。因为我们回测的时候必须要知道某一日期沪深股票的成分包含哪些对吧。所以我们要把沪深全…

《网页设计创意书》读后感

刚刚收到《网页设计创意书》&#xff0c;确实有点惊喜&#xff0c;开始以为是像之前审读的书一样是一叠叠的打印纸&#xff0c;没想到是一本成品书&#xff0c;拿到手上沉甸甸的&#xff0c;随便翻看了一下&#xff0c;没想到里面竟然还是全彩页印刷的&#xff0c;本书的第一感…

游戏AI –行为树简介

游戏AI是一个非常广泛的主题&#xff0c;尽管有很多资料&#xff0c;但我找不到能以较慢&#xff0c;更容易理解的速度缓慢介绍这些概念的东西。 本文将尝试解释如何基于行为树的概念来设计一个非常简单但可扩展的AI系统。 什么是AI&#xff1f; 人工智能是参与游戏的实体表现…

liteos错误处理(十一)

1. 概述 1.1 基本概念 错误处理指用户代码发生错误时&#xff0c;系统调用错误处理模块的接口函数&#xff0c;完成上报错误信息&#xff0c;并调用用户自己的钩子函数&#xff0c;进行特定的处理。 错误处理模块实现OS内部错误码记录功能。OS内部错误码无法通过接口返回&#…

js 变量提升与函数提升

规则&#xff1a; 函数的提升优先于变量提升。同名的函数会覆盖同名的函数与变量。同名的变量不会覆盖同名的函数。 示例代码1&#xff1a; <!DOCTYPE html><html lang"zh"><head><meta charset"UTF-8" /><meta name"vi…

mockJs文档(一)

Mock.js 官网 目录 1. 开始安装 1.1 Node&#xff08;CommonJS&#xff09; 1.2 CMD方式 2. 语法规范 2.1 数据模板定义规范 DTD 2.1.1. 属性值是字符串 String 2.1.2. 属性值是数字 Number 2.1.3. 属性值是布尔型 Boolean 2.1.4. 属性值是对象 Object 2.1.5. 属性值…

小程序 获取手机号

【参考小程序开发文档&#xff1a;开发-指南-开放能力-用户信息-获取手机号】 地理位置 wx.getLocation(Object object) | 微信开放文档 手机号 获取手机号 | 微信开放文档 微信信息 小程序与小游戏获取用户信息接口调整&#xff0c;请开发者注意升级。 | 微信开放社区 目录…

CSS布局之脱离文档流详解——浮动、绝对定位脱离文档流的区别

1、代码 &#xff08;1&#xff09;示例代码1 <!DOCTYPE html><html lang"zh"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><meta http-e…

小程序 获取当前城市位置-高德地图

微信小程序 wx.getLocation 只能获取到经纬度&#xff0c;想要获取具体城市信息&#xff0c;需要使用地图插件。公司要求使用 高德地图&#xff0c;在使用上&#xff0c;几个地图的代码步骤都差不多。 目录 1. 查看官方文档 1.1 申请高德地图Key&#xff0c;点击查看申请key…

网页端调用企业微信扫一扫 详细过程

效果展示&#xff08;需要使用微信内置浏览器打开&#xff09;&#xff1a; 目录 1. 快速集成H5开发应用 1.1 开始 1.2 创建应用 1.2.1 登录管理后台 1.2.2 添加自建应用 1.2.3 配置应用 1.2.4 获取应用的 AgentID 与 Secret 1.3 配置应用 1.3.1 配置应用主页 1.3.2 配置…

获取ip地址

代码 ///<summary>///取得客户端真实IP。如果有代理则取第一个非内网地址 ///</summary>publicstringIPAddress { get{ stringresult String.Empty; result HttpContext.Current.Request.ServerVariables["HTTP_X_FORWAR…

微信小程序 监听位置信息

wx.onLocationChange(function callback) | 微信开放文档微信开发者平台文档https://developers.weixin.qq.com/miniprogram/dev/api/location/wx.onLocationChange.html 小程序 获取当前城市位置-高德地图_Start2019-CSDN博客小程序获取位置信息&#xff0c;包括省市区、用户…

通过构建Cocoapods私有库进行组件化开发探索

专题一 一、创建私有索引库 选Github或者码云都可以&#xff0c;本例以Github为例。创建私有索引库用来作为自己组件库的索引&#xff1a; 二、本地添加私有索引库 添加&#xff1a;pod repo add 索引库名称 索引库地址 例&#xff1a;pod repo add ZYHModule https://github.c…

layui 父页面弹框中获取子页面的内容

layer弹层组件开发文档 - Layuihttps://www.layui.site/doc/modules/layer.html#layer.getChildFrame 需求及代码分析 如上图&#xff0c;原来是点击一个按钮跳转到子页面&#xff0c;现在想改为&#xff1a;点击按钮&#xff0c;在当前页打开。因为不想要重写子页面的样式及内…

在JBoss Fuse / Fabric8 / Karaf中使用Byteman

您是否曾经尝试过了解一些非常简单的方法不起作用的过程&#xff1f; 您正在任何众所周知的上下文中编写代码&#xff0c;无论出于何种原因它都无法正常工作。 而且您信任您的平台&#xff0c;因此您认真阅读了所有日志。 而且&#xff0c;您仍然不知道为什么某些行为不符合预…

个人作业——Alpha项目测试

一、 这个作业属于哪个课程 https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass1/ 这个作业要求在哪里 https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass1/homework/3338 团队名称 西柚皇家编程团队&#xff1a;https://www.cnblogs.com/TakeRa…

Windows7下Docker的安装

转自 https://blog.csdn.net/xiangxiezhuren/article/details/79698913 无法打开图3&#xff0c;打开属性。给其添加git路径 无法使用图2下载 https://www.cnblogs.com/huang-yc/p/10350408.html 转载于:https://www.cnblogs.com/shufeiyang/p/11016177.html