在一个数据持久化处理中定义了数据保存和读取的 泛型函数的,但是在运行时出现类型转换错误,类型不匹配,出错的位置不是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方法只是检查了列表类型,没有检查列表中的元素的类型,所以是不严谨的。

Java泛型函数的运行时类型检查的问题的更多相关文章

  1. Java 泛型优点之编译时类型检查

    Java 泛型优点之编译时类型检查 使用泛型代码要比非泛型代码更有优势,下面是 Java 官方教程对泛型其中一个优点的介绍: "Stronger type checks at compile ...

  2. Java基础之RTTI 运行时类型识别

    运行时类型识别(RTTI, Run-Time Type Identification)是Java中非常有用的机制,在Java运行时,RTTI维护类的相关信息. 多态(polymorphism)是基于R ...

  3. Java泛型类型擦除与运行时类型获取

    Java的泛型大家都知道是类型擦除的方式实现的,“编译器会进行泛型擦除”是一个常识了(实际擦除的是参数和自变量的类型).“类型擦除” 并非像许多开发者认为的那样,在 <..> 符号内的东西 ...

  4. C++学习之显式类型转换与运行时类型识别RTTI

    static_cast const_cast reinterpret_cast 运行时类型识别(RTTI) dynamic_cast 哪种情况下dynamic_cast和static_cast使用的情 ...

  5. C++运行时类型识别

    通过运行时类型识别(RTTI),程序能够使用基类的指针或引用来检索这些指针或引用所指对象的实际派生类型. 通过下面两个操作符提供 RTTI: 1. typeid 操作符,返回指针或引用所指对象的实际类 ...

  6. C++运行时类型判断dynamic_cast和typeid

    dynamic_cast dynamic_cast < Type-id > ( expression ) dynamic_cast<类型>(变量) 在运行期间检测类型转换是否安 ...

  7. Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除问题

    在开发时,遇到了下面这条语句,不懂,然习之. private List<MyZhuiHaoDetailModel> listLottery = new ArrayList<MyZhu ...

  8. java多态的向上转型与向下转型(与编译时类型与运行时类型有关)

    1.编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定. 当编译时类型和运行时类型不一致时,就会出现所谓的多态. 因为子类是一个特殊的父类,因此java允许把一个子类对象直接 ...

  9. RTTI (Run-Time Type Identification,通过运行时类型识别) 转

    参考一: RTTI(Run-Time Type Identification,通过运行时类型识别)程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型.   RTTI提供了以下两个 ...

随机推荐

  1. POJ 2299:Ultra-QuickSort

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 39397   Accepted: 14204 ...

  2. __align

    __align关键字指示编译器在n字节边界上对齐变量. __align是一个存储类修饰符.它不影响函数的类型. 语法 __align(n) 其中:  n是对齐边界. n可以具有值1.2.4或者8. _ ...

  3. elk中文教程

    https://kibana.logstash.es/content/elasticsearch/monitor/logging.html ELK 实战之Elasticsearch ELK 地址:ht ...

  4. linux centos7 常用命令【systemctl替换service】

    虽然linux的命令很多都是相同的,但是新版的centos 7 上面与以前的有些命令还是有所不同,不过还好,有提示.所以就在百度上面搜索了以下,作为记载,以后方便查看: centos7 上面启动服务以 ...

  5. HDU 2444 The Accomodation of Students二分图判定和匈牙利算法

    本题就是先推断能否够组成二分图,然后用匈牙利算法求出最大匹配. 究竟怎样学习一种新算法呢? 我也不知道什么方法是最佳的了,由于看书本和大牛们写的匈牙利算法具体分析,看了几乎相同两个小时没看懂,最后自己 ...

  6. Codeforces 86C Genetic engineering (AC自己主动机+dp)

    题目大意: 要求构造一个串,使得这个串是由所给的串相连接构成,连接能够有重叠的部分. 思路分析: 首先用所给的串建立自己主动机,每一个单词节点记录当前节点可以达到的最长后缀. 開始的时候想的是dp[i ...

  7. [na]思科产品选型pdf

    以前做工程时候想起了设备选型时候用过的一份文档. 有个小伙伴今天问起思科设备选型,恰好google到了这份文档 https://www.cisco.com/web/CN/products/pdf/04 ...

  8. Mingw opencv Windows下命令行运行

    1.下载opencv 2.3 http://sourceforge.net/projects/opencvlibrary/files/ 下个opencv-win版本吧 至于版本号就随意吧,我选的是2. ...

  9. feginclinet中设置hystrix的参数

    package com.example.demo; import com.netflix.hystrix.HystrixCommand; //import com.netflix.hystrix.co ...

  10. 快速了解Log4J (转)

    http://liuzhijun.iteye.com/blog/1746571 ***************************************** Log4J的三个组件: Logger ...