java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Stringpublicstaticvoidmain(String[]args){Map<String,Object>tt=newHashMap<String,Object>();inta=187117;tt.put("aa",a);try{longb=(l…

大家好,欢迎来到IT知识分享网。java.lang.ClassCastException:

public static void main(String[] args) {
        Map<String,Object> tt= new HashMap<String,Object>();
        int a = 187117;
        tt.put("aa",a);
        try {
            long b = (long) tt.get("aa");
//            long b = Long.valueOf(String.valueOf(tt.get("aa"))).longValue();
            System.out.println(b);
        }catch (Exception e ){
            e.printStackTrace();
        }
    }

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
    at com.facishare.appserver.test.MyTest.main(MyTest.java:878)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

但是如果我们在map中put的时候直接put的是long类型则无错误,如果用户不清楚具体是什么类型传了int,这样则会出现转换错误。

具体解释如下:

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

问题背景

接口中参数为 Map<String,Object>取出某 KEY 值时,强制将其转为 String ,出现上述异常
问题分析

以 Map<String,Object> 作为参数的原因:可以传递多个参数;若使用 PO 类作为参数,不同项目中引用时需升级版本;
出现问题的原因:对外提供接口,没有在接口上明确注释,某个key的value是什么类型,只有当时写此接口的人才会避免此问题,其他调用者则不清楚,在调用接口后对结果进行了强制转换
代码级别分析:问题的根本是泛型与Object的区别
 

// 示例:模拟将Integer存入Map,取出后强制转为String
    public static void main(String[] args) {
        Map<String,Object> params = new HashMap<String,Object>();
        // value为 int 类型
        params.put("1", 1);
        // 取出 value 转为 String 
        // 运行时此处出现
        // java.lang.Integer cannot be cast to java.lang.String
        String result = (String)params.get("1");
        System.out.println(result);

    }

问题:

  • map.get(“”) 返回类型为 Object ,为何将 Object 转为 String 时出现异常?
// java -version 1.7.0_79 源码
// 1. java.util.Map 的数据结构
// HashMap 为解决hash冲突使用链地址法:
// 整体是一个数组结构,数组中每个位置存放一个链表,Entry 为链表中的一个节点
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;
// 从 Entry<K,V> 得出,其中 K,V 都是泛型

// 2. java.util.HashMap 中 put方法
public V put(K key, V value) {
}
// 方法中的参数类型均为泛型,与 Entry 对应

// 3.泛型的优势
// 编译期可确认数据类型

// 4.泛型与Object 的区别
// 使用泛型取值,无需类型转换; Object 需要转换
// 使用泛型作为参数,在编译期可检测数据类型不一致的问题
// 如:
Map<String,Object> params = new HashMap<String,Object>();
params.put("1",1);
params.put(2,2) ; // 编译期出现异常提示;K k ,指定 K 泛型的数据类型为 String 

// 5.JVM 在编译器根据执行的泛型的数据类型擦除泛型
// JVM 中无泛型的概念
// JVM 编译时根据指定的数据类型,如上例中,VALUE 为 int 类型
// JVM 编译代码后,VALUE  变为 int 类型

// 6.分析上述例子中的结果
        Object object = params.get("1");
        if(object instanceof Integer){
            System.out.println("true"); // 控制台打印 true 
            // 由输出结果可知:虽然map中取出的结果是 Object ,但其实质是 Integer ,故在将其强制转为 String 时会出现强制类型转换的异常
        }
// 示例:解决方法
        String result1 = String.valueOf(object);
        // String.valueOf 实质调用 object.toString() 方法
        System.out.println(result1);

问题总结

Map<String,Object>作为接口参数类型时要注明可以接收的KEY与对应VALUE的数据类型
从Map<String,Object> params取值时,要注意可能出现转换异常,为避免出现上述问题,可通过 instanceOf 判断;可使用toString() / String.valueOf() 将其先转为 String 再转为需要的数据类型
泛型

泛型常用表示及含义

E – Element (在集合中使用,因为集合中存放的是元素)
T – Type(Java 类)
K – Key(键)
V – Value(值)
N – Number(数值类型)
? – 表示不确定的java类型(无限制通配符类型)
S、U、V – 2nd、3rd、4th types

 

 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/21204.html

(0)
上一篇 2024-01-24 21:45
下一篇 2024-01-25 16:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信