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提供了以下两个 ...
随机推荐
- object-c 获得目录(包括子目录)下所有文件和文件夹路径
void getAllPathNameInDirectory(vector<string>&filePathList,vector<string>&direct ...
- JS动态增加删除UL节点LI
JS如何动态增加删除UL节点LI及相关内容. <ul id="ul"> <li id=1>11111111111111111<a href=" ...
- [svc][op]LVS+keepalived
lvs是一种负载均衡技术.注意区分负载均衡和高可用的区别. keepalive是lvs的管理工具 ipvsadm也是lvs的管理工具 keepalive借助ipvsadm管理lvs.所以通常说lvs+ ...
- 在 Linux 上使用 Nginx 和 Gunicorn 托管 Django 应用
介绍 托管 Django Web 应用程序相当简单,虽然它比标准的 PHP 应用程序更复杂一些. 让 Web 服务器对接 Django 的方法有很多. Gunicorn 就是其中最简单的一个. Gun ...
- [leetcode] Longest Palindromic Substring 多种解法
非常经典的题目,求字符串中的最长回文子串. (1)最朴素的解法 ---暴力 复杂度O(N³) 这也是最easy想到的方法.最外层循环枚举起点i,第二层循环从i+1開始向后枚举,第三层推断是不是回文串. ...
- ie浏览器不兼容css媒体查询的解决办法
有些页面布局复杂,在不同分辨率下表现需要一致,这时需要用媒体查询根据不同分辨率进行百分比定位(不能用像素定位),如: @media screen and (max-width: 1600px) { . ...
- CCCatmullRomBy和CCPointArray
CCCatmullRomBy:把某一对象以Catmull-Rom curve曲线移动一段距离 CCPointArray *array = CCPointArray::create(); array-& ...
- html 中 input 控制输入百分比数值范围(0.0-100)
通过正则表达式在HTML的input中控制百分数的输入值(0.0-100),并且控制小数点的输入位置和个数 方案一: <input type="text" id=percen ...
- vim 学习日志(6):分屏 sp,vsp,分屏移动
Vim的分屏功能 本篇文章主要教你如何使用 Vim 分屏功能. 分屏启动Vim 使用大写的O参数来垂直分屏. vim -On file1 file2 ... 使用小写的o参数来水平分屏. vim -o ...
- 从JDBC程序看为什么需要Mybatis
package com.xuebusi.jdbc; import java.sql.*; /** * 从JDBC程序看为什么需要Mybatis * * 1.加载驱动程序和数据库连接所需要的url.用户 ...