zoukankan      html  css  js  c++  java
  • Java泛型函数的运行时类型检查的问题

    在一个数据持久化处理中定义了数据保存和读取的 泛型函数的,但是在运行时出现类型转换错误,类型不匹配,出错的位置不是load方法,而是在调用load方法之后,得到了列表数据,对列表数据进行使用时出现的。结果列表里面的元素实际是A类型,调用load方法传递的是B类型的class,但是仍然load成功。

    很是疑惑,最终修改代码调试后,解决问题。

    import android.content.Context;
    import android.text.TextUtils;
    
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.util.ArrayList;
    
    /**
         * 从私有文件加载对象
         * @param context
         * @param key 键值(文件名)
         * @return
         */
        public static Object loadFromPrivateFile(Context context, String key) {
            if (context == null || TextUtils.isEmpty(key)) {
                return null;
            }
    
            ObjectInputStream objectIn = null;
            Object result = null;
            try {
                FileInputStream fileIn = context.openFileInput(key);
                objectIn = new ObjectInputStream(fileIn);
                result = objectIn.readObject();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } finally {
                if (objectIn != null) {
                    try {
                        objectIn.close();
                    } catch (IOException e) {
                    }
                }
            }
            return result;
        }
    
        /**
         * 加载实体对象
         * @param context
         * @param key 键值(文件名)
         * @param clazzOfT 类类型
         */
        public static <T> T loadEntityObject(Context context, String key, Class<T> clazzOfT) {
            Object object = loadFromPrivateFile(context, key);
            if (object != null && clazzOfT != null && clazzOfT.isInstance(object)) {
                return clazzOfT.cast(object);
            }
            try {
                return (T) clazzOfT.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 加载数组列表
         * @param context
         * @param key 键值(文件名)
         * @param clazzOfT 类类型
         * @return
         */
        @SuppressWarnings("unchecked")
        public static <T> ArrayList<T> loadArrayList(Context context, String key, Class<T> clazzOfT) {
            Object object = loadFromPrivateFile(context, key);
            if (object instanceof ArrayList<?>) {
                try {
                    return (ArrayList<T>)object;
                } catch (Exception e) {
    
                }
            }
            return null;
        }
    
        /**
         * 加载数组列表
         * @param context
         * @param key 键值(文件名)
         * @param clazzOfT 类类型
         * @return
         */
        @SuppressWarnings("unchecked")
        public static <T> ArrayList<T> loadArrayList2(Context context, String key, Class<T> clazzOfT) {
            ArrayList<T> result = null;
            Object object = loadEntityObject(context, key, Object.class);
            if (object instanceof ArrayList<?>) {
                result = new ArrayList<T>();
                ArrayList<?> list = (ArrayList<?>)object;
                try {
                    final String className = clazzOfT. getName();
                    for (Object item : list) {
                        if (item. getClass().getName().equals(className)) {
                            result. add((T)item);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return result;
        }
    

    loadArrayList方法是错误的实现,下面的loadArrayList2是正确的实现。

    原因分析:泛型的类型信息在运行时是丢弃掉的,准确叫擦除(erasure),只有在编译时起到语法检查的作用。最初的loadArrayList方法只是检查了列表类型,没有检查列表中的元素的类型,所以是不严谨的。

  • 相关阅读:
    0108 创建表约束
    Mybatis 将数据库中查出的记录,一对多返回,即分组,然后返回每个组的所有数据
    SQL主表、从表
    MySQL中添加、删除字段,使用SQL语句操作
    git 将远程工作分支合并到本地dev分支
    MySQL inner join 和 left join 的区别
    Mysql union 和 order by 同时使用需要注意的问题
    The used SELECT statements have a different number of columns
    Every derived table must have its own alias(MySQL报错:每个派生表都必须有自己的别名)
    MySQL 日期格式化及字符串、date、毫秒互相转化
  • 原文地址:https://www.cnblogs.com/glowworm/p/6907906.html
Copyright © 2011-2022 走看看