java 泛型

导读

文章主要有三段

  • 泛型类初始化介绍
  • 通配符
  • 擦除
    如果你是急性子可以直接跳过本段
    下面代码有#号标识处有三处语法错误,如果你对此没有任何疑问,那么本文可能无法带给你更多知识。
public class GenericTest {
    static class A{}
    static class B extends A{}
    static class C{}

    public static void main(String[] args) {

        List none = new ArrayList();
        List<A> listA = new ArrayList<>();
        List<? extends A> listOextendsA = new ArrayList<>();
        List<?> listO = new ArrayList<>();

        ArrayList<?>[] a = new ArrayList<?>[5];
        ArrayList<A>[] b = new ArrayList[5];

        //使用测试
        none.add(new B());                  // #1
        listA.add(new B());                 // #2
        listOextendsA.add(new B());         // #3
        listO.add(new B());                 // #4

        //赋值测试
        listOextendsA = new ArrayList<C>(); // #5
        listOextendsA = new ArrayList<B>(); // #6
        a[0] = new ArrayList<A>();          // #7
        b[0] = new ArrayList<A>();          // #8
        none = new ArrayList<Object>();     // #9
    }
}

泛型类初始化介绍

泛型类声明可以分为五个档位。

  1. 直接声明不加任何修饰 List list
    JAVA中不强制泛型类必须使用泛型,但是默认会给没有指定泛型声明的对象默认加上 < object > , 所以不声明等于声明为Object
//例子
List none = new ArrayList();
none.add("1");    // 正确
none.add(1);      // 正确

List<Object> none1 = new ArrayList<>();
none1.add("1");    // 正确
none1.add(1);     // 正确
  1. 直接指定类型 List< String > list
    直接指明类型的泛型类, 只能使用指定类型,不能使用包括子类在内的任何类型
//例子  继代码片段一 B extends A
List<A> listA = new ArrayList<>();
listOextendsA.add(new B());         // 错误
listOextendsA.add(new A());         // 正确
  1. 范围指定 List< ? extends String> list;
    ?提供泛型占位,必须通过带有具体类型指明的声明才能使用。本例中 向下兼容,通过? 和 extends 指定范围,接受指定类与子类 的【初始化】
//例子    继代码片段一 B extends A
List<? extends A> listOextendsA = new ArrayList<>();
listOextendsA = new ArrayList<B>()    // 正确
listOextendsA.add(new A());           // 错误
  1. 范围指定 List< ? super String> list;
    ?提供泛型占位,必须通过带有具体类型指明的声明才能使用。本例中 向上兼容,通过? 和 super 指定范围,接受指定类与父类 的【初始化】
//例子    继代码片段一 B extends A
List<? extends B> listOextendsA = new ArrayList<>();
listOextendsA = new ArrayList<A>()    // 正确
listOextendsA.add(new A());           // 正确
  1. 通配符?指定 List< ?> list;
    ?提供泛型占位,必须通过带有具体类型指明的声明才能使用。 本例中?可以初始化任何类型。
//例子
List<? extends B> listOextendsA = new ArrayList<>();
listOextendsA.add(new A());           // 错误
listOextendsA = new ArrayList<A>()    // 正确
listOextendsA.add(new A());           // 正确
listOextendsA = new ArrayList<B>()    // 正确
listOextendsA.add(new A());           // 错误

通配符

  • 什么是通配符

    通配符“?”在泛型中有不可替代的特殊性。 通配符可以表示任何类型,但又不是任何一个具体类型。在 List< ? > list = new List< ? >(); 中,初始化了一个泛型List,但是编译器并不明确这是一个什么类型的泛型(不明确的类型,不等于new List() 因为直接声明会默认为Object类型),所以这个对象是不能直接使用的。 试想一下编译器声明了一个自己都不知道类型的泛型类,估计内心已经慌得一B。。

  • 通配符的用处
    1 做边界限定,在前面例子中已经使用。
    2 泛型占位,声明我是一个泛型(没有具体类型的泛型), 在我们可能遇见场景有以下场景, 更多用法需要大家一起创造。

    // 代码片段
   interface TestA{
        List<?> outList();
    }

    class TestB implements  TestA{
        @Override
        public List<?> outList() {
            return new ArrayList<String>();
        }
    }

    class TestC implements  TestA{
        @Override
        public List<?> outList() {
            return new ArrayList<Integer>();
        }
    }

擦除

  • 证明擦除的存在
    不知道你们有没有发现一些问题比如:
    # 1
    public static void main(String[] args) {
        System.out.println(new ArrayList<String>().getClass());
    }
    //输出结果 class java.util.ArrayList

    # 2
    public static void main(String[] args) {
        System.out.println(new ArrayList<String>() instanceof  ArrayList<Integer>());
    }
    // 语法错误
种种迹象表明擦除确实存在,并给我们带来一些困惑。擦除是JAVA语言实现泛型的折中之法,是JAVA团队在参考C++之后设计出的新特性, 而擦除则是为了兼容。

- 擦除会给我们带来什么
1,无法在泛型类中直接获取泛型的类型
2,在某些情况下泛型无法在编译器无法给予明确的类型警告(数组给出了鄙视)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值