easyexcel和poi版本冲突报错深入解析v2

easyexcel报错解决

问题

项目由poi改用easyexcel,报错如下: java.lang.NoSuchMethodError: ‘org.apache.poi.ss.usermodel.CellType
org.apache.poi.ss.usermodel.Cell.getCellType()’

原因

easyexcel中的poi和项目原本的poi版本冲突问题。 由于之前做过easyexcel项目,就把所以子工程pom里的poi注释掉了。
关键:忽略了parent项目pom的dependencyManagement中版本锁定的poi,这里误以为在子工程未使用就不会冲突。

解决

将项目所有有关poi的dependency全部注释掉,包括dependencies和dependencyManagement。
推荐:使用快捷键ctrl+shift+f直接搜索poi,找到直接注释

上述只是问题的解决方案,并没有系统的介绍为什么会报错。

1.问题

1、报的什么错?NoSuchMethodError 方法不存在错误
2、发生在编译期,还是运行时?
3、如果发生在运行时,为什么编译的时候没有识别出来这个方法不存在?

那么通过下面的解析,会清楚的理解上述问题。

2.模拟错误

由于easyexcel源码不方便修改,所以这里使用自己代码实现(代码无实际意义),主要演示报错。

2.1创建2个maven项目

easye模拟easyexcel,poi模拟poi。
在这里插入图片描述
自己项目调用了easyexcel的方法,而easyexcel又调用了poi方法。所以模拟,需要在poi创建一个getType方法。easye里创建testGet方法调用getType方法。

具体代码如下:
poi的pom:初始版本设置为1.0,版本后面会更改

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.zxh</groupId>
        <artifactId>test01</artifactId>
        <version>1.0</version>
    </parent>

    <groupId>cn.zxh</groupId>
    <artifactId>poi</artifactId>
    <version>1.0</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

CellImpl.java

package cn.zxh.poi;

public class CellImpl implements Cell {
    @Override
    public int getType() {
        return 1;
    }
}

Cell.java

package cn.zxh.poi;

public interface Cell {
    public int getType();
}

easye的pom:初始版本设置为1.0,引用poi1.0版本库

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.zxh</groupId>
        <artifactId>test01</artifactId>
        <version>1.0</version>
    </parent>
    <groupId>cn.zxh</groupId>
    <artifactId>easye</artifactId>
    <version>1.0</version>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>cn.zxh</groupId>
            <artifactId>poi</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>

</project>

MyGet.java

package cn.zxh.easye;

import cn.zxh.poi.Cell;
import cn.zxh.poi.CellImpl;
import java.util.Objects;

public class MyGet {
    public void testGet(){
        Cell cell = new CellImpl();
        //没有实际意义,主要是调用getType
        if(Objects.equals(cell.getType(),1)){
            System.out.println("pass");
        }
        System.out.println("fail");
    }
}

2.2安装到本地maven仓库

点击安装
在这里插入图片描述
然后找到自己的maven仓库内容如下
在这里插入图片描述

在这里插入图片描述

2.3在其他项目引入easye库

注:找个别的工程(不要还在这个工程),因为模拟引入easyexcel。自己工程肯定和easyexcel不在一个工程下。
在这里插入图片描述

2.4创建测试类并模拟调用

这里直接调用MyGet 的testGet。

package com.zxh.project.test1;

import cn.zxh.easye.MyGet;
import cn.zxh.poi.Cell;

public class MyTest {
    public static void main(String[] args) {
        MyGet myGet = new MyGet();
        myGet.testGet();
    }
}

这里先模拟版本一致正常情况,发现正常运行。
在这里插入图片描述

2.5降低poi的版本

找到之前自己的poi项目,更改getType,这里把返回类型换成String。
在这里插入图片描述
在这里插入图片描述

poi.pom里的版本改为0.5,然后只打包poi
在这里插入图片描述

在这里插入图片描述

2.6使用降低poi0.5版本

其他项目pom引入0.5版本
在这里插入图片描述
这里运行时会使用0.5,这就是常见的poi和easyexcel版本的冲突。
在这里插入图片描述

2.6错误模拟成功

果然不出所料,运行时报错了,这里打了断点,编译肯定通过的,确实为运行时报错。
在这里插入图片描述
在这里插入图片描述

2.7再再降低poi版本

重复上部分,降低到0.1,直接把poi中的getType的方法删掉(方便理解),再打包,然后引入改为0.1

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
发现依然编译通过,运行时报错。

3.原因分析

那么有疑问,既然用的是低版本poi0.1库,这个方法都不存在,为什么还编译通过了呢。那么再做个实验。

首先将easye1.0 和MyTest复制到另一个普通java项目。

在这里插入图片描述
在这里插入图片描述
然后添加类库
在这里插入图片描述

然后这里也是运行时报错,只是错误变了,类不存在。因为压根就没有引入poi的库,只引入了easye,poi库中的类肯定不存在
在这里插入图片描述
然后这里引入的easye库(包括maven引入的),都是已经编译好的.class文件
在这里插入图片描述

4.总结

