java 读取excel(支持xlsx、xls格式, 支持合并单元格)


推荐
更加规范和完整的工具:
码云-chimm.excel
码云-chimm.excel:设置单元格公式 值不对Issuse

个人学习练手的工具:java创建excel(不用设置样式,支持xlsx、xls格式, 不支持合并单元格)

实现效果
  • 将excel看成一个二维表,将数据存放在List<List>>中。[0,0]表示第一个单元格,[5,3]表示第6行,第4列数据,若空行或空列也会存在对应的下标位置。
  • 合并单元的值取最左上角单元格的值。每个子单元格的值与合并单元格的值保持一致。如:[0行,1行,0列,1列]为合并单元格,值为“AAA”。那么[0,0]、[0,1]、[1,0]、[1,1]的值都为“AAA”。
  • 可将某行为表头,将excel内容封装为bean或map集合,见sheetList2Bean、sheetList2Map方法。
概念
  • excel文件对应的是 workbook(xls xlsx)
  • 每个workbook 中有多个 sheet
  • 每个sheet有多行 Row
  • 每行有多列 Cell
  • sheet.getLastRowNum:获取sheet最后有数据行的下标(包含空行)。最后有数据的行是第n行则返回n-1,一行数据都没有则返回-1。行遍历,下标从0开始
  • row.getLastCellNum:获取某行最后有数据的列(包含空列)。只有第一列有数据则返回1,最后有数据的列是第n列则返回n,一列数据都没有则返回-1。列遍历,下标从0开始
  • sheet.getPhysicalNumberOfRows:获取sheet中实际有数据的行数(即,非默认格式的行数),一行数据都没有则返回0
  • row.getPhysicalNumberOfCells:获取某行实际有数据的列数(即,非默认格式的列数),一列数据都没有则返回0

注意事项
1、获取的excel行数不正确解决方法
2、poi认为的有数据:一般情况,非默认格式的行或列都是有数据的。特例,行高改变,被认为该行是有数据的;列宽改变,被认为该列是无数据列。
3、java进行Excel导入数字类型的处理:https://www.cnblogs.com/renjiaqi/p/10072861.html、https://www.cnblogs.com/renjiaqi/p/10072861.html

上面的执行的结果是:
case NUMERIC:
cellValue = String.valueOf(cell.getNumericCellValue());
break;
1.242532523632E12 //不是我们想要的字符串呢
那就使用poi的另一个神器NumberToTextConverter,改写switch的代码:

case NUMERIC:
// 改成这样
cellValue = NumberToTextConverter.toText(cell.getNumericCellValue());
break;
执行后返回:
1242532523632 //我们想要的结果
//引用poi包工具类数字转化工具
import org.apache.poi.ss.util.NumberToTextConverter;
//引用poi包时间格式判断工具
import org.apache.poi.hssf.usermodel.HSSFDateUtil;

//判断单元格的数据类型为数值,且不为时间的
if(!(cell.getCellType()!= Cell.CELL_TYPE_NUMERIC || 
   HSSFDateUtil.isCellDateFormatted(cell))) {
   String val=NumberToTextConverter.toText(cell.getNumericCellValue());
   System.out.println("---val:"+val);
}
依赖
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.2</version>
</dependency>
代码实现

所有代码都在一个类,方便直接使用。
完整代码及excel模板:https://gitee.com/andus_top/java-excel

