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方法只是检查了列表类型,没有检查列表中的元素的类型,所以是不严谨的。
Java泛型函数的运行时类型检查的问题的更多相关文章
- Java 泛型优点之编译时类型检查
Java 泛型优点之编译时类型检查 使用泛型代码要比非泛型代码更有优势,下面是 Java 官方教程对泛型其中一个优点的介绍: "Stronger type checks at compile ...
- Java基础之RTTI 运行时类型识别
运行时类型识别(RTTI, Run-Time Type Identification)是Java中非常有用的机制,在Java运行时,RTTI维护类的相关信息. 多态(polymorphism)是基于R ...
- Java泛型类型擦除与运行时类型获取
Java的泛型大家都知道是类型擦除的方式实现的,“编译器会进行泛型擦除”是一个常识了(实际擦除的是参数和自变量的类型).“类型擦除” 并非像许多开发者认为的那样,在 <..> 符号内的东西 ...
- C++学习之显式类型转换与运行时类型识别RTTI
static_cast const_cast reinterpret_cast 运行时类型识别(RTTI) dynamic_cast 哪种情况下dynamic_cast和static_cast使用的情 ...
- C++运行时类型识别
通过运行时类型识别(RTTI),程序能够使用基类的指针或引用来检索这些指针或引用所指对象的实际派生类型. 通过下面两个操作符提供 RTTI: 1. typeid 操作符,返回指针或引用所指对象的实际类 ...
- C++运行时类型判断dynamic_cast和typeid
dynamic_cast dynamic_cast < Type-id > ( expression ) dynamic_cast<类型>(变量) 在运行期间检测类型转换是否安 ...
- Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除问题
在开发时,遇到了下面这条语句,不懂,然习之. private List<MyZhuiHaoDetailModel> listLottery = new ArrayList<MyZhu ...
- java多态的向上转型与向下转型(与编译时类型与运行时类型有关)
1.编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定. 当编译时类型和运行时类型不一致时,就会出现所谓的多态. 因为子类是一个特殊的父类,因此java允许把一个子类对象直接 ...
- RTTI (Run-Time Type Identification,通过运行时类型识别) 转
参考一: RTTI(Run-Time Type Identification,通过运行时类型识别)程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型. RTTI提供了以下两个 ...
随机推荐
- Android github上开源项目、酷炫的交互动画和视觉效果地址集合
Android上开源的酷炫的交互动画和视觉效果:http://blog.csdn.net/u013278099/article/details/50323689 Awesome-android-ui: ...
- Python hex() 函数
描述 hex() 函数用于将10进制整数转换成16进制整数. 语法 hex 语法: hex(x) 参数说明: x -- 10进制整数 返回值 返回16进制整数. 实例 以下实例展示了 hex 的使用方 ...
- openssl之EVP系列之9---EVP_Digest系列函数的一个样例
openssl之EVP系列之9---EVP_Digest系列函数的一个样例 ---依据openssl doc/crypto/EVP_DigestInit.pod翻译 (作者:Drago ...
- 群智能优化算法-测试函数matlab源码
群智能优化算法测试函数matlab源代码 global M; creatematrix(2); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %画ackley图. %%%% ...
- VS2012/13中即将增加InstallShield升级版
对于Visual Studio 2012去掉了前作中的安装程序(Installer)项目模板,许多开发者都感到非常失望.这个流行的项目类型为开发者们提供了若干选项:除了InstallShield LE ...
- Redis(二十):Redis数据过期和淘汰策略详解(转)
原文地址:https://yq.aliyun.com/articles/257459# 背景 Redis作为一个高性能的内存NoSQL数据库,其容量受到最大内存限制的限制. 用户在使用Redis时,除 ...
- 关于NavigationItem.rightBarButtonItem设置
转自:http://blog.csdn.net/zhuzhihai1988/article/details/7701998 第一种: UIImage *searchimage=[UIImage ima ...
- web 安全问题(一):CSRF 攻击
什么是CSRF CSRF是怎么产生的 CSRF的攻击对象 CSRG的攻击手段 CSRF的防御措施 什么是CSRF 全称是(Cross Site Request Forgery)跨站请求伪造.也就是恶意 ...
- C++友元详解
1.什么是友元在一个类A中,将类B声明为友元类,则类B可以访问类A的私有成员和保护成员.另外,也可以将函数声明为友元函数. 2.什么时候用到友元若不同的类之间某些共享数据成员,可以使用友元,简化类的设 ...
- Oracle PLSQL Demo - 03.流程判断[IF ELEIF ELSE]
declare v_job ) := 'Programmer'; v_sal number; begin if v_job = 'Programmer' then v_sal :; elsif v_j ...