那么我们就可以大胆的猜测了(为什么时猜测,我也不知道对不对,欢迎大家讨论)
编译阶段,仅仅对直接引入的库中的方法进行检测是否存在,例如这里只判断easye库的MyGet.testGet,而easye库如果引用了其他库的方法,例如poi中的方法,由于已经编译成了MyGet.class,不再进行MyGet.class重新编译,所以深层的方法不在编译器发现(因为编译MyTest.class,只需要知道MyGet.testGet即可)。

JVM运行时,会根据方法的签名进行调用,如果方法的签名不在,报错。
下面为MyGet.testGet的class源码,
其中invokeinterface #4 <cn/zxh/poi/Cell.getType : ()I> count 1
这里就是获取cn/zxh/poi/Cell.getType : ()I 这种签名的方法。如果没有报错。

2.6错误模拟成功

这里报错是getType已经改成了String类型,I标识int,签名不一致找不到。

2.7再再降低poi版本

这里报错更简单,直接方法都删掉了,签名肯定找不到。

3.原因分析

这个里面的报错,是根据下面的源码
0 new #2 <cn/zxh/poi/CellImpl>
根据类路径找不到类,库都没有引入,所以报错。

 0 new #2 <cn/zxh/poi/CellImpl>
 3 dup
 4 invokespecial #3 <cn/zxh/poi/CellImpl.<init> : ()V>
 7 astore_1
 8 aload_1
 9 invokeinterface #4 <cn/zxh/poi/Cell.getType : ()I> count 1
14 invokestatic #5 <java/lang/Integer.valueOf : (I)Ljava/lang/Integer;>
17 iconst_1
18 invokestatic #5 <java/lang/Integer.valueOf : (I)Ljava/lang/Integer;>
21 invokestatic #6 <java/util/Objects.equals : (Ljava/lang/Object;Ljava/lang/Object;)Z>
24 ifeq 35 (+11)
27 getstatic #7 <java/lang/System.out : Ljava/io/PrintStream;>
30 ldc #8 <pass>
32 invokevirtual #9 <java/io/PrintStream.println : (Ljava/lang/String;)V>
35 getstatic #7 <java/lang/System.out : Ljava/io/PrintStream;>
38 ldc #10 <fail>
40 invokevirtual #9 <java/io/PrintStream.println : (Ljava/lang/String;)V>
43 return

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

npm install 安装不成功,node-sass缺失,提示python环境缺失的解决办法

npm install 安装不成功的原因 是因为缺少python的环境 解决方法&#xff1a; 1、去官网下载 https://www.python.org/downloads/release&#xff0c;注意安装3.6版本以上还是会有问题&#xff0c;建议安装3.6版本以上的&#xff0c;我选择安装的是3.9.6&#xff0c;对应的下载…

操作系统 大作业

1、现有成绩文件按“姓名 学校 年级 班级 分数”五列组成&#xff0c;编写Shell脚本&#xff0c;将某目录下所有成绩文件&#xff08;≥3个&#xff09;合并为一个&#xff0c;形成“姓名 班级 分数”三列&#xff0c;并按成绩排序&#xff0c;输出年级排名前十。同时输出60以下…

移植案例与原理 - HDF驱动框架-驱动配置(1)

HCS(HDF Configuration Source)是HDF驱动框架的配置描述源码&#xff0c;内容以Key-Value为主要形式。它实现了配置代码与驱动代码解耦&#xff0c;便于开发者进行配置管理。应该&#xff0c;类似Linux DTS(Device Tree Source)设备树。 HC-GEN(HDF Configuration Generator)是…

质检迈入新时代,天润融通推出基于大模型的质检3.0解决方案

近18个月以来&#xff0c;受益于生成式AI浪潮&#xff0c;千行百业迎来了前所未有的突破与变革。 今天我们荣幸地站在时代交汇点上&#xff0c;宣布天润融通正式推出基于大语言模型的质检3.0产品&#xff0c;文末扫码申请试用。 在揭示质检3.0的里程碑之前&#xff0c;让我们…

网工内推 | 中国电信、香港宽频系统工程师,CCIE认证优先,最高年薪25w

01 中国电信股份有限公司浙江分公司 &#x1f537;招聘岗位&#xff1a;系统架构师 &#x1f537;岗位职责&#xff1a; 1、做好客户网络和信息安全产品的解决方案支撑、交付及后续运营维护&#xff0c;做好相关产数项目的支撑。 2、根据信息安全管理要求&#xff0c;负责客户…

MPLS静态配置实验(初学版)

实验拓扑 配置接口地址 配置OSPF协议 测试网络连通性 配置静态MPLS AR1&#xff1a; [R1]mpls lsr-id 1.1.1.1 [R1]mpls [R1-GigabitEthernet0/0/0]mpls [R1]static-lsp ingress wps destination 4.4.4.4 32 nexthop 10.1.12.2 outgoing-interface g0/0/0 out-label 100AR2 [R2…

韩顺平0基础学java——第26天