测试代码
public static void main(String[] args) throws IOException, IllegalAccessException {

        ExcelReader excelReader = new ExcelReader("C:\\Users\\YSL\\Desktop\\read-test.xlsx");

        // test1: 获取sheet所有或指定位置的内容
        System.out.println("test1: 获取sheet所有或指定位置的内容");
        //List<List<Object>> sheetContent = excelReader.getSheetContent(0, 5, 11, 1, 2);
        List<List<Object>> sheetContent = excelReader.getSheetContent(0);
        for (List<Object> objects : sheetContent) {
            if(objects != null) {
                for (Object object : objects) {
                    if (object != null) {
                        System.out.print(String.valueOf(object) + ", ");
                    }else{
                        System.out.print("null, ");
                    }
                }
                System.out.println("\n");
            }else{
                System.out.println("跳过空行");
            }
        }

        // test2: 遍历excel每个sheet,获取sheet指定范围的内容
        System.out.println("\ntest2: 遍历excel每个sheet,获取sheet指定范围的内容");
        excelReader.clearCache();
        Map<String, List<List<Object>>> workbookContentMap = excelReader.getWorkbookContentMap(5, 11, 1, 2);
        workbookContentMap.forEach((k, v) -> {
            System.out.println(k);
            v.forEach(i -> {
                if(i != null)
                    i.forEach(j -> {
                        System.out.print(j + ", ");
                    });
                System.out.println();
            });
        });

        // test3: 遍历excel每个sheet,获取sheet指定范围的内容
        System.out.println("\ntest3: 遍历excel每个sheet,获取sheet指定范围的内容");
        excelReader.clearCache();
        List<List<List<Object>>> workbookContentList = excelReader.getWorkbookContentList();
        //List<List<List<Object>>> workbookContentList = excelReader.getWorkbookContentList(5, 11, 1, 2);
        workbookContentList.forEach(sheet -> {
            sheet.forEach(row -> {
                if(row != null) {
                    row.forEach(cell -> {
                        if (cell != null)
                            System.out.print(cell + ", ");
                    });
                    System.out.println();
                }
            });
        });

        // test4: 获取sheet内容,按指定行作为表头,转存为List<Bean> 结构
        System.out.println("\ntest4: 获取sheet内容,按指定行作为表头,转存为List<Bean> 结构");
        List<Bean> beans = excelReader.sheetList2Bean(0, 1, () -> new Bean());
        //List<Bean> beans = excelReader.sheetList2Bean("Sheet1", 1, Bean::new);
        beans.forEach(System.out::println);

        // test5: 获取sheet内容,按指定行作为表头,转存为 Map 结构
        System.out.printf("\ntest5: 获取sheet内容,按指定行作为表头,转存为 Map 结构");
        List<Map<String, Object>> mapList = excelReader.sheetList2Map("Sheet1", 1);
        mapList.forEach(System.out::println);

        excelReader.close();
    }
ExcelReader.java 工具类

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
//引用poi包工具类数字转化工具
import org.apache.poi.ss.util.NumberToTextConverter;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

/**
 * 读excel
 * @author andus.top
 * @date 2021/6/1  20:41
*/
public class ExcelReader {

    private Workbook workbook;
    private Map<String, List<List<Object>>> workbookContent;
    private FileInputStream in;

    public ExcelReader(File file) throws IOException {
        String fileName = file.getName();
        in = new FileInputStream(file);
        try{
            if(fileName.endsWith(".xls")){
                workbook = new HSSFWorkbook(in);
            }else if(fileName.endsWith(".xlsx")){
                workbook = new XSSFWorkbook(in);
            }
        }finally {

        }
        if(workbook == null){
            throw new RuntimeException("excel 文件格式错误");
        }
    }

    public ExcelReader(String filePath) throws IOException {
        this(new File(filePath));
    }

    public ExcelReader(FileInputStream in, boolean xls) throws IOException {
        this.in = in;
        if(xls){
            workbook = new HSSFWorkbook(this.in);
        }else{
            workbook = new XSSFWorkbook(this.in);
        }
    }

    /**
     * 获取sheet内容,按指定行作为表头,转存为List&lt;T&gt; 结构
     * @param sheetIndex sheet下标,从0开始
     * @param keyIndex 第几行用作key,从0开始。注意,key行的长度小于内容行,多余的内容会丢失;反之会放入null
     * @param keyIndex sup
     * @author andus.top
     * @date 2021/6/1 19:17
     * @return 将sheet内容从list,转为按指定行做key的map
     */
    public <T> List<T>  sheetList2Bean(int sheetIndex, int keyIndex, Supplier<T> sup) throws IllegalAccessException {
        return sheetList2Bean(getSheetContent(sheetIndex), keyIndex, sup);
    }

