java反射异常报错解决:java.lang.NoSuchFieldException

我这里是学习测试开发时报错,关联:运行代码中调用另一个代码文件的私有属性并且这个私有属性还需与本地excel文件中的title一致!

报错信息如下图:

69行代码:

103行代码:

 Caseinfo私有属性代码:

excel下标0行的列头:

总结:最终通过反复查看java.lang.NoSuchFieldException源代码的注解信息得到以下:

1.程序未找到相应的Field(解析比如:excel列名和CaseInfo属性,大小写都需对应上);

2.有该Field,但是该Field是使用private修饰的,而在获取该Field的时候,需要使用getDeclaredField这个方法。

3.死死往这两个方面去找原因吧。

问题解决:我main方法输出的caseInfo.getId() 和caseInfo.getIsDbCheck()与excel中列头不一致导致报错没有找到FieId。详情见总结-序号1;

最后祝愿大家在IT行业一路长虹。

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
packer-ng-plugin 是下一代Android渠道打包工具Gradle插件,支持极速打包,1000个渠道包只需要5秒钟,速度是 gradle-packer-plugin 的1000倍以上,可方便的用于CI系统集成,支持自定义输出目录和最终APK文件名,依赖包: com.mcxiaoke.gradle:packer-ng:1.0. 简短名:packer,可以在项目的 build.gradle 中指定使用,还提供了命令行独立使用的Java和Python脚本。实现原理PackerNg原理优点使用APK注释字段保存渠道信息和MAGIC字节,从文件末尾读取渠道信息,速度快实现为一个Gradle Plugin,支持定制输出APK的文件名等信息,方便CI集成提供Java版和Python的独立命令行脚本,不依赖Gradle插件,支持独立使用由于打包速度极快,单个包只需要5毫秒左右,可用于网站后台动态生成渠道包缺点没有使用Android的productFlavors,无法利用flavors条件编译的功能文件格式Android应用使用的APK文件就是一个带签名信息的ZIP文件,根据 ZIP文件格式规范,每个ZIP文件的最后都必须有一个叫 Central Directory Record 的部分,这个CDR的最后部分叫"end of central directory record",这一部分包含一些元数据,它的末尾是ZIP文件的注释。注释包含Comment Length和File Comment两个字段,前者表示注释内容的长度,后者是注释的内容,正确修改这一部分不会对ZIP文件造成破坏,利用这个字段,我们可以添加一些自定义的数据,PackerNg项目就是在这里添加和读取渠道信息。细节处理原理很简单,就是将渠道信息存放在APK文件的注释字段中,但是实现起来遇到不少坑,测试了好多次。ZipOutputStream.setCommentFileOutputStream is = new FileOutputStream("demo.apk", true);ZipOutputStream zos = new ZipOutputStream(is); zos.setComment("Google_Market"); zos.finish(); zos.close();ZipFile zipFile=new ZipFile("demo.apk");System.out.println(zipFile.getComment());使用Java写入APK文件注释虽然可以正常读取,但是安装的时候会失败,错误信息是:adb install -r demo.apk Failure [INSTALL_FAILED_INVALID_APK]原因未知,可能Java的Zip实现写入了某些特殊字符导致APK文件校验失败,于是只能放弃这个方法。同样的功能使用Python测试完全没有问题,处理后的APK可以正常安装。ZipFile.getComment上面是ZIP文件注释写入,使用Java会导致APK文件被破坏,无法安装。这里是读取ZIP文件注释的问题,Java 7里可以使用 zipFile.getComment() 方法直接读取注释,非常方便。但是Android系统直到API 19,也就是4.4以上的版本才支持 ZipFile.getComment() 方法。由于要兼容之前的版本,所以这个方法也不能使用。解决方法由于使用Java直接写入和读取ZIP文件的注释都不可行,使用Python又不方便与Gradle系统集成,所以只能自己实现注释的写入和读取。 实现起来也不复杂,就是为了提高性能,避免读取整个文件,需要在注释的最后加入几个MAGIC字节,这样从文件的最后开始,读取很少的几个字节就可以定位 渠道名的位置。几个常量定义:// ZIP文件的注释最长65535个字节 static final int ZIP_COMMENT_MAX_LENGTH = 65535; // ZIP文件注释长度字段的字节数 static final int SHORT_LENGTH = 2; // 文件最后用于定位的MAGIC字节 static final byte[] MAGIC = new byte[]{0x21, 0x5a, 0x58, 0x4b, 0x21}; //!ZXK!读写注释Java版详细的实现见 PackerNg.java,Python版的实现见 ngpacker.py 。写入ZIP文件注释:public static void writeZipComment(File file, String comment)  throws IOException {     byte[] data = comment.getBytes(UTF_8);     final RandomAccessFile raf = new RandomAccessFile(file, "rw");     raf.seek(file.length() - SHORT_LENGTH);     // write zip comment length     // (content field length   length field length   magic field length)     writeShort(data.length   SHORT_LENGTH   MAGIC.length, raf);     // write content     writeBytes(data, raf);     // write content length     writeShort(data.length, raf);     // write magic bytes     writeBytes(MAGIC, raf);     raf.close(); }读取ZIP文件注释,有两个版本的实现,这里使用的是 RandomAccessFile ,另一个版本使用的是 MappedByteBuffer ,经过测试,对于特别长的注释,使用内存映射文件读取性能要稍微好一些,对于特别短的注释(比如渠道名),这个版本反而更快一些。public static String readZipComment(File file) throws IOException {     RandomAccessFile raf = null;     try {         raf = new RandomAccessFile(file, "r");         long index = raf.length();         byte[] buffer = new byte[MAGIC.length];         index -= MAGIC.length;         // read magic bytes         raf.seek(index);         raf.readFully(buffer);         // if magic bytes matched         if (isMagicMatched(buffer)) {             index -= SHORT_LENGTH;             raf.seek(index);             // read content length field             int length = readShort(raf);             if (length > 0) {                 index -= length;                 raf.seek(index);                 // read content bytes                 byte[] bytesComment = new byte[length];                 raf.readFully(bytesComment);                 return new String(bytesComment, UTF_8);             }         }     } finally {         if (raf != null) {             raf.close();         }     }     return null; }读取APK文件,由于这个库 packer-helper 需要同时给Gradle插件和Android项目使用,所以不能添加Android相关的依赖,但是又需要读取自身APK文件的路径,使用反射实现:// for android code private static String getSourceDir(final Object context)         throws ClassNotFoundException,         InvocationTargetException,         IllegalAccessException,         NoSuchFieldException,         NoSuchMethodException {     final Class<?> contextClass = Class.forName("android.content.Context");     final Class<?> applicationInfoClass = Class.forName("android.content.pm.ApplicationInfo");     final Method getApplicationInfoMethod = contextClass.getMethod("getApplicationInfo");     final Object appInfo = getApplicationInfoMethod.invoke(context);     final Field sourceDirField = applicationInfoClass.getField("sourceDir");     return (String) sourceDirField.get(appInfo); }Gradle Plugin这个和旧版插件基本一致,首先是读取渠道列表文件,保存起来,打包的时候遍历列表,复制生成的APK文件到临时文件,给临时文件写入渠道信息,然后复制到输出目录,文件名可以使用模板定制。主要代码如下:// 添加打包用的TASK def archiveTask = project.task("apk${variant.name.capitalize()}",                 type: ArchiveAllApkTask) {             theVariant = variant             theExtension = modifierExtension             theMarkets = markets             dependsOn variant.assemble         }         def buildTypeName = variant.buildType.name         if (variant.name != buildTypeName) {             project.task("apk${buildTypeName.capitalize()}", dependsOn: archiveTask)         } // 遍历列表修改APK文件 theMarkets.each { String market ->             String apkName = buildApkName(theVariant, market)             File tempFile = new File(tempDir, apkName)             File finalFile = new File(outputDir, apkName)             tempFile << originalFile.bytes             copyTo(originalFile, tempFile)             PackerNg.Helper.writeMarket(tempFile, market)             if (PackerNg.Helper.verifyMarket(tempFile, market)) {                 copyTo(tempFile, finalFile)             }          }详细的实现可以查看文件 PackerNgPlugin.groovy 和文件 ArchiveAllApkTask.groovy 标签:packer
MyBatis 目录(?)[-] mybatis实战教程mybatis in action之一开发环境搭建 mybatis实战教程mybatis in action之二以接口的方式编程 mybatis实战教程mybatis in action之三实现数据的增删改查 mybatis实战教程mybatis in action之四实现关联数据的查询 mybatis实战教程mybatis in action之五与spring3集成附源码 mybatis实战教程mybatis in action之六与Spring MVC 的集成 mybatis实战教程mybatis in action之七实现mybatis分页源码下载 mybatis实战教程mybatis in action之八mybatis 动态sql语句 mybatis实战教程mybatis in action之九mybatis 代码生成工具的使用 mybatis SqlSessionDaoSupport的使用附代码下载 转自:http://www.yihaomen.com/article/java/302.htm (读者注:其实这个应该叫做很基础的入门一下下,如果你看过Hibernate了那这个就非常的简单) (再加一条,其实大家可以看官方的教程更好些:http://mybatis.github.io/mybatis-3/,而且如果英文不是很好的那就看中文的:http://mybatis.github.io/mybatis-3/zh/sqlmap-xml.html) 写在这个系列前面的话: 以前曾经用过ibatis,这是mybatis的前身,当时在做项目时,感觉很不错,比hibernate灵活。性能也比hibernate好。而且也比较轻量级,因为当时在项目中,没来的及做很很多笔记。后来项目结束了,我也没写总结文档。已经过去好久了。但最近突然又对这个ORM 工具感兴趣。因为接下来自己的项目中很有可能采用这个ORM工具。所以在此重新温习了一下 mybatis, 因此就有了这个系列的 mybatis 教程. 什么是mybatis MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis使用简单的XML或注解用于配置和原始映射,将接口和Java的POJOs(Plan Old Java Objects,普通的Java对象)映射成数据库中的记录. orm工具的基本思想 无论是用过的hibernate,mybatis,你都可以法相他们有一个共同点: 1. 从配置文件(通常是XML配置文件中)得到 sessionfactory. 2. 由sessionfactory 产生 session 3. 在session 中完成对数据的增删改查和事务提交等. 4. 在用完之后关闭session 。 5. 在java 对象和 数据库之间有做mapping 的配置文件,也通常是xml 文件。 mybatis实战教程(mybatis in action)之一:开发环境搭建 mybatis 的开发环境搭建,选择: eclipse j2ee 版本,mysql 5.1 ,jdk 1.7,mybatis3.2.0.jar包。这些软件工具均可以到各自的官方网站上下载。 首先建立一个名字为 MyBaits 的 dynamic web project 1. 现阶段,你可以直接建立java 工程,但一般都是开发web项目,这个系列教程最后也是web的,所以一开始就建立web工程。 2. 将 mybatis-3.2.0-SNAPSHOT.jar,mysql-connector-java-5.1.22-bin.jar 拷贝到 web工程的lib目录. 3. 创建mysql 测试数据库和用户表,注意,这里采用的是 utf-8 编码 创建用户表,并插入一条测试数据 程序代码 程序代码 Create TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userName` varchar(50) DEFAULT NULL, `userAge` int(11) DEFAULT NULL, `userAddress` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; Insert INTO `user` VALUES ('1', 'summer', '100', 'shanghai,pudong'

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Myself-testdev

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值