侧边栏壁纸
博主头像
素秋云博主等级

行动起来,活在当下

  • 累计撰写 11 篇文章
  • 累计创建 15 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

关于泛型你能说出个所以然吗

素秋云
2023-11-16 / 0 评论 / 0 点赞 / 23 阅读 / 4372 字

泛型概念

泛型其实就是将类型参数化(即把要操作的数据类型当做一个参数),这样我们就可以在编译时就类,方法,接口的数据类型规定好了,减少了过多的向下转型,程序更加安全了。更通俗的讲,那垃圾分类举例子,一个垃圾桶,厂家生产的时候并没有给它规定,它里面只能放什么垃圾,这时的垃圾桶可以放任何垃圾,当我们确定了他只能放有害垃圾时,我们就给了他一个标签,他就只能放有害垃圾,其他的不行。

以我们的代码为例,就是如果我们需要在一个list中存放String类型的元素,就可以使用泛型,如果放入非String类型的数据,就会编译报错如下所以。

public class test {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        //list.add(1); 编译出错,不能放入int类型
    }
}

泛型的标记:E、T、K、V、N

  • E:在集合中使用,表示集合中存放的元素

  • T:表示Java类,所有的基本类和自定义的类

  • K:表示键(Key)

  • V:表示值(Value)

  • N:表示数值类型(Number)

  • ?:表示不明确的类型

泛型上限、下限的限定

  • 泛型上限限定:< ? extends T>

用通配符?和关键字extends来规定泛型的上限,我们知道extends是继承的关键字,这里表示通配符?代表的类型是T的子类或者子接口

泛型下限限定:< ? super T>

用通配符?和关键字super来规定泛型的下限,在方法中super代表着父类,这里表示通配符?代表的类型是T的父类或者父接口

泛型类(在类上定义类型)

public class Person<T> {
    private T t;
    public T getT() {
        return t;
    }
    public void setT(T t) {
        this.t = t;
    }
}

我们看下测试方法,person1对象实例的set方法泛型设置的String类型,放入18时编译报错。person2对象实例的set方法设置为Integer类型放入18则不报错。

泛型接口(在接口上定义类型)

public interface demo<T> {//泛型接口
  void test(T t);
}

public class demoImpl implements demo<String>{//清楚接口类型
    @Override
    public void test(String s) {
        System.out.println(s);
    }
}

public class demoImpl<T> implements demo<T>{//不清楚类型
    @Override
    public void test(T t) {
        System.out.println(t);
    }
}

泛型方法(在方法参数上定义类型)

public class test {
    public static void main(String[] args) {
        Person<Integer> person = new Person<>();
         person.setT(1);
        test(1,2,3,4);
        test("a","b","c","d");
    }
    public static <T> void test(T ... tArray ){
        for (T t : tArray) {
            System.out.print(t);
        }
    }
}

泛型擦除

使用泛型时加上的类型参数,会被编译器在编译时去掉,这个过程就是泛型擦除。所以泛型主要用于编译阶段,编译后生成的class文件并没有泛型中的类型信息。

举个体现泛型擦除的例子,一目了然。

在编译前,list2是无法赋值给list的,因为此时的存在泛型的类型信息,list存放的String类型数据,list2存放的Integer类型,所以相互之间无法赋值。

public class test {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();
        list.add("a");
        ArrayList<Integer> list2 = new ArrayList<Integer>();
        list2.add(1);
        System.out.println(list.getClass() == list2.getClass()); //输出:true
    }
}

删除赋值,查看编译之后的对象,果然相等,说明编译之后泛型的类型信息被擦除了。

0

评论区