    /**
     * 获取sheet内容,按指定行作为表头,转存为List&lt;T&gt; 结构
     * @param sheetName sheet名称
     * @param keyIndex 第几行用作key,从0开始。注意,key行的长度小于内容行,多余的内容会丢失;反之会放入null
     * @param keyIndex sup
     * @author andus.top
     * @date 2021/6/1 19:17
     * @return 将sheet内容从list,转为按指定行做key的map
     */
    public <T> List<T>  sheetList2Bean(String sheetName, int keyIndex, Supplier<T> sup) throws IllegalAccessException {
        return sheetList2Bean(getSheetContent(sheetName), keyIndex, sup);
    }

    /**
     * 获取sheet内容,按指定行作为表头,转存为map结构
     * @param sheetIndex sheet下标,从0开始
     * @param keyIndex 第几行用作key,从0开始。注意,key行的长度小于内容行,多余的内容会丢失;反之会放入null
     * @author andus.top
     * @date 2021/6/1 19:17
     * @return 将sheet内容从list,转为按指定行做key的map
     */
    public List<Map<String, Object>> sheetList2Map(int sheetIndex, int keyIndex){
        return sheetList2Map(getSheetContent(sheetIndex), keyIndex);
    }

    /**
     * 获取sheet内容,按指定行作为表头,转存为map结构
     * @param sheetName sheet名称
     * @param keyIndex 第几行用作key,从0开始。注意,key行的长度小于内容行,多余的内容会丢失;反之会放入null
     * @author andus.top
     * @date 2021/6/1 19:17
     * @return 将sheet内容从list,转为按指定行做key的map
     */
    public List<Map<String, Object>> sheetList2Map(String sheetName, int keyIndex){
        return sheetList2Map(getSheetContent(sheetName), keyIndex);
    }

    /**
     * 获取sheet所有或指定位置的内容。若为合并单元格,子单元格会的值为合并单元格的值<br>
     * note:若在该方法之前已读取了excel数据,那么需调用clearCache方法,清空之前的数据,否则指定范围读取无效
     * @param sheetIndex sheet下标,从0开始
     * @param range  下标从0开始。<b>要么不传,要么4个值都传。</b>-1表示取到最后一行或最后一列<br>
     *  &nbsp; range结构为:[int startRow, int endRow, int startCol, int endCol] <br>
     *  &emsp;&emsp;  startRow 开始的行,从0开始<br>
     *  &emsp;&emsp;  endRow 结束的行<br>
     *  &emsp;&emsp;  startCol 开始的列,从0开始<br>
     *  &emsp;&emsp;  endCol 结束的列<br>
     * @author andus.top
     * @date 2021/6/1 20:46
     */
    public List<List<Object>> getSheetContent(int sheetIndex, Integer...range){
        return getWorkbookContentList(range).get(sheetIndex);
    }

    /**
     * 获取sheet所有或指定位置的内容。若为合并单元格,子单元格会的值为合并单元格的值<br>
     * note:若在该方法之前已读取了excel数据,那么需调用clearCache方法,清空之前的数据,否则指定范围读取无效
     * @param sheetName sheet名称
     * @param range  下标从0开始。<b>要么不传,要么4个值都传。</b>-1表示取到最后一行或最后一列<br>
     *  &nbsp; range结构为:[int startRow, int endRow, int startCol, int endCol] <br>
     *  &emsp;&emsp;  startRow 开始的行,从0开始<br>
     *  &emsp;&emsp;  endRow 结束的行<br>
     *  &emsp;&emsp;  startCol 开始的列,从0开始<br>
     *  &emsp;&emsp;  endCol 结束的列<br>
     * @author andus.top
     * @date 2021/6/1 20:46
     */
    public List<List<Object>> getSheetContent(String sheetName, Integer...range){
        return getWorkbookContentMap(range).get(sheetName);
    }