p523-547 HashSet扩容时&#xff0c;只要节点到达了阈值就会扩&#xff0c;而不是数组长度到了才扩。 比如长16的数组&#xff0c;索引1放了8个&#xff0c;索引3放了4个&#xff0c;我再加一个他就会扩容。 另外谁能告诉我老师的debug界面是怎么设置的吗忘光了 HashSet存放…

shell脚本之数组及冒泡排序

1.数组定义&#xff1a;在集合当中指定多个元素&#xff0c;元素的类型可以是整数、字符串及浮点。 2.数组作用&#xff1a;一次性的定义多个元素&#xff0c;可以为变量赋值提供便利。 3.数组的定义方法&#xff1a; 数组名&#xff08;a b c d&#xff09; 数组名不能重复…

Qt6视频播放器项目框架代码

视频播放的关键代码如下: 使用Qt6的QMediaPlayer,QVideoWidget实现 void FunnyWidget::initVideo() {player = new QMediaPlayer(this);videoWidget = new QVideoWidget(this);playButton = new QPushButton("Play", this);pauseButton = new QPushButton("…

【Ruby基础01】windows和termux中搭建Ruby开发环境

windows下环境搭建 railsinstaller官方git地址 按照文档安装git、nodejs、yarn&#xff0c;安装教程百度一下。railsinstall可以从release页面下载最新版本4.1.0。 安装完成如下 安装RubyMine 下载RubyMine RubyMine下载地址 安装激活 下载文件&#xff0c;按照里面的流程…

《算法设计与分析》第五六章:回溯法与分支限界法

文章目录 回溯法分支限界法一、本章作业1.活动安排问题2.旅行商问题3.单源最短路径4.任务分配问题 二、算法积累1.回溯法求解01背包问题2.回溯法求解最大团问题3.回溯法求解n皇后问题4.回溯法求解地图着色5.回溯法求解哈密尔顿图6.回溯法求活动安排7.分支限界法求01背包问题8.分…

手写MyBatis 重要基本原理框架

1. 手写MyBatis 重要基本原理框架 文章目录 1. 手写MyBatis 重要基本原理框架1.1 第一步&#xff1a;IDEA中创建模块1.2 第二步&#xff1a;资源工具类&#xff0c;方便获取指向配置文件的输入流1.3 第三步&#xff1a;定义SqlSessionFactoryBuilder类1.4 第四步&#xff1a;分…

再进一步!deepin V23成功适配SpacemiT MUSE™ Box

内容来源&#xff1a;deepin&#xff08;深度&#xff09;社区 deepin作为国内领先的Linux操作系统发行版&#xff0c;一直致力于为用户提供更广泛的硬件支持&#xff0c;并积极投身于蓬勃发展的RISC-V生态建设。自deepin-ports SIG&#xff08;特别兴趣小组&#xff09;成立以…

WSL2 无法将磁盘”C:\Program Files\WSL\system.vhd“ 附加到WSL2 系统找不到指定的文件

WSL2 无法将磁盘”C:\Program Files\WSL\system.vhd“ 附加到WSL2 系统找不到指定的文件 开局就是雷蹦开局就是雷蹦 早上上班,一开机直接崩溃了,这啥问题,这个文件我哪里敢删除不是。肯定不是我的问题,我不看。心里默默告诉自己,一切都是状态机。确定了一下,首先确实存在…

类注释规范

类注释规范 1.1.1 模板配置 模板路径&#xff1a;File–>settings–>Editor–>File and Code Templates–>Includes–>File Header  N A M E &#xff1a;设置类名&#xff0c;与下面的 {NAME}&#xff1a;设置类名&#xff0c;与下面的 NAME&#xff1a;设…

gitee添加别人的仓库后,在该仓库里添加文件夹/文件

一、在指定分支里添加文件夹&#xff08;如果库主没有创建分支&#xff0c;自己还要先创建分支&#xff09; eg:以在一个项目里添加视图文件为例&#xff0c;用Echarts分支在usr/views目录下添加Echarts文件夹&#xff0c;usr/views/Echarts目录下添加index.vue 1.切换为本地仓…

C++之STL(二三)

1、vector源码刨析 1.1、数据结构以及动态扩充算法 其实vector内部有三个指针&#xff0c;分别是数据的第一个元素Myfirst、数据的最后一个元素的下一个位置Mylast&#xff0c;最后一个空间的下一个位置Myend&#xff1b;当你插入数据的时候&#xff0c;先判断当前容量够不够&…

浅谈RC4

一、什么叫RC4&#xff1f;优点和缺点 RC4是对称密码&#xff08;加密解密使用同一个密钥&#xff09;算法中的流密码&#xff08;一个字节一个字节的进行加密&#xff09;加密算法。 优点&#xff1a;简单、灵活、作用范围广&#xff0c;速度快 缺点&#xff1a;安全性能较差&…

昇思大模型学习·第一天

mindspore快速入门回顾 导入mindspore包 处理数据集 下载mnist数据集进行数据集预处理 MnistDataset()方法train_dataset.get_col_names() 打印列名信息使用create_tuple_iterator 或create_dict_iterator对数据集进行迭代访问 网络构建 mindspore.nn: 构建所有网络的基类用…