Java通配符看这一篇就够

本文详细解析了Java中的类或接口范型、方法范型和引用范型通配符,包括不同情况下的类型确定规则,以及它们在实际编程中的应用,特别关注了向上转型的概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

推荐你阅读
互联网大厂万字专题总结
Redis总结
JUC总结
操作系统总结
JVM总结
Mysql总结
互联网大厂常考知识点
什么是系统调用
CPU底层锁指令有哪些
AQS与ReentrantLock原理
旁路策略缓存一致性
Java通配符看这一篇就够

类或接口范型通配符

类或接口范型可以应用到属性方法形参方法局部变量方法返回类型

第一种情况

类或接口范型类型可以是任意类型,不指定类型默认 Object 类型

class A<T> {
    public T t;

    public void set(T t) {
        T localVar = t;
        this.t = localVar;
    }

    public T get() {
        return t;
    }
}

第二种情况

类范型类型只允许是 B 类及其子类,不指定类型默认 B 类型

class A<T extends B> {
    public T t;

    public void set(T t) {
        T localVar = t;
        this.t = localVar;
    }

    public T get() {
        return t;
    }
}

方法范型通配符

方法范型可以由形参类型形参对象范型确定,可以应用到方法局部变量、方法返回类型

第一种情况

方法范型可以是任意类型,由形参确定

class A {
    public <T> T test(T t) {
        T tmp = t;
        return tmp;
    }
}

第二种情况

方法范型只能是 B 类型及其子类型,由形参确定

class A {
    public <T extends B> T test(T t) {
        T tmp = t;
        return tmp;
    }
}

第三种情况

方法范型可以是任意类型,由形参范型确定

class A {
    public <T> T test(List<T> t) {
        List<T> tmp = t;
        return tmp.get(0);
    }
}

第四种情况

方法范型只能是** B 类型及其子类型**,由形参范型确定

class A {
    public <T extends B> T test(List<T> t) {
        List<T> tmp = t;
        return tmp.get(0);
    }
}

引用范型通配符

引用范型通配符指的是在引用处指定范型范围,所谓引用处可以是属性静态属性局部变量方法形参,下面以局部变量为例。

class A {
    private static class Some<T> {
        public T t;

        public void set(T t) {
            T tmp = t;
            this.t = tmp;
        }

        public T get() {
            return t;
        }
    }

    private static class B extends A {
    }

    private static class C extends B {
    }
}

第一种情况

这种情况引用直接确定了范型类型,其中Some some3 = new Some()默认是 Object 类型。

Some<B> some1 = new Some<>();
Some<Object> some2 = new Some<>();
Some some3 = new Some();

第二种情况

这种情况引用允许任意类型,这里我们传入 B 范型的 Some 对象,set 方法失效get 方法返回 Object
原理:<?>代表某种确定类型,但是不知道具体是什么类型。因此,set 方法没有办法传入任何对象,而 get 方法只能返回 Object 类型

Some<?> some4 = new Some<B>();
Object object = some4.get();

第三种情况

这种情况引用允许 B 类型及其子类型,这里我们传入 B 范型的 Some 对象和 C 范型的 Some 对象,set 方法失效get 方法返回 B 类型
原理:<? extends B>代表某种确定类型,我们只知道这种类型是 B 类型及其子类型,但是不知道具体是什么类型。因此,set 方法没有办法传入任何对象,而由于我们能够确定 get 方法返回的一定是 B 类型及其子类型,所以可以确定为 B(可能存在向上转型)。

Some<? extends B> some5 = new Some<B>();
Some<? extends B> some6 = new Some<C>();
B b1 = some5.get();
B b2 = some6.get();

第四种情况

这种情况引用允许 B 类型及其父类型,这里我们传入 B 范型的 Some 对象和 A 范型的 Some 对象,set 方法可以传入 B 类型及其子类型get 方法返回 Object
原理:<? super B>代表某种确定类型,我们只知道这种类型是 B 类型及其父类型,但是不知道具体是什么类型。因此,set 方法可以传入 B 类型及其子类型(可能存在向上转型),而 get 方法只能返回 Object 类型

Some<? super B> some7 = new Some<B>();
Some<? super B> some8 = new Some<A>();
some7.set(new B());
some7.set(new C());
some8.set(new B());
some8.set(new C());
Object object1 = some7.get();
Object object2 = some8.get();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值