为了账号安全,请及时绑定邮箱和手机立即绑定

ClassCast 异常:子类实现在调用超类方法时抛出异常

ClassCast 异常:子类实现在调用超类方法时抛出异常

拉丁的传说 2021-06-21 15:19:36
我创建了一个抽象类 Foo 。现在我想要一个上述通用类的字符串实现。但是当我运行代码时我得到了一个 ClassCast 异常。public abstract class Foo<T> {    abstract void add(T ... elements); //warning :Type safety: Potential heap pollution via varargs parameter elements    void addUnlessNull(T ... elements) //warning :Type safety: Potential heap pollution via varargs parameter elements    {        for(T element:elements)        {            if(element!=null)                add(element); // Warning:Type safety: A generic array of T is created for a varargs parameter        }    }}public class StringFoo extends Foo<String> {    private List<String> list=new ArrayList<>();    @Override    void add(String... elements) {        list.addAll(Arrays.asList(elements));    }    public static void main(String[] args)    {        StringFoo ss=new StringFoo();        ss.addUnlessNull("Hello","World"); //Class Cast Exception     }}Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;    at StringFoo.add(StringFoo.java:1)    at Foo.addUnlessNull(Foo.java:10)    at StringFoo.main(StringFoo.java:19)
查看完整描述

1 回答

?
繁花如伊

TA贡献2012条经验 获得超12个赞

我不知道为什么,但我想我知道原因。当您调用 时add(element), 将element被打包Object[] { element }并传递给add方法。所以有一个ClassCastExceptionfrom Object[]to String[]。


以下是一个不好的解决方案,但它应该可以解决您的问题。


if(element != null) {

    Object arr = Array.newInstance(element.getClass(), 1);

    Array.set(arr, 0, element);

    add((T[]) arr);

}

我在JDK 10上测试过,还有一个ClassCastException,上面的代码可以消除这个异常。


更新

我写了一个简单的例子,它也会产生ClassCastException:


abstract class A<T> {

    public void test(T t) { f(t); } 

    public abstract void f(T... ts);

}


class B extends A<String> {

    @Override

    public void f(String[] s) {}


    public static void main(String[] args) {

        new B().test("");

    }

}

我用反射检查了B的方法,有3个相关的方法:


public void B.f(java.lang.Object[])

public void B.f(java.lang.String[])

public void A.test(java.lang.Object)

当我打电话时new B().test(""),它会打电话public void A.test(java.lang.Object)。在这个方法中,它然后调用f(t),它实际上会调用public void B.f(java.lang.Object[])。那是因为t被视为Object(尽管它是String)。所以t被装入Object[]而不是String[]. 但是,类中的实际方法B是public void B.f(java.lang.String[]),因此有一个ClassCastException.


我不确定我是否理解正确,我无法在 JLS 中找到某些内容。


查看完整回答
反对 回复 2021-06-30
  • 1 回答
  • 0 关注
  • 115 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信