groovy 中使用easyexcel
问题:在groovy中使用easyexcel读取文件时,出现如下报错:
com.alibaba.excel.exception.ExcelDataConvertException: Converter not found, convert NUMBER to org.codehaus.groovy.reflection.ClassInfo
at com.alibaba.excel.util.ConverterUtils.doConvertToJavaObject(ConverterUtils.java:177)
at com.alibaba.excel.util.ConverterUtils.convertToJavaObject(ConverterUtils.java:121)
at com.alibaba.excel.util.ConverterUtils.convertToJavaObject(ConverterUtils.java:87)
at com.alibaba.excel.read.listener.ModelBuildEventListener.buildUserModel(ModelBuildEventListener.java:145)
at com.alibaba.excel.read.listener.ModelBuildEventListener.invoke(ModelBuildEventListener.java:37)
at com.alibaba.excel.read.listener.ModelBuildEventListener.invoke(ModelBuildEventListener.java:30)
at com.alibaba.excel.read.processor.DefaultAnalysisEventProcessor.dealData(DefaultAnalysisEventProcessor.java:109)
at com.alibaba.excel.read.processor.DefaultAnalysisEventProcessor.endRow(DefaultAnalysisEventProcessor.java:50)
at com.alibaba.excel.analysis.v07.handlers.RowTagHandler.endElement(RowTagHandler.java:66)
at com.alibaba.excel.analysis.v07.handlers.sax.XlsxRowHandler.endElement(XlsxRowHandler.java:99)
at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:610)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1718)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2883)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:605)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:534)
at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:888)
at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:824)
at java.xml/com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1216)
at java.xml/com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:635)
at com.alibaba.excel.analysis.v07.XlsxSaxAnalyser.parseXmlSource(XlsxSaxAnalyser.java:239)
at com.alibaba.excel.analysis.v07.XlsxSaxAnalyser.execute(XlsxSaxAnalyser.java:261)
at com.alibaba.excel.analysis.ExcelAnalyserImpl.analysis(ExcelAnalyserImpl.java:124)
at com.alibaba.excel.ExcelReader.read(ExcelReader.java:66)
at com.alibaba.excel.ExcelReader.read(ExcelReader.java:56)
at com.alibaba.excel.read.builder.ExcelReaderSheetBuilder.doRead(ExcelReaderSheetBuilder.java:65)
at com.alibaba.excel.read.builder.ExcelReaderSheetBuilder$doRead.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:119)
at com.groovy.MyTest.MyTest.MyTest01(MyTest.groovy:25)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:686)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:212)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:208)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:137)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:71)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$5(DefaultLauncher.java:211)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:132)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
Process finished with exit code -1
问题分析
easyexcel版本:4.0.3 读取文件的代码如下
void MyTest01() {
AnalysisEventListener listener = new AnalysisEventListener<Person>() {
@Override
void invoke(Person data, AnalysisContext context) {
println data.name
}
@Override
void doAfterAllAnalysed(AnalysisContext context) {
println "read done"
}
}
EasyExcel.read(new ByteArrayInputStream(new File("E:\\Learn\\ProgramDesign\\Java\\idea\\jdk11-gradle-groovy\\src\\test\\groovy\\com\\groovy\\MyTest\\test.xlsx").bytes), Person, listener)
.sheet(0) // 默认读取第一个 sheet
.doRead() // 开始读取
}
import com.alibaba.excel.annotation.ExcelProperty
class Person {
@ExcelProperty(value = "Name")
String name
}
下面时excel文件内容:
但是如果将Person按照下面两种方式写,却不会报错,能够正确读取文件:
import com.alibaba.excel.annotation.ExcelProperty
class Person {
@ExcelProperty(value = "Name")
String name
@ExcelProperty(value = "Age")
String age
}
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated
import com.alibaba.excel.annotation.ExcelProperty
@ExcelIgnoreUnannotated()
class Person {
@ExcelProperty(value = "Name")
String name
}
经过调试发现,easyexcel读取文件后,会将excel文件中的字段映射到Person字段中,但是Person出现除了name字段以外的字段,导致将文件字段内容映射到Person类是出现了类型转换的错误。
根据调试分析,源代码通过反射获取Person类属性,一共会得到name, $staticClassInfo, $callSiteArray, $staticClassInfo$, metaClass, __$stMC 。
但是明明Person类中只定义了一个name属性,为什么会得到这么多属性?通过分析Person字节码文件,可以发现Person类被编译字节码文件后会自动添加一些字段, 下面是Person的字节码文件内容:
// class version 55.0 (55)
// access flags 0x21
public class com/groovy/MyTest/Person implements groovy/lang/GroovyObject {
// compiled from: Person.groovy
// access flags 0x2
private Ljava/lang/String; name
@Lcom/alibaba/excel/annotation/ExcelProperty;(value={"Name"})
// access flags 0x100A
private static synthetic Lorg/codehaus/groovy/reflection/ClassInfo; $staticClassInfo
// access flags 0x1089
public static transient synthetic Z __$stMC
// access flags 0x1082
private transient synthetic Lgroovy/lang/MetaClass; metaClass
// access flags 0x100A
private static synthetic Lorg/codehaus/groovy/reflection/ClassInfo; $staticClassInfo$
// access flags 0x100A
private static synthetic Ljava/lang/ref/SoftReference; $callSiteArray
// access flags 0x1
public <init>()V
@Lgroovy/transform/Generated;()
L0
INVOKESTATIC com/groovy/MyTest/Person.$getCallSiteArray ()[Lorg/codehaus/groovy/runtime/callsite/CallSite;
ASTORE 1
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
ALOAD 0
INVOKEVIRTUAL com/groovy/MyTest/Person.$getStaticMetaClass ()Lgroovy/lang/MetaClass;
ASTORE 2
ALOAD 2
ALOAD 0
SWAP
PUTFIELD com/groovy/MyTest/Person.metaClass : Lgroovy/lang/MetaClass;
ALOAD 2
POP
L1
RETURN
LOCALVARIABLE this Lcom/groovy/MyTest/Person; L0 L1 0
MAXSTACK = 2
MAXLOCALS = 3
// access flags 0x1004
protected synthetic $getStaticMetaClass()Lgroovy/lang/MetaClass;
ALOAD 0
INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class;
LDC Lcom/groovy/MyTest/Person;.class
IF_ACMPEQ L0
ALOAD 0
INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.initMetaClass (Ljava/lang/Object;)Lgroovy/lang/MetaClass;
ARETURN
L0
FRAME SAME
GETSTATIC com/groovy/MyTest/Person.$staticClassInfo : Lorg/codehaus/groovy/reflection/ClassInfo;
ASTORE 1
ALOAD 1
IFNONNULL L1
ALOAD 0
INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class;
INVOKESTATIC org/codehaus/groovy/reflection/ClassInfo.getClassInfo (Ljava/lang/Class;)Lorg/codehaus/groovy/reflection/ClassInfo;
DUP
ASTORE 1
PUTSTATIC com/groovy/MyTest/Person.$staticClassInfo : Lorg/codehaus/groovy/reflection/ClassInfo;
L1
FRAME APPEND [org/codehaus/groovy/reflection/ClassInfo]
ALOAD 1
INVOKEVIRTUAL org/codehaus/groovy/reflection/ClassInfo.getMetaClass ()Lgroovy/lang/MetaClass;
ARETURN
MAXSTACK = 2
MAXLOCALS = 2
// access flags 0x1001
public synthetic getMetaClass()Lgroovy/lang/MetaClass;
@Lgroovy/transform/Generated;()
@Lgroovy/transform/Internal;()
ALOAD 0
GETFIELD com/groovy/MyTest/Person.metaClass : Lgroovy/lang/MetaClass;
DUP
IFNULL L0
ARETURN
L0
FRAME SAME1 groovy/lang/MetaClass
POP
ALOAD 0
DUP
INVOKEVIRTUAL com/groovy/MyTest/Person.$getStaticMetaClass ()Lgroovy/lang/MetaClass;
PUTFIELD com/groovy/MyTest/Person.metaClass : Lgroovy/lang/MetaClass;
ALOAD 0
GETFIELD com/groovy/MyTest/Person.metaClass : Lgroovy/lang/MetaClass;
ARETURN
MAXSTACK = 2
MAXLOCALS = 1
// access flags 0x1001
public synthetic setMetaClass(Lgroovy/lang/MetaClass;)V
@Lgroovy/transform/Generated;()
@Lgroovy/transform/Internal;()
ALOAD 0
ALOAD 1
PUTFIELD com/groovy/MyTest/Person.metaClass : Lgroovy/lang/MetaClass;
RETURN
MAXSTACK = 2
MAXLOCALS = 2
// access flags 0x1001
public synthetic invokeMethod(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
@Lgroovy/transform/Generated;()
@Lgroovy/transform/Internal;()
ALOAD 0
INVOKEVIRTUAL com/groovy/MyTest/Person.getMetaClass ()Lgroovy/lang/MetaClass;
ALOAD 0
ALOAD 1
ALOAD 2
INVOKEINTERFACE groovy/lang/MetaClass.invokeMethod (Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; (itf)
ARETURN
MAXSTACK = 4
MAXLOCALS = 3
// access flags 0x1001
public synthetic getProperty(Ljava/lang/String;)Ljava/lang/Object;
@Lgroovy/transform/Generated;()
@Lgroovy/transform/Internal;()
ALOAD 0
INVOKEVIRTUAL com/groovy/MyTest/Person.getMetaClass ()Lgroovy/lang/MetaClass;
ALOAD 0
ALOAD 1
INVOKEINTERFACE groovy/lang/MetaClass.getProperty (Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object; (itf)
ARETURN
MAXSTACK = 3
MAXLOCALS = 2
// access flags 0x1001
public synthetic setProperty(Ljava/lang/String;Ljava/lang/Object;)V
@Lgroovy/transform/Generated;()
@Lgroovy/transform/Internal;()
ALOAD 0
INVOKEVIRTUAL com/groovy/MyTest/Person.getMetaClass ()Lgroovy/lang/MetaClass;
ALOAD 0
ALOAD 1
ALOAD 2
INVOKEINTERFACE groovy/lang/MetaClass.setProperty (Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V (itf)
RETURN
MAXSTACK = 4
MAXLOCALS = 3
// access flags 0x1
public getName()Ljava/lang/String;
@Lgroovy/transform/Generated;()
ALOAD 0
GETFIELD com/groovy/MyTest/Person.name : Ljava/lang/String;
ARETURN
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1
public setName(Ljava/lang/String;)V
@Lgroovy/transform/Generated;()
ALOAD 0
ALOAD 1
PUTFIELD com/groovy/MyTest/Person.name : Ljava/lang/String;
RETURN
MAXSTACK = 2
MAXLOCALS = 2
// access flags 0x100A
private static synthetic $createCallSiteArray()Lorg/codehaus/groovy/runtime/callsite/CallSiteArray;
LDC 0
ANEWARRAY java/lang/String
ASTORE 0
NEW org/codehaus/groovy/runtime/callsite/CallSiteArray
DUP
LDC Lcom/groovy/MyTest/Person;.class
ALOAD 0
INVOKESPECIAL org/codehaus/groovy/runtime/callsite/CallSiteArray.<init> (Ljava/lang/Class;[Ljava/lang/String;)V
ARETURN
MAXSTACK = 4
MAXLOCALS = 1
// access flags 0x100A
private static synthetic $getCallSiteArray()[Lorg/codehaus/groovy/runtime/callsite/CallSite;
GETSTATIC com/groovy/MyTest/Person.$callSiteArray : Ljava/lang/ref/SoftReference;
IFNULL L0
GETSTATIC com/groovy/MyTest/Person.$callSiteArray : Ljava/lang/ref/SoftReference;
INVOKEVIRTUAL java/lang/ref/SoftReference.get ()Ljava/lang/Object;
CHECKCAST org/codehaus/groovy/runtime/callsite/CallSiteArray
DUP
ASTORE 0
IFNONNULL L1
L0
FRAME SAME
INVOKESTATIC com/groovy/MyTest/Person.$createCallSiteArray ()Lorg/codehaus/groovy/runtime/callsite/CallSiteArray;
ASTORE 0
NEW java/lang/ref/SoftReference
DUP
ALOAD 0
INVOKESPECIAL java/lang/ref/SoftReference.<init> (Ljava/lang/Object;)V
PUTSTATIC com/groovy/MyTest/Person.$callSiteArray : Ljava/lang/ref/SoftReference;
L1
FRAME APPEND [org/codehaus/groovy/runtime/callsite/CallSiteArray]
ALOAD 0
GETFIELD org/codehaus/groovy/runtime/callsite/CallSiteArray.array : [Lorg/codehaus/groovy/runtime/callsite/CallSite;
ARETURN
MAXSTACK = 3
MAXLOCALS = 1
}
确实存在:
private static synthetic Lorg/codehaus/groovy/reflection/ClassInfo; $staticClassInfo
public static transient synthetic Z __$stMC
private transient synthetic Lgroovy/lang/MetaClass; metaClass
private static synthetic Lorg/codehaus/groovy/reflection/ClassInfo; $staticClassInfo$
private static synthetic Ljava/lang/ref/SoftReference; $callSiteArray
继续调试源码,发现下面这个方法会筛选掉一些字段:
private static FieldCache declaredFields(Class<?> clazz) {
if (clazz == null) {
return null;
}
return FIELD_CACHE.computeIfAbsent(clazz, key -> {
List<Field> tempFieldList = new ArrayList<>();
Class<?> tempClass = clazz;
// When the parent class is null, it indicates that the parent class (Object class) has reached the top
// level.
while (tempClass != null) {
Collections.addAll(tempFieldList, tempClass.getDeclaredFields());
// Get the parent class and give it to yourself
tempClass = tempClass.getSuperclass();
}
// Screening of field
Map<Integer, List<Field>> orderFieldMap = new TreeMap<Integer, List<Field>>();
Map<Integer, Field> indexFieldMap = new TreeMap<Integer, Field>();
Map<String, Field> ignoreMap = new HashMap<String, Field>(16);
ExcelIgnoreUnannotated excelIgnoreUnannotated = clazz.getAnnotation(ExcelIgnoreUnannotated.class);
for (Field field : tempFieldList) {
declaredOneField(field, orderFieldMap, indexFieldMap, ignoreMap, excelIgnoreUnannotated);
}
return new FieldCache(buildSortedAllFieldMap(orderFieldMap, indexFieldMap), indexFieldMap, ignoreMap);
});
}
private static void declaredOneField(Field field, Map<Integer, List<Field>> orderFieldMap,
Map<Integer, Field> indexFieldMap, Map<String, Field> ignoreMap,
ExcelIgnoreUnannotated excelIgnoreUnannotated) {
ExcelIgnore excelIgnore = field.getAnnotation(ExcelIgnore.class);
if (excelIgnore != null) {
ignoreMap.put(field.getName(), field);
return;
}
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
boolean noExcelProperty = excelProperty == null && excelIgnoreUnannotated != null;
if (noExcelProperty) {
ignoreMap.put(field.getName(), field);
return;
}
boolean isStaticFinalOrTransient =
(Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()))
|| Modifier.isTransient(field.getModifiers());
if (excelProperty == null && isStaticFinalOrTransient) {
ignoreMap.put(field.getName(), field);
return;
}
if (excelProperty != null && excelProperty.index() >= 0) {
if (indexFieldMap.containsKey(excelProperty.index())) {
throw new ExcelCommonException("The index of '" + indexFieldMap.get(excelProperty.index()).getName()
+ "' and '" + field.getName() + "' must be inconsistent");
}
indexFieldMap.put(excelProperty.index(), field);
return;
}
int order = Integer.MAX_VALUE;
if (excelProperty != null) {
order = excelProperty.order();
}
List<Field> orderFieldList = orderFieldMap.computeIfAbsent(order, key -> ListUtils.newArrayList());
orderFieldList.add(field);
}
仔细观察以下这段代码,他会剔除 static final和transientx 修饰的字段。也就是__$stMC和metaClass。经过测试,使用java 类生成的字节码也会包含这两个字段。
boolean isStaticFinalOrTransient =
(Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()))
|| Modifier.isTransient(field.getModifiers());
if (excelProperty == null && isStaticFinalOrTransient) {
ignoreMap.put(field.getName(), field);
return;
}
分析其中这两段代码,发现如果类用 @ExcelIgnoreUnannotated() 修饰,并且没有被@ExcelProperty注解的属性也会被剔除掉
ExcelIgnoreUnannotated excelIgnoreUnannotated = clazz.getAnnotation(ExcelIgnoreUnannotated.class)
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
boolean noExcelProperty = excelProperty == null && excelIgnoreUnannotated != null;
if (noExcelProperty) {
ignoreMap.put(field.getName(), field);
return;
}
通过以上分析,就可以解释读取文件出错的原因了。
当Person类中声明的属性少于excel文件中的字段,并且没有用@ExcelIgnoreUnannotated() 注解类时,$staticClassInfo, $callSiteArray, $staticClassInfo$ 这三个字段将会参与到字段映射的操作中去,于是出现了类型转换的错误。