Java泛型函數的運行時類型檢查的問題

在一個數據持久化處理中定義了數據保存和讀取的 泛型函數的,可是在運行時出現類型轉換錯誤,類型不匹配,出錯的位置不是load方法,而是在調用load方法以後,獲得了列表數據,對列表數據進行使用時出現的。結果列表裏面的元素實際是A類型,調用load方法傳遞的是B類型的class,可是仍然load成功。java

非常疑惑,最終修改代碼調試後,解決問題。android

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方法只是檢查了列表類型,沒有檢查列表中的元素的類型,因此是不嚴謹的。函數

相關文章
相關標籤/搜索