Map<String,String> stringMap = new HashMap<>(); //1
String value = https://www.cnblogs.com/dabaieyangzhijidi/p/stringMap.get("name"); //2
問個問題 如何才能讓第二行報下面的錯??
java.lang.ClassCastException:
java.lang.Integer cannot be cast to java.lang.String
這個問題是年前碰到的問題,今天突然想起來了,除錯了下原始碼,找了找答案,
事情經過是這樣子的,有一朋友寫了類似的代碼:
XML:
<select id="selectAllSongInfoMap" resultType="java.util.Map">
select * from song_Info
</select>
Mapper.java:
Map<String,String> selectAllSongInfoMap();
A.java:
Map<String,String> stringMap = selectAllSongInfoMap();
for (Map.Entry<String, String> stringStringEntry : stringMap.entrySet()) {
String value = https://www.cnblogs.com/dabaieyangzhijidi/p/stringStringEntry.getValue(); //233
}
行233報錯了:
java.lang.ClassCastException:
java.lang.Integer cannot be cast to java.lang.String
乍一看日志報錯的行號是233行,這肯定不能信啊,這行打死也不會報這個錯,
肯定一番操作,拉線上jar包,反編譯對行號,還特么是這行,直接蒙B
時間又回到了今晚,先說結論:
Map<String,String> myMap = null;
Map ff = new HashMap();
ff.put("age",22);
myMap = ff;
String s = myMap.get("age"); //5
行5就會報錯
java.lang.ClassCastException:
java.lang.Integer cannot be cast to java.lang.String
但是如果按照上邊寫的,你用的開發工具肯定就提醒了
但是你在Mybatis中用作回傳值就沒有提醒了
程序:
- 拉去Mybatis原始碼
- 打開原始碼中的org.apache.ibatis.session.SqlSessionTest類
- 測驗類配好資料庫直接跑
- 跟蹤代碼直到要把資料庫查出的值轉換成我們指定的型別的時候
- org.apache.ibatis.executor.resultset.DefaultResultSetHandler#getRowValue(org.apache.ibatis.executor.resultset.ResultSetWrapper, org.apache.ibatis.mapping.ResultMap, java.lang.String)
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
//根據xml中指定的回傳值創建物件
//這里java.util.Map 就會被實力化為 new HashMap() 沒有指定范型
Object rowValue = https://www.cnblogs.com/dabaieyangzhijidi/p/createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
// 這里就厲害了 根據rowValue實體化 先看后邊的
final MetaObject metaObject = configuration.newMetaObject(rowValue);
boolean foundValues = this.useConstructorMappings;
//到這里 也就是說
//MetaObject 被實體化成功
//其中的 objectWrapper 則被實體化成了 MapWrapper
//MapWrapper 中有個 Map map 屬性
//rowValue 則被賦值給了 map
//而 map 則可以作為 rowValue 的參考胡作非為
//后邊 兩個賦值操作
if (shouldApplyAutomaticMappings(resultMap, false)) {
foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
}
foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
foundValues = lazyLoader.size() > 0 || foundValues;
rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
}
return rowValue;
}
//實體化 MetaObject
private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
this.originalObject = object;
this.objectFactory = objectFactory;
this.objectWrapperFactory = objectWrapperFactory;
this.reflectorFactory = reflectorFactory;
//各式各樣
if (object instanceof ObjectWrapper) {
this.objectWrapper = (ObjectWrapper) object;
} else if (objectWrapperFactory.hasWrapperFor(object)) {
this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
} else if (object instanceof Map) {
//我們的Map 肯定就走這里了
this.objectWrapper = new MapWrapper(this, (Map) object);
} else if (object instanceof Collection) {
this.objectWrapper = new CollectionWrapper(this, (Collection) object);
} else {
this.objectWrapper = new BeanWrapper(this, object);
}
}
public class MapWrapper extends BaseWrapper {
//原來里面是有范型
private final Map map;
public MapWrapper(MetaObject metaObject, Map map) {
super(metaObject);
this.map = map;
}
.
.
.
}
大致再一梳理,就是這么回事,資料庫的欄位有int型別所以報了轉換的錯:
Map<String,String> myMap = null; //myMap
Map ff = new HashMap(); // ff
Map<String,Object> mObject = ff; // mObject
mObject.put("c",2);
mObject.put("a","b");
myMap = ff;
String s = myMap.get("c"); //報錯一行
mObject仗著自己有 ff 的參考,胡亂塞值,等到真正的使用者myMap使用的時候確報了強制轉換的錯誤,
突然聯想到昨晚看的奇葩說辯論“扶弟魔”,女人背著老公把錢借給弟弟,結果老公想買東西的時候發現沒錢了,
本文由博客一文多發平臺 OpenWrite 發布!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/262788.html
標籤:Java
下一篇:Spring回圈依賴問題的解決
