记录一次报错引起的对向下转型的理解

文章讲述了在Java中,如何从HashMap中获取值并转换为List时遇到的ClassCastException,解释了向下转型的概念,指出原因在于不能将父类引用强转为子类,提供了四种解决方案,包括使用keySet、values()迭代、entrySet迭代以及ArrayList构造器接收Collection。
摘要由CSDN通过智能技术生成

报错:

java.lang.ClassCastException: java.util.HashMap$Values cannot be cast to java.util.ArrayList

场景:

class DAO<T>{
    //一个hashMap对象
    private Map<String,T> map = new HashMap<>();
    //这个方法返回一个list类对象
    public List<T> list(){
        return (ArrayList<T>) map.values();
    }
}

这里想将HashMap中的值取出来转换成一个List接口类的对象再返回。然后使用HashMap的values()方法返回collection集合,再使用向下转型将collection集合转型为他的子类ArrayList发生类型转换错误。一开始想的比较简单,但是报错了,于是回顾之前的转型知识搞明白了为什么有这种情况。

回顾向下转型:

首先我们为什么要有向下转型?  因为在向上转型之后,我们的父类引用指向子类对象,但是如果我们要使用子类的特有方法,这时候会发现编译器报错,所以我们引出了向下转型。在这个向上转型和向下转型的过程中,向上转型是安全的,而向下转型并不是安全的。

比如

class Animal {}

class Dog extends Animal{}

public class test {
    public static void main(String[] args){
        
        Animal animal = new Animal();//创建一个父类对象
        
        Dog dog = (Dog) animal;//通过强制类型转换将animal对象强制向下转型赋给一个子类对象
       
    }    
}

这时会报错

Exception in thread "main" java.lang.ClassCastException: Homework.Animal cannot be cast to Homework.Dog at Homework.test.main(test.java:16)

也就是说我们是无法把一个子类对象的引用指向一个父类对象的。所以一开始的问题就明白了,使用HashMap类的values方法返回的是一个collection对象,我们是无法用子类对象引用ArrayList指向父类对象Collection实例的。之所以会犯这样的错误是因为我对向下转型的理解不够深刻,之前我们提到的向下转型是在向上转型的前提之下,也就是说不管向上转型向下转型,我们堆中的对象也就是我们的运行类型是不变的,变化的是引用也就是编译类型。

  结论:所以父类对象强转为子类对象的前提是父类对象要先引用这个子类对象

解决方案:

 1,通过HashMap的keySet方法返回keySet集合,再用Map的get()方法获得value

public List<T> list(){

        List<T> list = new ArrayList<>();
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            list.add(map.get(key));
        }
        return list;
}

2,通过HashMap的values()方法获得values集合,再使用迭代器或者foreach

public List<T> list(){

        List<T> list = new ArrayList<>();

        Collection<T> values = map.values();
        for (T t: values) {
            list.add(t);
        }
        return list;
}

 3,通过entrySet方法返回entrySet集合再使用迭代器或者foreach,再调用entry类型的getValues和getKey

public List<T> list(){

        List<T> list = new ArrayList<>();
        Set<Map.Entry<String, T>> entries = map.entrySet();
        Iterator<Map.Entry<String, T>> iterator = entries.iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, T> next = iterator.next();
            list.add(next.getValue());
        }
        return list;
}

 4这种也是最简单的一种,直接使用ArrayList的有参构造器public ArrayList(Collection<? extends E> var1)

public List<T> list(){
      ArrayList<T> ts = new ArrayList<>(map.values());
      return ts;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值