java 类型变量使用通配符后如何调用?

发布于 2022-09-12 00:03:36 字数 978 浏览 38 评论 0

有一个泛型类 A


class A<T extends Person>
{
    public void test(T val)
    {
        val.say();
    }
}

然后具有父子关系的普通类:

class Person {
    
}

class Male extends Person {
    public void say()
    {
        System.out.println("i am male");
    }
}

使用通配符代码运行以下代码后,无法执行!这是为什么?

class App {
    public static void main(String[] args)
    {
        // male 实例
        Male male = new Male();
        // 泛型类 A<Male>
        A<Male> maleA = new A<>();
        // 泛型类 A<? extends Person>
        A<? extends Person> personA = maleA;
        // 这个地方为什么报错?
        // 我看书中的解释是说 A<? extends Person> 中
        // 由于 ? 是通配符,虽然意思表明需要提供的类型
        // 为 Person 的子类型,但是由于通配符的原因
        // 导致该方法实际上是拒绝任何类型的
        // 所以实际上是成了无法调用的方法
        // 这是为什么?
        personA.test(male);
    }
}

使用了 ? 通配符后,即使提供正确的参数也无法成功调用(从代码上看...),这是为什么?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

暖树树初阳… 2022-09-19 00:03:36

学java泛型的时候要抛弃面向对象里面继承那一套东西,始终从类型安全角度来考虑。

A<Male> maleA = new A<>();
A<? extends Person> personA = maleA;
personA.test(male);

思考一下,从编译器的角度来考虑,在这段程序里面,personA的具体泛型类型是什么?
答案是不知道,编译器只知道是Person或其子类型,但无法确定具体类型是什么。所以把male传入test方法是不安全的。

举个例子,如果male允许,那么假设我有一个Female类,同样继承Person,那么下面这段代码:

Female female = ……
A<Male> maleA = new A<>();
A<? extends Person> personA = maleA;
personA.test(female);

同样可以通过编译,但这样就违反了设计泛型的初衷,破坏了类型安全性。所以java编译器干脆就拒绝编译这样的代码了

此生挚爱伱 2022-09-19 00:03:36

是无法执行还是无法通过编译,泛型不会影响执行,编译成字节码之后,所有调用的参数都会变成Person,调用不可能不成功。

如果编译不能成功,可以强制类型转换。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文