    /**
     * 遍历excel,获取sheet所有或指定范围的内容。返回List集合<br>
     * note:若在该方法之前已读取了excel数据,那么需调用clearCache方法,清空之前的数据,否则指定范围读取无效
     * @param range  下标从0开始。<b>要么不传,要么4个值都传。</b>-1表示取到最后一行或最后一列<br>
     *  &nbsp; range结构为:[int startRow, int endRow, int startCol, int endCol] <br>
     *  &emsp;&emsp;  startRow 开始的行,从0开始<br>
     *  &emsp;&emsp;  endRow 结束的行<br>
     *  &emsp;&emsp;  startCol 开始的列,从0开始<br>
     *  &emsp;&emsp;  endCol 结束的列<br>
     * @author andus.top
     * @date 2021/6/1 20:41
     * @return 按照sheetIndex->row->cell 逐层获取。List&lt;List&lt;Object&gt;&gt; 为每个sheet数据;List&lt;Object&gt; 为每行数据
    */
    public List<List<List<Object>>> getWorkbookContentList(Integer...range){
        if(workbookContent == null || workbookContent.isEmpty()){
            getWorkbookContentMap(range);
        }
        List<List<List<Object>>> rlist = new ArrayList<>(workbookContent.size());
        workbookContent.forEach((k,v) -> rlist.add(v));
        return rlist;
    }

    /**
     * 遍历excel,获取sheet所有或指定范围的内容。返回Map集合<br>
     * note:若在该方法之前已读取了excel数据,那么需调用clearCache方法,清空之前的数据,否则指定范围读取无效
     * @param range  下标从0开始。<b>要么不传,要么4个值都传。</b>-1表示取到最后一行或最后一列<br>
     *  &nbsp; range结构为:[int startRow, int endRow, int startCol, int endCol] <br>
     *  &emsp;&emsp;  startRow 开始的行,从0开始<br>
     *  &emsp;&emsp;  endRow 结束的行<br>
     *  &emsp;&emsp;  startCol 开始的列,从0开始<br>
     *  &emsp;&emsp;  endCol 结束的列<br>
     * @author andus.top
     * @date 2021/6/1 20:41
     * @return 按照sheetName->row->cell 逐层获取。key为sheet名称;vlaue为每个sheet数据;List&lt;Object&gt; 为每行数据
     */
    public Map<String, List<List<Object>>> getWorkbookContentMap(Integer...range){
        if(range == null || range.length%4 != 0){
            System.err.println("sheet range format is error");
            return null;
        }
        if(workbookContent == null || workbookContent.isEmpty()){
            workbookContent = new HashMap<>();
            int numberOfSheets = workbook.getNumberOfSheets();
            for (int x = 0; x < numberOfSheets; x++) {
                Sheet sheet = workbook.getSheetAt(x);
                workbookContent.put(sheet.getSheetName(), getSheetContent(sheet, range));
            }
        }
        return workbookContent;
    }

    /**
     * 清空workbookContent。<br>
     * 需要指定范围读取数据时,需清空之前的数据
     * @author andus.top
     * @date 2021/6/29 14:24
    */
    public void clearCache(){
        if(workbookContent != null)workbookContent.clear();
    }

    /**
     * 关闭流
     * @author andus.top
     * @date 2021/6/2 20:26
    */
    public void close(){
        try {
            if(workbook != null){
                workbook.close();
            }
            if(in != null){
                in.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取每个sheet的数据。合并单元格,获取第一个cell的值
     * @param sheet 当前org.apache.poi.ss.usermodel.Sheet对象
     * @param range  下标从0开始。<b>要么不传,要么4个值都传。</b>-1表示取到最后一行或最后一列<br>
     *  &nbsp; range结构为:[int startRow, int endRow, int startCol, int endCol] <br>
     *  &emsp;&emsp;  startRow 开始的行,从0开始<br>
     *  &emsp;&emsp;  endRow 结束的行<br>
     *  &emsp;&emsp;  startCol 开始的列,从0开始<br>
     *  &emsp;&emsp;  endCol 结束的列<br>
     * @author andus.top
     * @date 2021/6/1 20:50
    */
    private List<List<Object>> getSheetContent(Sheet sheet, Integer...range){
        if(sheet == null){
            System.err.println("sheet is null");
            return null;
        }

        // // fixme 【已修复】开始行设置为0,保证通过下标获取数据时,不会出错。
        Integer startRow = 0; // sheet.getFirstRowNum():第0行无数据,第1行有数据,此时返回1
        Integer endRow = sheet.getLastRowNum(); // n行返回n-1
        if(range != null && range.length == 4){
            // 开始行和结束行小于0,或者结束行小于开始行 ,或者其他参数错误时,使用getFirstRowNum或
            if(range[0] > 0 && range[0] <= endRow && (range[0] <= range[1] || range[1] < 0)){ // range[1] < 0 与 getLastRowNum 等价
                startRow = range[0];
            }
            if(range[1] > 0 && range[1] <= endRow  && range[0] <= range[1]){
                endRow = range[1];
            }
        }
        List<List<Object>> slist = new ArrayList<>((endRow - startRow) + 1);
        // 遍历指定范围的行
        for (int x = startRow; x <= endRow; x++){
            slist.add(getRow(sheet.getRow(x), range));
        }
        return slist;
    }
    /**
     * 获取当前row的数据。合并单元格,获取第一个cell的值
     * @param row 当前org.apache.poi.ss.usermodel.Row对象
     * @param range  下标从0开始。<b>要么不传,要么4个值都传。</b>-1表示取到最后一行或最后一列<br>
     *  &nbsp; range结构为:[int startRow, int endRow, int startCol, int endCol] <br>
     *  &emsp;&emsp;  startRow 开始的行,从0开始<br>
     *  &emsp;&emsp;  endRow 结束的行<br>
     *  &emsp;&emsp;  startCol 开始的列,从0开始<br>
     *  &emsp;&emsp;  endCol 结束的列<br>
     * @author andus.top
     * @date 2021/6/1 20:51
    */
    private List<Object> getRow(Row row, Integer...range){
        if(row == null){
            return null;
        }
        // fixme  【已修复】开始行设置为0,保证每列数据不会错误。即,保证转换为key,value是 不会错位
        short startCol = 0; // row.getFirstCellNum():第0列无数据,第1列有数据,此时返回1
        short endCol = (short)(row.getLastCellNum()-(short) 1); //  n列,返回n。fixme: 【已修复】所以最大列数需减一
        if(range != null && range.length == 4){
            // 开始行和结束行小于0,或者结束行小于开始行 ,或者其他参数错误时,使用getFirstRowNum或
            if(range[2] > 0 && range[2] <= endCol && (range[2] <= range[3] || range[3] < 0)){ // range[3] < 0 与 getLastCellNum 等价
                startCol = Short.valueOf(String.valueOf(range[2]));
            }
            if(range[3] > 0 && range[3] <= endCol  && range[2] <= range[3]){
                endCol = Short.valueOf(String.valueOf(range[3]));
            }
        }

        List<Object> rlist = new ArrayList<>();
        // 遍历指定范围的列
        for (int x = startCol; x <= endCol; x++) {
            Cell cell = row.getCell(x);

            if(cell != null) {
                boolean isMerge = isMergedRegion(row.getSheet(), row.getRowNum(), cell.getColumnIndex());
                //判断是否具有合并单元格
                if (isMerge) {
                    rlist.add(getMergedRegionValue(row.getSheet(), row.getRowNum(), cell.getColumnIndex()));
                } else {
                    rlist.add(getCellValue(cell));
                }
            }else{
                // 添加null
                rlist.add(getCellValue(cell));
            }
        }

        // 直接迭代,读取所有行
        // List<Object> rlist = new ArrayList<>();
        // row.cellIterator().forEachRemaining(cell -> rlist.add(getCell(cell)));
        return rlist;
    }
    /**
     * 获取当前cell的数据
     * @param cell 当前org.apache.poi.ss.usermodel.Cell对象
     * @author andus.top
     * @date 2021/6/1 20:52
     */
    private Object getCellValue(Cell cell){
        if(cell == null){
            return null;
        }else{
            CellType cft = cell.getCellType();
            switch (cft){
                case BLANK:
                    return "";
                case BOOLEAN:
                    return cell.getBooleanCellValue();
                case ERROR:
                    return cell.getErrorCellValue();
                case NUMERIC:
                    if(DateUtil.isCellDateFormatted(cell)){
                       return cell.getLocalDateTimeCellValue();
                    }else{//判断单元格的数据类型为数值,且不为时间的
                        return NumberToTextConverter.toText(cell.getNumericCellValue());
                    }
                case FORMULA:
                    return cell.getCellFormula();
                    //return cell.getStringCellValue();
                default:
                    return cell.getStringCellValue();
                    //return cell.getRichStringCellValue().toString();
            }
        }
    }

    /**
     * 判断指定的单元格是否是合并单元格
     * @param sheet
     * @param row 行下标
     * @param column 列下标
     * @return true:是合并单元格,false:非合并单元格
     */
    private static boolean isMergedRegion(Sheet sheet, int row ,int column) {

        // 得到一个sheet中有多少个合并单元格
        int sheetMergeCount = sheet.getNumMergedRegions();
        for (int i = 0; i < sheetMergeCount; i++) {

            // 得出具体的合并单元格
            CellRangeAddress range = sheet.getMergedRegion(i);

            // 得到合并单元格的起始行, 结束行, 起始列, 结束列
            int firstColumn = range.getFirstColumn();
            int lastColumn = range.getLastColumn();
            int firstRow = range.getFirstRow();
            int lastRow = range.getLastRow();

            // 判断该单元格是否在合并单元格范围之内, 如果是, 则返回 true
            if(row >= firstRow && row <= lastRow){
                if(column >= firstColumn && column <= lastColumn){
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 获取合并单元格的值<br>
     * 即获取合并单元格第一个cell的值
     * @param sheet 当前sheet
     * @param row 当前行下标
     * @param column 当前列下标
     * @return 该合并单元格的值
     */
    private Object getMergedRegionValue(Sheet sheet ,int row , int column){

        // 获得一个 sheet 中合并单元格的数量
        int sheetMergeCount = sheet.getNumMergedRegions();

        // 遍历合并单元格
        for(int i = 0 ; i < sheetMergeCount ; i++){

            // 得出具体的合并单元格
            CellRangeAddress ca = sheet.getMergedRegion(i);

            // 得到合并单元格的起始行, 结束行, 起始列, 结束列
            int firstColumn = ca.getFirstColumn();
            int lastColumn = ca.getLastColumn();
            int firstRow = ca.getFirstRow();
            int lastRow = ca.getLastRow();

            // 获取合并单元格第一个cell的值
            if(row >= firstRow && row <= lastRow){
                if(column >= firstColumn && column <= lastColumn){
                    Row fRow = sheet.getRow(firstRow);
                    Cell fCell = fRow.getCell(firstColumn);
                    return getCellValue(fCell) ;
                }
            }
        }

        return null ;
    }

    private <T> List<T>  sheetList2Bean(List<List<Object>> sheet , int keyIndex, Supplier<T> sup) throws IllegalAccessException {
        int s = sheet.size(); // 当前sheet 行数
        List<T> elist = new ArrayList<>();
        List<Object> keyList = sheet.get(keyIndex);
        int ks = keyList.size();
        for (int x = keyIndex + 1; x < s; x++) {
            List<Object> row = sheet.get(x); // 某行数据
            Map<String, Object> emap = new HashMap<>();
            for (int y = 0; y < ks; y++) {
                emap.put(String.valueOf(keyList.get(y)), tryGet(row, y));
            }
            elist.add(map2Bean(emap, sup));
        }
        return elist;
    }

    private List<Map<String, Object>> sheetList2Map(List<List<Object>> sheet , int keyIndex){
        int rowNum = sheet.size();
        // 将每行map的对象存入List
        List<Map<String, Object>> elementList = new ArrayList<>();
        // 暂存指定的key
        List<Object> keyList = sheet.get(keyIndex);
        int keyNum = keyList.size();
        for (int x = keyIndex + 1; x < rowNum; x++) {
            List<Object> row = sheet.get(x);
            Map<String, Object> emap = new HashMap<>();
            elementList.add(emap);
            for (int y = 0; y < keyNum; y++) {
                emap.put(String.valueOf(keyList.get(y)), tryGet(row, y));
            }
        }
        return elementList;
    }

    // 可放于其他工具类
    private <T> T map2Bean(Map<String, Object> map, Supplier<T> sup) throws IllegalAccessException {
        T t = sup.get();
        Field[] fields = t.getClass().getDeclaredFields();
        for (Field field : fields) {
            String fname = field.getName();
            if(!Modifier.isStatic(field.getModifiers())){// 只取非静态对象
                field.setAccessible(true);
                Object o = map.get(fname);
                Class<?> type = field.getType();
                try {
                    if (o != null) {
                        switch (type.getName()) {
                            case "java.lang.String":
                                field.set(t, o.toString());
                                break;
                            case "int":
                                field.set(t, IntegerKit.parseInt(o));
                                break;
                            case "java.lang.Integer":
                                field.set(t, IntegerKit.of(o));
                                break;
                            case "java.time.LocalDateTime":
                                if (o instanceof LocalDateTime) {
                                    field.set(t, o);
                                } else {
                                    field.set(t, LocalDateTime.parse(o.toString(), DateTimeFormatter.ofPattern("yyyy-M-d  HH:mm:ss")));
                                }
                                break;
                            case "double":
                                field.set(t, DoubleKit.parseDouble(o));
                                break;
                            case "java.lang.Double":
                                field.set(t, DoubleKit.of(o));
                                break;
                            case "boolean":
                                field.set(t, BooleanKit.parseBoolean(o));
                                break;
                            case "java.lang.Boolean":
                                field.set(t, BooleanKit.of(o));
                                break;
                            case "float":
                                field.set(t, FloatKit.parseFloat(o));
                                break;
                            case "java.lang.Float":
                                field.set(t, FloatKit.of(o));
                                break;
                            case "short":
                                field.set(t, ShortKit.parseShort(o));
                                break;
                            case "java.lang.Short":
                                field.set(t, ShortKit.of(o));
                                break;
                            case "byte":
                                field.set(t, ByteKit.parseByte(o));
                                break;
                            case "java.lang.Byte":
                                field.set(t, ByteKit.of(o));
                                break;
                            default:
                                break;

                        }
                    } else {
                        System.err.println("data is null");
                    }
                }catch (Exception e){
                    e.printStackTrace();
                    // 打印数据转换错误
                    if (o != null)System.err.println("--->>>>field is " + field.getName() + ", field type is " + type + ",value is " + o + ", value type is " + o.getClass());
                }
            }
        }
        return t;
    }

    /**
     * 引用类型转换为基本类型
     * https://blog.youkuaiyun.com/csm_qz/article/details/46853567
     * @param cls
     * @author andus.top
     * @date 2021/6/1 16:08
     */
    private static Class<?> getBasicClass(Class<?> cls){
        if (Integer.class.equals(cls)) {
            return Integer.TYPE; //return int.class;
        }else if(Long.class.equals(cls)){
            return Long.TYPE; // return long.class;
        }else if(Float.class.equals(cls)){
            return Float.TYPE; // return float.class;
        }else if(Boolean.class.equals(cls)){
            return Boolean.TYPE;// return boolean.class;
        }else if(Character.class.equals(cls)){
            return Character.TYPE; // return char.class;
        }else if(Byte.class.equals(cls)){
            return Byte.TYPE; // return byte.class
        }else if(Void.class.equals(cls)){
            return Void.TYPE; // return void.class
        }else if(Short.TYPE.equals(cls)){
            return Short.TYPE; // short.class
        }
        return cls;
    }

    // 可放于其他工具类
    private <T>T tryGet(List<T> list, int index){
        if(list == null || list.size() <= index){
            return null;
        }
        return list.get(index);
    }

    static class IntegerKit {
        public static Integer of(Object o){
            if(o == null){
                return null;
            }
            if(o instanceof Integer){
                return (Integer)o;
            }
            if(o instanceof Number){
                return ((Number)o).intValue();
            }
            return of(o.toString());
        }
        public static Integer of(String s){
            if(s == null || s.isEmpty()){
                return null;
            }
            return Integer.valueOf(s);
        }

        public static int parseInt(String s){
            if(s == null || s.isEmpty()){
                return 0;
            }
            return Integer.parseInt(s);
        }

        public static int parseInt(Object o){
            Integer i = of(o);
            if(i == null){
                return 0;
            }
            return i;
        }
    }

    static class FloatKit {
        public static Float of(Object o){
            if(o == null){
                return null;
            }
            if(o instanceof Float){
                return (Float)o;
            }
            if(o instanceof Number){
                return ((Number)o).floatValue();
            }
            return of(o.toString());
        }
        public static Float of(String s){
            if(s == null || s.isEmpty()){
                return null;
            }
            return Float.valueOf(s);
        }

        public static float parseFloat(String s){
            if(s == null || s.isEmpty()){
                return 0l;
            }
            return Float.parseFloat(s);
        }

        public static float parseFloat(Object o){
            Float f = of(o);
            if(f == null){
                return 0l;
            }
            return f;
        }
    }

    static class DoubleKit {
        public static Double of(Object o){
            if(o == null){
                return null;
            }
            if(o instanceof Double){
                return (Double)o;
            }
            if(o instanceof Number){
                return ((Number)o).doubleValue();
            }
            return of(o.toString());
        }
        public static Double of(String s){
            if(s == null || s.isEmpty()){
                return null;
            }
            return Double.valueOf(s);
        }

        public static double parseDouble(String s){
            if(s == null || s.isEmpty()){
                return 0;
            }
            return Double.parseDouble(s);
        }

        public static double parseDouble(Object o){
            Double d = of(o);
            if(d == null){
                return 0;
            }
            return d;
        }
    }

    static class BooleanKit {
        public static Boolean of(Object o){
            if(o == null){
                return null;
            }
            if(o instanceof Boolean){
                return (Boolean)o;
            }
            return of(o.toString());
        }
        public static Boolean of(String s){
            if(s == null || s.isEmpty()){
                return null;
            }
            return Boolean.valueOf(s);
        }

        public static boolean parseBoolean(String s){
            if(s == null || s.isEmpty()){
                return false;
            }
            return Boolean.valueOf(s);
        }

        public static boolean parseBoolean(Object o){
            Boolean b = of(o);
            if(b == null){
                return false;
            }
            return b;
        }
    }

    static class ByteKit {
        public static Byte of(Object o){
            if(o == null){
                return null;
            }
            if(o instanceof Byte){
                return (Byte)o;
            }
            return of(o.toString());
        }
        public static Byte of(String s){
            if(s == null || s.isEmpty()){
                return null;
            }
            return Byte.valueOf(s);
        }

        public static byte parseByte(String s){
            if(s == null || s.isEmpty()){
                return 0;
            }
            return Byte.parseByte(s);
        }

        public static byte parseByte(Object o){
            Byte b = of(o);
            if(b == null){
                return 0;
            }
            return b;
        }
    }

    static class ShortKit {
        public static Short of(Object o){
            if(o == null){
                return null;
            }
            if(o instanceof Short){
                return (Short)o;
            }
            if(o instanceof Short){
                return ((Short)o).shortValue();
            }
            return of(o.toString());
        }
        public static Short of(String s){
            if(s == null || s.isEmpty()){
                return null;
            }
            return Short.valueOf(s);
        }

        public static short parseShort(String s){
            if(s == null || s.isEmpty()){
                return 0;
            }
            return Short.parseShort(s);
        }

        public static short parseShort(Object o){
            Short s = of(o);
            if(s == null){
                return 0;
            }
            return s;
        }
    }

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值